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