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