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