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