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