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