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