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