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