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