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