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