Clean out last vestiges of the old HAVE_CONFIG_H stuff.
[bpt/emacs.git] / lwlib / lwlib.c
CommitLineData
07bf635f 1/* A general interface to the widgets of different toolkits.
67f02b82 2
4424d48a 3Copyright (C) 1992, 1993 Lucid, Inc.
acaf905b 4Copyright (C) 1994-1996, 1999-2012 Free Software Foundation, Inc.
07bf635f
RS
5
6This file is part of the Lucid Widget Library.
7
177c0ea7 8The Lucid Widget Library is free software; you can redistribute it and/or
07bf635f 9modify it under the terms of the GNU General Public License as published by
2aa86c0f 10the Free Software Foundation; either version 2, or (at your option)
07bf635f
RS
11any later version.
12
13The Lucid Widget Library is distributed in the hope that it will be useful,
177c0ea7 14but WITHOUT ANY WARRANTY; without even the implied warranty of
07bf635f
RS
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
20the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
07bf635f 22
0f0912e6 23#include <config.h>
0f0912e6 24
d7306fe6 25#include <setjmp.h>
67f02b82 26#include <lisp.h>
a3bf8a8c 27
07bf635f 28#include <sys/types.h>
07bf635f 29#include <stdio.h>
5f61736f 30#include <ctype.h>
e7818b5a 31#include "lwlib-int.h"
07bf635f 32#include "lwlib-utils.h"
01492d1b 33#include <X11/StringDefs.h>
07bf635f 34
07bf635f
RS
35#if defined (USE_LUCID)
36#include "lwlib-Xlw.h"
37#endif
38#if defined (USE_MOTIF)
39#include "lwlib-Xm.h"
ce5a08a1
FP
40#else /* not USE_MOTIF */
41#if defined (USE_LUCID)
42#define USE_XAW
43#endif /* not USE_MOTIF && USE_LUCID */
07bf635f 44#endif
9331cca8 45#if defined (USE_XAW)
5262c5c7
CY
46#ifdef HAVE_XAW3D
47#include <X11/Xaw3d/Paned.h>
48#else /* !HAVE_XAW3D */
cec17865 49#include <X11/Xaw/Paned.h>
5262c5c7 50#endif /* HAVE_XAW3D */
9331cca8
FP
51#include "lwlib-Xaw.h"
52#endif
07bf635f 53
db0e17de
DL
54#if !defined (USE_LUCID) && !defined (USE_MOTIF)
55 #error At least one of USE_LUCID or USE_MOTIF must be defined.
07bf635f
RS
56#endif
57
2af91681
PR
58#ifndef max
59#define max(x, y) ((x) > (y) ? (x) : (y))
60#endif
61
07bf635f
RS
62/* List of all widgets managed by the library. */
63static widget_info*
64all_widget_info = NULL;
65
99dcca2f 66#ifdef USE_MOTIF
a953c1e3 67const char *lwlib_toolkit_type = "motif";
99dcca2f 68#else
a953c1e3 69const char *lwlib_toolkit_type = "lucid";
99dcca2f 70#endif
07bf635f 71
f57e2426
J
72static widget_value *merge_widget_value (widget_value *,
73 widget_value *,
74 int, int *);
75static void instantiate_widget_instance (widget_instance *);
f57e2426
J
76static void safe_free_str (char *);
77static void free_widget_value_tree (widget_value *);
78static widget_value *copy_widget_value_tree (widget_value *,
79 change_type);
a953c1e3 80static widget_info *allocate_widget_info (const char *, const char *, LWLIB_ID,
f57e2426
J
81 widget_value *,
82 lw_callback, lw_callback,
83 lw_callback, lw_callback);
84static void free_widget_info (widget_info *);
85static void mark_widget_destroyed (Widget, XtPointer, XtPointer);
86static widget_instance *allocate_widget_instance (widget_info *,
87 Widget, Boolean);
88static void free_widget_instance (widget_instance *);
89static widget_info *get_widget_info (LWLIB_ID, Boolean);
90static widget_instance *get_widget_instance (Widget, Boolean);
91static widget_instance *find_instance (LWLIB_ID, Widget, Boolean);
d6dcbe70
DN
92static Boolean safe_strcmp (const char *, const char *);
93static Widget name_to_widget (widget_instance *, const char *);
f57e2426
J
94static void set_one_value (widget_instance *, widget_value *, Boolean);
95static void update_one_widget_instance (widget_instance *, Boolean);
96static void update_all_widget_values (widget_info *, Boolean);
97static void initialize_widget_instance (widget_instance *);
d6dcbe70
DN
98static widget_creation_function find_in_table (const char *, const widget_creation_entry *);
99static Boolean dialog_spec_p (const char *);
f57e2426
J
100static void destroy_one_instance (widget_instance *);
101static void lw_pop_all_widgets (LWLIB_ID, Boolean);
102static Boolean get_one_value (widget_instance *, widget_value *);
103static void show_one_widget_busy (Widget, Boolean);
07bf635f 104\f/* utility functions for widget_instance and widget_info */
bb2ee72b 105char *
c3174d16 106safe_strdup (const char *s)
07bf635f
RS
107{
108 char *result;
109 if (! s) return 0;
3370edca 110 result = (char *) xmalloc (strlen (s) + 1);
07bf635f
RS
111 strcpy (result, s);
112 return result;
113}
114
3511c784
DA
115#ifdef HAVE_STRCASECMP
116#define lwlib_strcasecmp(x,y) strcasecmp ((x), (y))
117#else
118
5f61736f
RS
119/* Like strcmp but ignore differences in case. */
120
121static int
3511c784 122lwlib_strcasecmp (const char *s1, const char *s2)
5f61736f
RS
123{
124 while (1)
125 {
126 int c1 = *s1++;
127 int c2 = *s2++;
128 if (isupper (c1))
129 c1 = tolower (c1);
130 if (isupper (c2))
131 c2 = tolower (c2);
132 if (c1 != c2)
133 return (c1 > c2 ? 1 : -1);
134 if (c1 == 0)
135 return 0;
136 }
137}
3511c784 138#endif /* HAVE_STRCASECMP */
5f61736f 139
07bf635f 140static void
c3174d16 141safe_free_str (char *s)
07bf635f 142{
81d40c92 143 xfree (s);
07bf635f
RS
144}
145
146static widget_value *widget_value_free_list = 0;
0b96f00b 147static int malloc_cpt = 0;
07bf635f
RS
148
149widget_value *
c3174d16 150malloc_widget_value (void)
07bf635f
RS
151{
152 widget_value *wv;
153 if (widget_value_free_list)
154 {
155 wv = widget_value_free_list;
156 widget_value_free_list = wv->free_list;
157 wv->free_list = 0;
158 }
159 else
160 {
3370edca 161 wv = (widget_value *) xmalloc (sizeof (widget_value));
0b96f00b 162 malloc_cpt++;
07bf635f 163 }
72af86bd 164 memset ((void*) wv, 0, sizeof (widget_value));
07bf635f
RS
165 return wv;
166}
167
7ef3956a 168/* this is analogous to free(). It frees only what was allocated
177c0ea7 169 by malloc_widget_value(), and no substructures.
07bf635f
RS
170 */
171void
c3174d16 172free_widget_value (widget_value *wv)
07bf635f
RS
173{
174 if (wv->free_list)
175 abort ();
0b96f00b 176
d2a5919f 177 if (malloc_cpt > 25)
0b96f00b
FP
178 {
179 /* When the number of already allocated cells is too big,
180 We free it. */
81d40c92 181 xfree (wv);
d2a5919f 182 malloc_cpt--;
0b96f00b
FP
183 }
184 else
185 {
186 wv->free_list = widget_value_free_list;
187 widget_value_free_list = wv;
188 }
07bf635f
RS
189}
190
191static void
c3174d16 192free_widget_value_tree (widget_value *wv)
07bf635f
RS
193{
194 if (!wv)
195 return;
196
81d40c92
DA
197 xfree (wv->name);
198 xfree (wv->value);
199 xfree (wv->key);
07bf635f 200
a3bf8a8c 201 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
07bf635f
RS
202
203 if (wv->toolkit_data && wv->free_toolkit_data)
204 {
53e28d2a 205 XtFree (wv->toolkit_data);
07bf635f
RS
206 wv->toolkit_data = (void *) 0xDEADBEEF;
207 }
208
209 if (wv->contents && (wv->contents != (widget_value*)1))
210 {
211 free_widget_value_tree (wv->contents);
212 wv->contents = (widget_value *) 0xDEADBEEF;
213 }
214 if (wv->next)
215 {
216 free_widget_value_tree (wv->next);
217 wv->next = (widget_value *) 0xDEADBEEF;
218 }
219 free_widget_value (wv);
220}
221
222static widget_value *
c3174d16 223copy_widget_value_tree (widget_value *val, change_type change)
07bf635f
RS
224{
225 widget_value* copy;
177c0ea7 226
07bf635f
RS
227 if (!val)
228 return NULL;
229 if (val == (widget_value *) 1)
230 return val;
231
232 copy = malloc_widget_value ();
233 copy->name = safe_strdup (val->name);
234 copy->value = safe_strdup (val->value);
235 copy->key = safe_strdup (val->key);
a3bf8a8c 236 copy->help = val->help;
07bf635f 237 copy->enabled = val->enabled;
da88f592 238 copy->button_type = val->button_type;
07bf635f
RS
239 copy->selected = val->selected;
240 copy->edited = False;
241 copy->change = change;
0c12a958 242 copy->this_one_change = change;
07bf635f
RS
243 copy->contents = copy_widget_value_tree (val->contents, change);
244 copy->call_data = val->call_data;
245 copy->next = copy_widget_value_tree (val->next, change);
246 copy->toolkit_data = NULL;
247 copy->free_toolkit_data = False;
248 return copy;
249}
250
251static widget_info *
a953c1e3
DN
252allocate_widget_info (const char* type,
253 const char* name,
c825c0b6
J
254 LWLIB_ID id,
255 widget_value* val,
256 lw_callback pre_activate_cb,
257 lw_callback selection_cb,
258 lw_callback post_activate_cb,
259 lw_callback highlight_cb)
07bf635f 260{
3370edca 261 widget_info* info = (widget_info*) xmalloc (sizeof (widget_info));
07bf635f
RS
262 info->type = safe_strdup (type);
263 info->name = safe_strdup (name);
264 info->id = id;
265 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
266 info->busy = False;
267 info->pre_activate_cb = pre_activate_cb;
268 info->selection_cb = selection_cb;
269 info->post_activate_cb = post_activate_cb;
02512b20 270 info->highlight_cb = highlight_cb;
07bf635f
RS
271 info->instances = NULL;
272
273 info->next = all_widget_info;
274 all_widget_info = info;
275
276 return info;
277}
278
279static void
c3174d16 280free_widget_info (widget_info *info)
07bf635f
RS
281{
282 safe_free_str (info->type);
283 safe_free_str (info->name);
284 free_widget_value_tree (info->val);
72af86bd 285 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
81d40c92 286 xfree (info);
07bf635f
RS
287}
288
289static void
c3174d16 290mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
07bf635f
RS
291{
292 widget_instance* instance = (widget_instance*)closure;
293
294 /* be very conservative */
295 if (instance->widget == widget)
296 instance->widget = NULL;
297}
298
299static widget_instance *
db0e17de 300allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
07bf635f
RS
301{
302 widget_instance* instance =
3370edca 303 (widget_instance*) xmalloc (sizeof (widget_instance));
72af86bd 304 memset (instance, 0, sizeof *instance);
07bf635f
RS
305 instance->parent = parent;
306 instance->pop_up_p = pop_up_p;
307 instance->info = info;
308 instance->next = info->instances;
309 info->instances = instance;
310
7ef3956a 311 instantiate_widget_instance (instance);
07bf635f
RS
312
313 XtAddCallback (instance->widget, XtNdestroyCallback,
314 mark_widget_destroyed, (XtPointer)instance);
315 return instance;
316}
317
318static void
c3174d16 319free_widget_instance (widget_instance *instance)
07bf635f 320{
72af86bd 321 memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
81d40c92 322 xfree (instance);
07bf635f
RS
323}
324
325static widget_info *
db0e17de 326get_widget_info (LWLIB_ID id, Boolean remove_p)
07bf635f
RS
327{
328 widget_info* info;
329 widget_info* prev;
330 for (prev = NULL, info = all_widget_info;
331 info;
332 prev = info, info = info->next)
333 if (info->id == id)
334 {
335 if (remove_p)
336 {
337 if (prev)
338 prev->next = info->next;
339 else
340 all_widget_info = info->next;
341 }
342 return info;
343 }
344 return NULL;
345}
346
9331cca8
FP
347/* Internal function used by the library dependent implementation to get the
348 widget_value for a given widget in an instance */
349widget_info *
c3174d16 350lw_get_widget_info (LWLIB_ID id)
9331cca8
FP
351{
352 return get_widget_info (id, 0);
353}
354
07bf635f 355static widget_instance *
db0e17de 356get_widget_instance (Widget widget, Boolean remove_p)
07bf635f
RS
357{
358 widget_info* info;
359 widget_instance* instance;
360 widget_instance* prev;
361 for (info = all_widget_info; info; info = info->next)
362 for (prev = NULL, instance = info->instances;
363 instance;
364 prev = instance, instance = instance->next)
365 if (instance->widget == widget)
366 {
367 if (remove_p)
368 {
369 if (prev)
370 prev->next = instance->next;
371 else
372 info->instances = instance->next;
373 }
374 return instance;
375 }
376 return (widget_instance *) 0;
377}
378
02512b20
GM
379/* Value is a pointer to the widget_instance corresponding to
380 WIDGET, or null if WIDGET is not a lwlib widget. */
381
382widget_instance *
c3174d16 383lw_get_widget_instance (Widget widget)
02512b20
GM
384{
385 return get_widget_instance (widget, False);
386}
387
07bf635f 388static widget_instance*
db0e17de 389find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
07bf635f
RS
390{
391 widget_info* info = get_widget_info (id, False);
392 widget_instance* instance;
393
394 if (info)
395 for (instance = info->instances; instance; instance = instance->next)
396 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
397 return instance;
398
399 return NULL;
400}
401
402\f
403/* utility function for widget_value */
404static Boolean
d6dcbe70 405safe_strcmp (const char *s1, const char *s2)
07bf635f
RS
406{
407 if (!!s1 ^ !!s2) return True;
408 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
409}
410
07bf635f
RS
411
412#if 0
413# define EXPLAIN(name, oc, nc, desc, a1, a2) \
414 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
415 name, \
416 (oc == NO_CHANGE ? "none" : \
417 (oc == INVISIBLE_CHANGE ? "invisible" : \
418 (oc == VISIBLE_CHANGE ? "visible" : \
419 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
420 oc, \
421 (nc == NO_CHANGE ? "none" : \
422 (nc == INVISIBLE_CHANGE ? "invisible" : \
423 (nc == VISIBLE_CHANGE ? "visible" : \
424 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
425 nc, desc, a1, a2)
426#else
9ac71959 427# define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
07bf635f
RS
428#endif
429
430
431static widget_value *
c825c0b6
J
432merge_widget_value (widget_value *val1,
433 widget_value *val2,
434 int level,
435 int *change_p)
07bf635f 436{
0c12a958 437 change_type change, this_one_change;
07bf635f
RS
438 widget_value* merged_next;
439 widget_value* merged_contents;
440
441 if (!val1)
442 {
443 if (val2)
a17063b5
GM
444 {
445 *change_p = 1;
446 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
447 }
07bf635f
RS
448 else
449 return NULL;
450 }
451 if (!val2)
452 {
a17063b5 453 *change_p = 1;
07bf635f
RS
454 free_widget_value_tree (val1);
455 return NULL;
456 }
177c0ea7 457
07bf635f
RS
458 change = NO_CHANGE;
459
460 if (safe_strcmp (val1->name, val2->name))
461 {
462 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
463 val1->name, val2->name);
464 change = max (change, STRUCTURAL_CHANGE);
465 safe_free_str (val1->name);
466 val1->name = safe_strdup (val2->name);
467 }
468 if (safe_strcmp (val1->value, val2->value))
469 {
470 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
471 val1->value, val2->value);
472 change = max (change, VISIBLE_CHANGE);
473 safe_free_str (val1->value);
474 val1->value = safe_strdup (val2->value);
475 }
476 if (safe_strcmp (val1->key, val2->key))
477 {
478 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
479 val1->key, val2->key);
480 change = max (change, VISIBLE_CHANGE);
481 safe_free_str (val1->key);
482 val1->key = safe_strdup (val2->key);
483 }
a3bf8a8c 484 if (! EQ (val1->help, val2->help))
02512b20
GM
485 {
486 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
487 val1->help, val2->help);
488 change = max (change, VISIBLE_CHANGE);
a3bf8a8c 489 val1->help = val2->help;
02512b20 490 }
07bf635f
RS
491 if (val1->enabled != val2->enabled)
492 {
493 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
494 val1->enabled, val2->enabled);
495 change = max (change, VISIBLE_CHANGE);
496 val1->enabled = val2->enabled;
497 }
da88f592
GM
498 if (val1->button_type != val2->button_type)
499 {
500 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
501 val1->button_type, val2->button_type);
502 change = max (change, VISIBLE_CHANGE);
503 val1->button_type = val2->button_type;
504 }
07bf635f
RS
505 if (val1->selected != val2->selected)
506 {
507 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
508 val1->selected, val2->selected);
509 change = max (change, VISIBLE_CHANGE);
510 val1->selected = val2->selected;
511 }
512 if (val1->call_data != val2->call_data)
513 {
514 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
515 val1->call_data, val2->call_data);
516 change = max (change, INVISIBLE_CHANGE);
517 val1->call_data = val2->call_data;
518 }
519
520 if (level > 0)
521 {
522 merged_contents =
a17063b5
GM
523 merge_widget_value (val1->contents, val2->contents, level - 1,
524 change_p);
177c0ea7 525
07bf635f
RS
526 if (val1->contents && !merged_contents)
527 {
7ef3956a
RS
528 /* This used to say INVISIBLE_CHANGE,
529 but it is visible and vitally important when
530 the contents of the menu bar itself are entirely deleted.
531
532 But maybe it doesn't matter. This fails to fix the bug. */
533 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
07bf635f 534 0, 0);
7ef3956a 535 change = max (change, STRUCTURAL_CHANGE);
07bf635f
RS
536 }
537 else if (merged_contents && merged_contents->change != NO_CHANGE)
538 {
539 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
540 0, 0);
541 change = max (change, INVISIBLE_CHANGE);
61069f2b 542#if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
2fe6d204
RS
543#ifdef USE_MOTIF
544 change = max (merged_contents->change, change);
61069f2b 545#endif
2fe6d204 546#endif
07bf635f 547 }
177c0ea7 548
07bf635f
RS
549 val1->contents = merged_contents;
550 }
551
0c12a958
RS
552 this_one_change = change;
553
a17063b5 554 merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
07bf635f
RS
555
556 if (val1->next && !merged_next)
557 {
558 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
559 0, 0);
560 change = max (change, STRUCTURAL_CHANGE);
561 }
562 else if (merged_next)
563 {
564 if (merged_next->change)
565 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
566 0, 0);
567 change = max (change, merged_next->change);
568 }
569
570 val1->next = merged_next;
571
0c12a958 572 val1->this_one_change = this_one_change;
07bf635f 573 val1->change = change;
177c0ea7 574
07bf635f
RS
575 if (change > NO_CHANGE && val1->toolkit_data)
576 {
a17063b5 577 *change_p = 1;
07bf635f 578 if (val1->free_toolkit_data)
53e28d2a 579 XtFree (val1->toolkit_data);
07bf635f
RS
580 val1->toolkit_data = NULL;
581 }
582
583 return val1;
584}
585
586\f
587/* modifying the widgets */
588static Widget
d6dcbe70 589name_to_widget (widget_instance *instance, const char *name)
07bf635f
RS
590{
591 Widget widget = NULL;
592
593 if (!instance->widget)
594 return NULL;
595
596 if (!strcmp (XtName (instance->widget), name))
597 widget = instance->widget;
598 else
599 {
600 int length = strlen (name) + 2;
f60044f5 601 char* real_name = (char *) xmalloc (length);
07bf635f
RS
602 real_name [0] = '*';
603 strcpy (real_name + 1, name);
177c0ea7 604
07bf635f 605 widget = XtNameToWidget (instance->widget, real_name);
f60044f5 606
81d40c92 607 xfree (real_name);
07bf635f
RS
608 }
609 return widget;
610}
611
612static void
db0e17de 613set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
07bf635f
RS
614{
615 Widget widget = name_to_widget (instance, val->name);
177c0ea7 616
07bf635f
RS
617 if (widget)
618 {
619#if defined (USE_LUCID)
620 if (lw_lucid_widget_p (instance->widget))
621 xlw_update_one_widget (instance, widget, val, deep_p);
622#endif
623#if defined (USE_MOTIF)
624 if (lw_motif_widget_p (instance->widget))
625 xm_update_one_widget (instance, widget, val, deep_p);
626#endif
9331cca8
FP
627#if defined (USE_XAW)
628 if (lw_xaw_widget_p (instance->widget))
629 xaw_update_one_widget (instance, widget, val, deep_p);
07bf635f
RS
630#endif
631 }
632}
633
634static void
db0e17de 635update_one_widget_instance (widget_instance* instance, Boolean deep_p)
07bf635f
RS
636{
637 widget_value *val;
638
639 if (!instance->widget)
640 /* the widget was destroyed */
641 return;
642
643 for (val = instance->info->val; val; val = val->next)
644 if (val->change != NO_CHANGE)
645 set_one_value (instance, val, deep_p);
646}
647
648static void
db0e17de 649update_all_widget_values (widget_info* info, Boolean deep_p)
07bf635f
RS
650{
651 widget_instance* instance;
652 widget_value* val;
653
654 for (instance = info->instances; instance; instance = instance->next)
655 update_one_widget_instance (instance, deep_p);
656
657 for (val = info->val; val; val = val->next)
658 val->change = NO_CHANGE;
659}
660
a17063b5 661int
db0e17de 662lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
07bf635f
RS
663{
664 widget_info* info = get_widget_info (id, False);
665 widget_value* new_val;
666 widget_value* next_new_val;
667 widget_value* cur;
668 widget_value* prev;
669 widget_value* next;
670 int found;
a17063b5 671 int change_p = 0;
07bf635f
RS
672
673 if (!info)
fdc4d3cd 674 return 0;
07bf635f
RS
675
676 for (new_val = val; new_val; new_val = new_val->next)
677 {
678 next_new_val = new_val->next;
679 new_val->next = NULL;
680 found = False;
681 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
682 if (!strcmp (cur->name, new_val->name))
683 {
684 found = True;
685 next = cur->next;
686 cur->next = NULL;
a17063b5
GM
687 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
688 &change_p);
07bf635f
RS
689 if (prev)
690 prev->next = cur ? cur : next;
691 else
692 info->val = cur ? cur : next;
693 if (cur)
694 cur->next = next;
695 break;
696 }
697 if (!found)
698 {
699 /* Could not find it, add it */
700 if (prev)
701 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
702 else
703 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
a17063b5 704 change_p = 1;
07bf635f
RS
705 }
706 new_val->next = next_new_val;
707 }
708
709 update_all_widget_values (info, deep_p);
a17063b5 710 return change_p;
07bf635f
RS
711}
712
713\f
714/* creating the widgets */
715
716static void
c3174d16 717initialize_widget_instance (widget_instance *instance)
07bf635f
RS
718{
719 widget_value* val;
720
721 for (val = instance->info->val; val; val = val->next)
722 val->change = STRUCTURAL_CHANGE;
723
724 update_one_widget_instance (instance, True);
725
726 for (val = instance->info->val; val; val = val->next)
727 val->change = NO_CHANGE;
728}
729
730
731static widget_creation_function
d6dcbe70 732find_in_table (const char *type, const widget_creation_entry *table)
07bf635f 733{
d6dcbe70 734 const widget_creation_entry* cur;
07bf635f 735 for (cur = table; cur->type; cur++)
3511c784 736 if (!lwlib_strcasecmp (type, cur->type))
07bf635f
RS
737 return cur->function;
738 return NULL;
739}
740
741static Boolean
d6dcbe70 742dialog_spec_p (const char *name)
07bf635f 743{
177c0ea7 744 /* return True if name matches [EILPQeilpq][1-9][Bb] or
07bf635f
RS
745 [EILPQeilpq][1-9][Bb][Rr][1-9] */
746 if (!name)
747 return False;
177c0ea7 748
07bf635f
RS
749 switch (name [0])
750 {
751 case 'E': case 'I': case 'L': case 'P': case 'Q':
752 case 'e': case 'i': case 'l': case 'p': case 'q':
753 if (name [1] >= '0' && name [1] <= '9')
754 {
755 if (name [2] != 'B' && name [2] != 'b')
756 return False;
757 if (!name [3])
758 return True;
759 if ((name [3] == 'T' || name [3] == 't') && !name [4])
760 return True;
761 if ((name [3] == 'R' || name [3] == 'r')
762 && name [4] >= '0' && name [4] <= '9' && !name [5])
763 return True;
764 return False;
765 }
766 else
767 return False;
177c0ea7 768
07bf635f
RS
769 default:
770 return False;
771 }
772}
773
774static void
c3174d16 775instantiate_widget_instance (widget_instance *instance)
07bf635f
RS
776{
777 widget_creation_function function = NULL;
778
779#if defined (USE_LUCID)
780 if (!function)
781 function = find_in_table (instance->info->type, xlw_creation_table);
782#endif
783#if defined(USE_MOTIF)
784 if (!function)
785 function = find_in_table (instance->info->type, xm_creation_table);
786#endif
9331cca8
FP
787#if defined (USE_XAW)
788 if (!function)
789 function = find_in_table (instance->info->type, xaw_creation_table);
790#endif
07bf635f
RS
791
792 if (!function)
793 {
794 if (dialog_spec_p (instance->info->type))
795 {
796#if defined (USE_LUCID)
797 /* not yet */
798#endif
799#if defined(USE_MOTIF)
800 if (!function)
801 function = xm_create_dialog;
802#endif
9331cca8
FP
803#if defined (USE_XAW)
804 if (!function)
805 function = xaw_create_dialog;
07bf635f
RS
806#endif
807 }
808 }
177c0ea7 809
07bf635f
RS
810 if (!function)
811 {
812 printf ("No creation function for widget type %s\n",
813 instance->info->type);
814 abort ();
815 }
816
817 instance->widget = (*function) (instance);
818
819 if (!instance->widget)
820 abort ();
821
822 /* XtRealizeWidget (instance->widget);*/
823}
824
177c0ea7 825void
a953c1e3
DN
826lw_register_widget (const char* type,
827 const char* name,
c825c0b6
J
828 LWLIB_ID id,
829 widget_value* val,
830 lw_callback pre_activate_cb,
831 lw_callback selection_cb,
832 lw_callback post_activate_cb,
833 lw_callback highlight_cb)
07bf635f
RS
834{
835 if (!get_widget_info (id, False))
836 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
02512b20 837 post_activate_cb, highlight_cb);
07bf635f
RS
838}
839
840Widget
db0e17de 841lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
07bf635f
RS
842{
843 widget_instance* instance;
177c0ea7 844
07bf635f
RS
845 instance = find_instance (id, parent, pop_up_p);
846 return instance ? instance->widget : NULL;
847}
848
849Widget
db0e17de 850lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
07bf635f
RS
851{
852 widget_instance* instance;
853 widget_info* info;
177c0ea7 854
07bf635f
RS
855 instance = find_instance (id, parent, pop_up_p);
856 if (!instance)
857 {
858 info = get_widget_info (id, False);
859 if (!info)
860 return NULL;
861 instance = allocate_widget_instance (info, parent, pop_up_p);
862 initialize_widget_instance (instance);
863 }
864 if (!instance->widget)
865 abort ();
866 return instance->widget;
867}
868
869Widget
a953c1e3 870lw_create_widget (const char* type, const char* name, LWLIB_ID id, widget_value* val,
db0e17de
DL
871 Widget parent, Boolean pop_up_p,
872 lw_callback pre_activate_cb, lw_callback selection_cb,
873 lw_callback post_activate_cb, lw_callback highlight_cb)
07bf635f
RS
874{
875 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
02512b20 876 post_activate_cb, highlight_cb);
07bf635f
RS
877 return lw_make_widget (id, parent, pop_up_p);
878}
177c0ea7 879
07bf635f
RS
880\f
881/* destroying the widgets */
882static void
c3174d16 883destroy_one_instance (widget_instance *instance)
07bf635f
RS
884{
885 /* Remove the destroy callback on the widget; that callback will try to
886 dereference the instance object (to set its widget slot to 0, since the
887 widget is dead.) Since the instance is now dead, we don't have to worry
888 about the fact that its widget is dead too.
889
890 This happens in the Phase2Destroy of the widget, so this callback would
891 not have been run until arbitrarily long after the instance was freed.
892 */
893 if (instance->widget)
894 XtRemoveCallback (instance->widget, XtNdestroyCallback,
895 mark_widget_destroyed, (XtPointer)instance);
896
897 if (instance->widget)
898 {
899 /* The else are pretty tricky here, including the empty statement
900 at the end because it would be very bad to destroy a widget
901 twice. */
902#if defined (USE_LUCID)
903 if (lw_lucid_widget_p (instance->widget))
904 xlw_destroy_instance (instance);
905 else
906#endif
907#if defined (USE_MOTIF)
908 if (lw_motif_widget_p (instance->widget))
909 xm_destroy_instance (instance);
910 else
911#endif
9331cca8
FP
912#if defined (USE_XAW)
913 if (lw_xaw_widget_p (instance->widget))
914 xaw_destroy_instance (instance);
177c0ea7 915 else
07bf635f 916#endif
9ac71959
PE
917 {
918 /* Empty compound statement to terminate if-then-else chain. */
919 }
07bf635f
RS
920 }
921
922 free_widget_instance (instance);
923}
924
925void
c3174d16 926lw_destroy_widget (Widget w)
07bf635f
RS
927{
928 widget_instance* instance = get_widget_instance (w, True);
177c0ea7 929
07bf635f
RS
930 if (instance)
931 {
932 widget_info *info = instance->info;
933 /* instance has already been removed from the list; free it */
934 destroy_one_instance (instance);
935 /* if there are no instances left, free the info too */
936 if (!info->instances)
937 lw_destroy_all_widgets (info->id);
938 }
939}
940
941void
c3174d16 942lw_destroy_all_widgets (LWLIB_ID id)
07bf635f
RS
943{
944 widget_info* info = get_widget_info (id, True);
945 widget_instance* instance;
946 widget_instance* next;
947
948 if (info)
949 {
950 for (instance = info->instances; instance; )
951 {
952 next = instance->next;
953 destroy_one_instance (instance);
954 instance = next;
955 }
956 free_widget_info (info);
957 }
958}
959
960void
c3174d16 961lw_destroy_everything (void)
07bf635f
RS
962{
963 while (all_widget_info)
964 lw_destroy_all_widgets (all_widget_info->id);
965}
966
967void
c3174d16 968lw_destroy_all_pop_ups (void)
07bf635f
RS
969{
970 widget_info* info;
971 widget_info* next;
972 widget_instance* instance;
973
974 for (info = all_widget_info; info; info = next)
975 {
976 next = info->next;
977 instance = info->instances;
978 if (instance && instance->pop_up_p)
979 lw_destroy_all_widgets (info->id);
980 }
981}
982
983#ifdef USE_MOTIF
748945cc 984extern Widget first_child (Widget); /* garbage */
07bf635f
RS
985#endif
986
987Widget
c3174d16 988lw_raise_all_pop_up_widgets (void)
07bf635f
RS
989{
990 widget_info* info;
991 widget_instance* instance;
992 Widget result = NULL;
993
994 for (info = all_widget_info; info; info = info->next)
995 for (instance = info->instances; instance; instance = instance->next)
996 if (instance->pop_up_p)
997 {
998 Widget widget = instance->widget;
999 if (widget)
1000 {
1001 if (XtIsManaged (widget)
1002#ifdef USE_MOTIF
1003 /* What a complete load of crap!!!!
1004 When a dialogShell is on the screen, it is not managed!
1005 */
1006 || (lw_motif_widget_p (instance->widget) &&
1007 XtIsManaged (first_child (widget)))
1008#endif
1009 )
1010 {
1011 if (!result)
1012 result = widget;
1013 XMapRaised (XtDisplay (widget), XtWindow (widget));
1014 }
1015 }
1016 }
1017 return result;
1018}
1019
1020static void
db0e17de 1021lw_pop_all_widgets (LWLIB_ID id, Boolean up)
07bf635f
RS
1022{
1023 widget_info* info = get_widget_info (id, False);
1024 widget_instance* instance;
1025
1026 if (info)
1027 for (instance = info->instances; instance; instance = instance->next)
1028 if (instance->pop_up_p && instance->widget)
1029 {
07bf635f
RS
1030#if defined (USE_LUCID)
1031 if (lw_lucid_widget_p (instance->widget))
9331cca8
FP
1032 {
1033 XtRealizeWidget (instance->widget);
1034 xlw_pop_instance (instance, up);
1035 }
07bf635f
RS
1036#endif
1037#if defined (USE_MOTIF)
1038 if (lw_motif_widget_p (instance->widget))
9331cca8
FP
1039 {
1040 XtRealizeWidget (instance->widget);
1041 xm_pop_instance (instance, up);
1042 }
07bf635f 1043#endif
9331cca8
FP
1044#if defined (USE_XAW)
1045 if (lw_xaw_widget_p (instance->widget))
1046 {
1047 XtRealizeWidget (XtParent (instance->widget));
1048 XtRealizeWidget (instance->widget);
1049 xaw_pop_instance (instance, up);
1050 }
07bf635f
RS
1051#endif
1052 }
1053}
1054
1055void
c3174d16 1056lw_pop_up_all_widgets (LWLIB_ID id)
07bf635f
RS
1057{
1058 lw_pop_all_widgets (id, True);
1059}
1060
1061void
c3174d16 1062lw_pop_down_all_widgets (LWLIB_ID id)
07bf635f
RS
1063{
1064 lw_pop_all_widgets (id, False);
1065}
1066
1067void
c3174d16 1068lw_popup_menu (Widget widget, XEvent *event)
07bf635f
RS
1069{
1070#if defined (USE_LUCID)
1071 if (lw_lucid_widget_p (widget))
5b3b31d6 1072 xlw_popup_menu (widget, event);
07bf635f
RS
1073#endif
1074#if defined (USE_MOTIF)
1075 if (lw_motif_widget_p (widget))
5b3b31d6 1076 xm_popup_menu (widget, event);
07bf635f 1077#endif
9331cca8
FP
1078#if defined (USE_XAW)
1079 if (lw_xaw_widget_p (widget))
5b3b31d6 1080 xaw_popup_menu (widget, event);
9331cca8 1081#endif
07bf635f
RS
1082}
1083
1084\f/* get the values back */
1085static Boolean
c3174d16 1086get_one_value (widget_instance *instance, widget_value *val)
07bf635f
RS
1087{
1088 Widget widget = name_to_widget (instance, val->name);
177c0ea7 1089
07bf635f
RS
1090 if (widget)
1091 {
1092#if defined (USE_LUCID)
1093 if (lw_lucid_widget_p (instance->widget))
1094 xlw_update_one_value (instance, widget, val);
1095#endif
1096#if defined (USE_MOTIF)
1097 if (lw_motif_widget_p (instance->widget))
1098 xm_update_one_value (instance, widget, val);
1099#endif
9331cca8
FP
1100#if defined (USE_XAW)
1101 if (lw_xaw_widget_p (instance->widget))
1102 xaw_update_one_value (instance, widget, val);
07bf635f
RS
1103#endif
1104 return True;
1105 }
1106 else
1107 return False;
1108}
1109
1110Boolean
c3174d16 1111lw_get_some_values (LWLIB_ID id, widget_value *val_out)
07bf635f
RS
1112{
1113 widget_info* info = get_widget_info (id, False);
1114 widget_instance* instance;
1115 widget_value* val;
1116 Boolean result = False;
1117
1118 if (!info)
1119 return False;
1120
1121 instance = info->instances;
1122 if (!instance)
1123 return False;
1124
1125 for (val = val_out; val; val = val->next)
1126 if (get_one_value (instance, val))
1127 result = True;
1128
1129 return result;
1130}
1131
1132widget_value*
c3174d16 1133lw_get_all_values (LWLIB_ID id)
07bf635f
RS
1134{
1135 widget_info* info = get_widget_info (id, False);
1136 widget_value* val = info->val;
1137 if (lw_get_some_values (id, val))
1138 return val;
1139 else
1140 return NULL;
1141}
1142
1143/* internal function used by the library dependent implementation to get the
1144 widget_value for a given widget in an instance */
1145widget_value*
c3174d16 1146lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
07bf635f
RS
1147{
1148 char* name = XtName (w);
1149 widget_value* cur;
1150 for (cur = instance->info->val; cur; cur = cur->next)
1151 if (!strcmp (cur->name, name))
1152 return cur;
1153 return NULL;
1154}
1155
1156\f/* update other instances value when one thing changed */
bd2c5b53
KH
1157
1158/* To forbid recursive calls */
1159static Boolean lwlib_updating;
1160
20db1522
JB
1161/* This function can be used as an XtCallback for the widgets that get
1162 modified to update other instances of the widgets. Closure should be the
1163 widget_instance. */
07bf635f 1164void
c825c0b6
J
1165lw_internal_update_other_instances (Widget widget,
1166 XtPointer closure,
1167 XtPointer call_data)
07bf635f 1168{
07bf635f
RS
1169 widget_instance* instance = (widget_instance*)closure;
1170 char* name = XtName (widget);
1171 widget_info* info;
1172 widget_instance* cur;
1173 widget_value* val;
1174
bd2c5b53
KH
1175 /* Avoid possibly infinite recursion. */
1176 if (lwlib_updating)
07bf635f
RS
1177 return;
1178
1179 /* protect against the widget being destroyed */
1180 if (XtWidgetBeingDestroyedP (widget))
1181 return;
1182
1183 /* Return immediately if there are no other instances */
1184 info = instance->info;
1185 if (!info->instances->next)
1186 return;
1187
bd2c5b53 1188 lwlib_updating = True;
07bf635f
RS
1189
1190 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1191
1192 if (val && get_one_value (instance, val))
1193 for (cur = info->instances; cur; cur = cur->next)
1194 if (cur != instance)
1195 set_one_value (cur, val, True);
1196
bd2c5b53 1197 lwlib_updating = False;
07bf635f
RS
1198}
1199
1200
1201\f/* get the id */
1202
1203LWLIB_ID
c3174d16 1204lw_get_widget_id (Widget w)
07bf635f
RS
1205{
1206 widget_instance* instance = get_widget_instance (w, False);
1207
1208 return instance ? instance->info->id : 0;
1209}
1210
1211\f/* set the keyboard focus */
1212void
c3174d16 1213lw_set_keyboard_focus (Widget parent, Widget w)
07bf635f
RS
1214{
1215#if defined (USE_MOTIF)
1216 xm_set_keyboard_focus (parent, w);
1217#else
1218 XtSetKeyboardFocus (parent, w);
1219#endif
1220}
1221
1222\f/* Show busy */
1223static void
db0e17de 1224show_one_widget_busy (Widget w, Boolean flag)
07bf635f
RS
1225{
1226 Pixel foreground = 0;
1227 Pixel background = 1;
1228 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1229 if (!widget_to_invert)
1230 widget_to_invert = w;
177c0ea7 1231
07bf635f
RS
1232 XtVaGetValues (widget_to_invert,
1233 XtNforeground, &foreground,
1234 XtNbackground, &background,
8dd095ee 1235 NULL);
07bf635f
RS
1236 XtVaSetValues (widget_to_invert,
1237 XtNforeground, background,
1238 XtNbackground, foreground,
8dd095ee 1239 NULL);
07bf635f
RS
1240}
1241
1242void
db0e17de 1243lw_show_busy (Widget w, Boolean busy)
07bf635f
RS
1244{
1245 widget_instance* instance = get_widget_instance (w, False);
1246 widget_info* info;
1247 widget_instance* next;
1248
1249 if (instance)
1250 {
1251 info = instance->info;
1252 if (info->busy != busy)
1253 {
1254 for (next = info->instances; next; next = next->next)
1255 if (next->widget)
1256 show_one_widget_busy (next->widget, busy);
1257 info->busy = busy;
1258 }
1259 }
1260}
2af91681
PR
1261
1262/* This hack exists because Lucid/Athena need to execute the strange
1263 function below to support geometry management. */
1264void
db0e17de 1265lw_refigure_widget (Widget w, Boolean doit)
2af91681 1266{
177c0ea7 1267#if defined (USE_XAW)
2af91681
PR
1268 XawPanedSetRefigureMode (w, doit);
1269#endif
1270#if defined (USE_MOTIF)
1271 if (doit)
2af91681 1272 XtManageChild (w);
a61155bc
RS
1273 else
1274 XtUnmanageChild (w);
2af91681
PR
1275#endif
1276}
1277
1278/* Toolkit independent way of determining if an event window is in the
1279 menubar. */
1280Boolean
c3174d16 1281lw_window_is_in_menubar (Window win, Widget menubar_widget)
2af91681
PR
1282{
1283 return menubar_widget
1284#if defined (USE_LUCID)
1285 && XtWindow (menubar_widget) == win;
1286#endif
1287#if defined (USE_MOTIF)
c17d59fc
RS
1288 && ((XtWindow (menubar_widget) == win)
1289 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1290 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1291 == menubar_widget)));
2af91681
PR
1292#endif
1293}
1294
1295/* Motif hack to set the main window areas. */
1296void
c3174d16 1297lw_set_main_areas (Widget parent, Widget menubar, Widget work_area)
2af91681
PR
1298{
1299#if defined (USE_MOTIF)
6618806e 1300 xm_set_main_areas (parent, menubar, work_area);
2af91681
PR
1301#endif
1302}
1303
1304/* Manage resizing for Motif. This disables resizing when the menubar
1305 is about to be modified. */
1306void
db0e17de 1307lw_allow_resizing (Widget w, Boolean flag)
2af91681
PR
1308{
1309#if defined (USE_MOTIF)
f78c5177 1310 xm_manage_resizing (w, flag);
2af91681
PR
1311#endif
1312}
da88f592
GM
1313
1314
1315/* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1316 set to an appropriate enumerator of type enum menu_separator.
1317 MOTIF_P non-zero means map separator types not supported by Motif
1318 to similar ones that are supported. */
1319
1320int
d6dcbe70 1321lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
da88f592 1322{
0f3360b0 1323 int separator_p = 0;
da88f592
GM
1324
1325 if (strlen (label) >= 3
72af86bd 1326 && memcmp (label, "--:", 3) == 0)
da88f592
GM
1327 {
1328 static struct separator_table
1329 {
a953c1e3 1330 const char *name;
da88f592
GM
1331 enum menu_separator type;
1332 }
1333 separator_names[] =
1334 {
4a5301d8
PJ
1335 {"space", SEPARATOR_NO_LINE},
1336 {"noLine", SEPARATOR_NO_LINE},
1337 {"singleLine", SEPARATOR_SINGLE_LINE},
1338 {"doubleLine", SEPARATOR_DOUBLE_LINE},
1339 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE},
1340 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE},
1341 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN},
1342 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT},
1343 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
1344 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
1345 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
1346 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
1347 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
1348 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
1349 {0,0}
da88f592
GM
1350 };
1351
1352 int i;
1353
1354 label += 3;
1355 for (i = 0; separator_names[i].name; ++i)
1356 if (strcmp (label, separator_names[i].name) == 0)
1357 {
1358 separator_p = 1;
1359 *type = separator_names[i].type;
1360
2af98732
GM
1361 /* If separator type is not supported under Motif,
1362 use a similar one. */
1363 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1364 *type -= 4;
1365 break;
1366 }
1367 }
1368 else if (strlen (label) > 3
72af86bd 1369 && memcmp (label, "--", 2) == 0
46d74a69 1370 && label[2] != '-')
2af98732
GM
1371 {
1372 /* Alternative, more Emacs-style names. */
1373 static struct separator_table
1374 {
a953c1e3 1375 const char *name;
2af98732
GM
1376 enum menu_separator type;
1377 }
1378 separator_names[] =
1379 {
4a5301d8
PJ
1380 {"space", SEPARATOR_NO_LINE},
1381 {"no-line", SEPARATOR_NO_LINE},
1382 {"single-line", SEPARATOR_SINGLE_LINE},
1383 {"double-line", SEPARATOR_DOUBLE_LINE},
1384 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE},
1385 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE},
1386 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN},
1387 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT},
1388 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
1389 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
1390 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
1391 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
1392 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
1393 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
1394 {0,0}
2af98732
GM
1395 };
1396
1397 int i;
1398
1399 label += 2;
1400 for (i = 0; separator_names[i].name; ++i)
1401 if (strcmp (label, separator_names[i].name) == 0)
1402 {
1403 separator_p = 1;
1404 *type = separator_names[i].type;
1405
da88f592
GM
1406 /* If separator type is not supported under Motif,
1407 use a similar one. */
1408 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1409 *type -= 4;
1410 break;
1411 }
1412 }
1413 else
1414 {
1415 /* Old-style separator, maybe. It's a separator if it contains
1416 only dashes. */
1417 while (*label == '-')
1418 ++label;
1419 separator_p = *label == 0;
1420 *type = SEPARATOR_SHADOW_ETCHED_IN;
1421 }
1422
1423 return separator_p;
1424}