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