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