(compilation-parse-errors):
[emacs.git] / lwlib / lwlib.c
blobf71f6ef6d57751306c896415800e64ad07cf1736
1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifdef NeXT
22 #undef __STRICT_BSD__ /* ick */
23 #endif
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include "lwlib-int.h"
29 #include "lwlib-utils.h"
30 #include <X11/StringDefs.h>
32 #ifdef __osf__
33 #include <string.h>
34 #include <stdlib.h>
35 extern long *xmalloc();
36 #endif
38 #if defined (USE_LUCID)
39 #include "lwlib-Xlw.h"
40 #endif
41 #if defined (USE_MOTIF)
42 #include "lwlib-Xm.h"
43 #else /* not USE_MOTIF */
44 #if defined (USE_LUCID)
45 #define USE_XAW
46 #endif /* not USE_MOTIF && USE_LUCID */
47 #endif
48 #if defined (USE_OLIT)
49 #include "lwlib-Xol.h"
50 #endif
51 #if defined (USE_XAW)
52 #include "lwlib-Xaw.h"
53 #endif
55 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
56 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
57 #endif
59 #if defined (USE_MOTIF) && defined (USE_OLIT)
60 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
61 #endif
63 #ifndef max
64 #define max(x, y) ((x) > (y) ? (x) : (y))
65 #endif
67 /* List of all widgets managed by the library. */
68 static widget_info*
69 all_widget_info = NULL;
71 #ifdef USE_MOTIF
72 char *lwlib_toolkit_type = "motif";
73 #else
74 char *lwlib_toolkit_type = "lucid";
75 #endif
76 \f/* Forward declarations */
77 static void
78 instantiate_widget_instance (/* widget_instance* instance */);
80 lwlib_memset (address, value, length)
81 char *address;
82 int value;
83 int length;
85 int i;
87 for (i = 0; i < length; i++)
88 address[i] = value;
91 lwlib_bcopy (from, to, length)
92 char *from;
93 char *to;
94 int length;
96 int i;
98 for (i = 0; i < length; i++)
99 to[i] = from[i];
101 \f/* utility functions for widget_instance and widget_info */
102 char *
103 safe_strdup (s)
104 char *s;
106 char *result;
107 if (! s) return 0;
108 result = (char *) malloc (strlen (s) + 1);
109 if (! result)
110 return 0;
111 strcpy (result, s);
112 return result;
115 /* Like strcmp but ignore differences in case. */
117 static int
118 my_strcasecmp (s1, s2)
119 char *s1, *s2;
121 while (1)
123 int c1 = *s1++;
124 int c2 = *s2++;
125 if (isupper (c1))
126 c1 = tolower (c1);
127 if (isupper (c2))
128 c2 = tolower (c2);
129 if (c1 != c2)
130 return (c1 > c2 ? 1 : -1);
131 if (c1 == 0)
132 return 0;
136 static void
137 safe_free_str (s)
138 char *s;
140 if (s) free (s);
143 static widget_value *widget_value_free_list = 0;
144 static int malloc_cpt = 0;
146 widget_value *
147 malloc_widget_value ()
149 widget_value *wv;
150 if (widget_value_free_list)
152 wv = widget_value_free_list;
153 widget_value_free_list = wv->free_list;
154 wv->free_list = 0;
156 else
158 wv = (widget_value *) malloc (sizeof (widget_value));
159 malloc_cpt++;
161 lwlib_memset (wv, 0, sizeof (widget_value));
162 return wv;
165 /* this is analogous to free(). It frees only what was allocated
166 by malloc_widget_value(), and no substructures.
168 void
169 free_widget_value (wv)
170 widget_value *wv;
172 if (wv->free_list)
173 abort ();
175 if (malloc_cpt > 25)
177 /* When the number of already allocated cells is too big,
178 We free it. */
179 free (wv);
180 malloc_cpt--;
182 else
184 wv->free_list = widget_value_free_list;
185 widget_value_free_list = wv;
189 static void
190 free_widget_value_tree (wv)
191 widget_value *wv;
193 if (!wv)
194 return;
196 if (wv->name) free (wv->name);
197 if (wv->value) free (wv->value);
198 if (wv->key) free (wv->key);
200 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
202 if (wv->toolkit_data && wv->free_toolkit_data)
204 XtFree (wv->toolkit_data);
205 wv->toolkit_data = (void *) 0xDEADBEEF;
208 if (wv->contents && (wv->contents != (widget_value*)1))
210 free_widget_value_tree (wv->contents);
211 wv->contents = (widget_value *) 0xDEADBEEF;
213 if (wv->next)
215 free_widget_value_tree (wv->next);
216 wv->next = (widget_value *) 0xDEADBEEF;
218 free_widget_value (wv);
221 static widget_value *
222 copy_widget_value_tree (val, change)
223 widget_value* val;
224 change_type change;
226 widget_value* copy;
228 if (!val)
229 return NULL;
230 if (val == (widget_value *) 1)
231 return val;
233 copy = malloc_widget_value ();
234 copy->name = safe_strdup (val->name);
235 copy->value = safe_strdup (val->value);
236 copy->key = safe_strdup (val->key);
237 copy->enabled = val->enabled;
238 copy->selected = val->selected;
239 copy->edited = False;
240 copy->change = change;
241 copy->contents = copy_widget_value_tree (val->contents, change);
242 copy->call_data = val->call_data;
243 copy->next = copy_widget_value_tree (val->next, change);
244 copy->toolkit_data = NULL;
245 copy->free_toolkit_data = False;
246 return copy;
249 static widget_info *
250 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
251 char* type;
252 char* name;
253 LWLIB_ID id;
254 widget_value* val;
255 lw_callback pre_activate_cb;
256 lw_callback selection_cb;
257 lw_callback post_activate_cb;
259 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
260 info->type = safe_strdup (type);
261 info->name = safe_strdup (name);
262 info->id = id;
263 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
264 info->busy = False;
265 info->pre_activate_cb = pre_activate_cb;
266 info->selection_cb = selection_cb;
267 info->post_activate_cb = post_activate_cb;
268 info->instances = NULL;
270 info->next = all_widget_info;
271 all_widget_info = info;
273 return info;
276 static void
277 free_widget_info (info)
278 widget_info* info;
280 safe_free_str (info->type);
281 safe_free_str (info->name);
282 free_widget_value_tree (info->val);
283 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
284 free (info);
287 static void
288 mark_widget_destroyed (widget, closure, call_data)
289 Widget widget;
290 XtPointer closure;
291 XtPointer call_data;
293 widget_instance* instance = (widget_instance*)closure;
295 /* be very conservative */
296 if (instance->widget == widget)
297 instance->widget = NULL;
300 static widget_instance *
301 allocate_widget_instance (info, parent, pop_up_p)
302 widget_info* info;
303 Widget parent;
304 Boolean pop_up_p;
306 widget_instance* instance =
307 (widget_instance*)malloc (sizeof (widget_instance));
308 instance->parent = parent;
309 instance->pop_up_p = pop_up_p;
310 instance->info = info;
311 instance->next = info->instances;
312 info->instances = instance;
314 instantiate_widget_instance (instance);
316 XtAddCallback (instance->widget, XtNdestroyCallback,
317 mark_widget_destroyed, (XtPointer)instance);
318 return instance;
321 static void
322 free_widget_instance (instance)
323 widget_instance* instance;
325 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
326 free (instance);
329 static widget_info *
330 get_widget_info (id, remove_p)
331 LWLIB_ID id;
332 Boolean remove_p;
334 widget_info* info;
335 widget_info* prev;
336 for (prev = NULL, info = all_widget_info;
337 info;
338 prev = info, info = info->next)
339 if (info->id == id)
341 if (remove_p)
343 if (prev)
344 prev->next = info->next;
345 else
346 all_widget_info = info->next;
348 return info;
350 return NULL;
353 /* Internal function used by the library dependent implementation to get the
354 widget_value for a given widget in an instance */
355 widget_info *
356 lw_get_widget_info (id)
357 LWLIB_ID id;
359 return get_widget_info (id, 0);
362 static widget_instance *
363 get_widget_instance (widget, remove_p)
364 Widget widget;
365 Boolean remove_p;
367 widget_info* info;
368 widget_instance* instance;
369 widget_instance* prev;
370 for (info = all_widget_info; info; info = info->next)
371 for (prev = NULL, instance = info->instances;
372 instance;
373 prev = instance, instance = instance->next)
374 if (instance->widget == widget)
376 if (remove_p)
378 if (prev)
379 prev->next = instance->next;
380 else
381 info->instances = instance->next;
383 return instance;
385 return (widget_instance *) 0;
388 static widget_instance*
389 find_instance (id, parent, pop_up_p)
390 LWLIB_ID id;
391 Widget parent;
392 Boolean pop_up_p;
394 widget_info* info = get_widget_info (id, False);
395 widget_instance* instance;
397 if (info)
398 for (instance = info->instances; instance; instance = instance->next)
399 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
400 return instance;
402 return NULL;
406 /* utility function for widget_value */
407 static Boolean
408 safe_strcmp (s1, s2)
409 char* s1;
410 char* s2;
412 if (!!s1 ^ !!s2) return True;
413 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
417 #if 0
418 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
419 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
420 name, \
421 (oc == NO_CHANGE ? "none" : \
422 (oc == INVISIBLE_CHANGE ? "invisible" : \
423 (oc == VISIBLE_CHANGE ? "visible" : \
424 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
425 oc, \
426 (nc == NO_CHANGE ? "none" : \
427 (nc == INVISIBLE_CHANGE ? "invisible" : \
428 (nc == VISIBLE_CHANGE ? "visible" : \
429 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
430 nc, desc, a1, a2)
431 #else
432 # define EXPLAIN(name, oc, nc, desc, a1, a2)
433 #endif
436 static widget_value *
437 merge_widget_value (val1, val2, level)
438 widget_value* val1;
439 widget_value* val2;
440 int level;
442 change_type change;
443 widget_value* merged_next;
444 widget_value* merged_contents;
446 if (!val1)
448 if (val2)
449 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
450 else
451 return NULL;
453 if (!val2)
455 free_widget_value_tree (val1);
456 return NULL;
459 change = NO_CHANGE;
461 if (safe_strcmp (val1->name, val2->name))
463 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
464 val1->name, val2->name);
465 change = max (change, STRUCTURAL_CHANGE);
466 safe_free_str (val1->name);
467 val1->name = safe_strdup (val2->name);
469 if (safe_strcmp (val1->value, val2->value))
471 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
472 val1->value, val2->value);
473 change = max (change, VISIBLE_CHANGE);
474 safe_free_str (val1->value);
475 val1->value = safe_strdup (val2->value);
477 if (safe_strcmp (val1->key, val2->key))
479 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
480 val1->key, val2->key);
481 change = max (change, VISIBLE_CHANGE);
482 safe_free_str (val1->key);
483 val1->key = safe_strdup (val2->key);
485 if (val1->enabled != val2->enabled)
487 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
488 val1->enabled, val2->enabled);
489 change = max (change, VISIBLE_CHANGE);
490 val1->enabled = val2->enabled;
492 if (val1->selected != val2->selected)
494 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
495 val1->selected, val2->selected);
496 change = max (change, VISIBLE_CHANGE);
497 val1->selected = val2->selected;
499 if (val1->call_data != val2->call_data)
501 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
502 val1->call_data, val2->call_data);
503 change = max (change, INVISIBLE_CHANGE);
504 val1->call_data = val2->call_data;
507 if (level > 0)
509 merged_contents =
510 merge_widget_value (val1->contents, val2->contents, level - 1);
512 if (val1->contents && !merged_contents)
514 /* This used to say INVISIBLE_CHANGE,
515 but it is visible and vitally important when
516 the contents of the menu bar itself are entirely deleted.
518 But maybe it doesn't matter. This fails to fix the bug. */
519 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
520 0, 0);
521 change = max (change, STRUCTURAL_CHANGE);
523 else if (merged_contents && merged_contents->change != NO_CHANGE)
525 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
526 0, 0);
527 change = max (change, INVISIBLE_CHANGE);
530 val1->contents = merged_contents;
533 merged_next = merge_widget_value (val1->next, val2->next, level);
535 if (val1->next && !merged_next)
537 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
538 0, 0);
539 change = max (change, STRUCTURAL_CHANGE);
541 else if (merged_next)
543 if (merged_next->change)
544 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
545 0, 0);
546 change = max (change, merged_next->change);
549 val1->next = merged_next;
551 val1->change = change;
553 if (change > NO_CHANGE && val1->toolkit_data)
555 if (val1->free_toolkit_data)
556 XtFree (val1->toolkit_data);
557 val1->toolkit_data = NULL;
560 return val1;
564 /* modifying the widgets */
565 static Widget
566 name_to_widget (instance, name)
567 widget_instance* instance;
568 char* name;
570 Widget widget = NULL;
572 if (!instance->widget)
573 return NULL;
575 if (!strcmp (XtName (instance->widget), name))
576 widget = instance->widget;
577 else
579 int length = strlen (name) + 2;
580 char* real_name = (char *) xmalloc (length);
581 real_name [0] = '*';
582 strcpy (real_name + 1, name);
584 widget = XtNameToWidget (instance->widget, real_name);
586 free (real_name);
588 return widget;
591 static void
592 set_one_value (instance, val, deep_p)
593 widget_instance* instance;
594 widget_value* val;
595 Boolean deep_p;
597 Widget widget = name_to_widget (instance, val->name);
599 if (widget)
601 #if defined (USE_LUCID)
602 if (lw_lucid_widget_p (instance->widget))
603 xlw_update_one_widget (instance, widget, val, deep_p);
604 #endif
605 #if defined (USE_MOTIF)
606 if (lw_motif_widget_p (instance->widget))
607 xm_update_one_widget (instance, widget, val, deep_p);
608 #endif
609 #if defined (USE_OLIT)
610 if (lw_olit_widget_p (instance->widget))
611 xol_update_one_widget (instance, widget, val, deep_p);
612 #endif
613 #if defined (USE_XAW)
614 if (lw_xaw_widget_p (instance->widget))
615 xaw_update_one_widget (instance, widget, val, deep_p);
616 #endif
620 static void
621 update_one_widget_instance (instance, deep_p)
622 widget_instance* instance;
623 Boolean deep_p;
625 widget_value *val;
627 if (!instance->widget)
628 /* the widget was destroyed */
629 return;
631 for (val = instance->info->val; val; val = val->next)
632 if (val->change != NO_CHANGE)
633 set_one_value (instance, val, deep_p);
636 static void
637 update_all_widget_values (info, deep_p)
638 widget_info* info;
639 Boolean deep_p;
641 widget_instance* instance;
642 widget_value* val;
644 for (instance = info->instances; instance; instance = instance->next)
645 update_one_widget_instance (instance, deep_p);
647 for (val = info->val; val; val = val->next)
648 val->change = NO_CHANGE;
651 void
652 lw_modify_all_widgets (id, val, deep_p)
653 LWLIB_ID id;
654 widget_value* val;
655 Boolean deep_p;
657 widget_info* info = get_widget_info (id, False);
658 widget_value* new_val;
659 widget_value* next_new_val;
660 widget_value* cur;
661 widget_value* prev;
662 widget_value* next;
663 int found;
665 if (!info)
666 return;
668 for (new_val = val; new_val; new_val = new_val->next)
670 next_new_val = new_val->next;
671 new_val->next = NULL;
672 found = False;
673 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
674 if (!strcmp (cur->name, new_val->name))
676 found = True;
677 next = cur->next;
678 cur->next = NULL;
679 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
680 if (prev)
681 prev->next = cur ? cur : next;
682 else
683 info->val = cur ? cur : next;
684 if (cur)
685 cur->next = next;
686 break;
688 if (!found)
690 /* Could not find it, add it */
691 if (prev)
692 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
693 else
694 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
696 new_val->next = next_new_val;
699 update_all_widget_values (info, deep_p);
703 /* creating the widgets */
705 static void
706 initialize_widget_instance (instance)
707 widget_instance* instance;
709 widget_value* val;
711 for (val = instance->info->val; val; val = val->next)
712 val->change = STRUCTURAL_CHANGE;
714 update_one_widget_instance (instance, True);
716 for (val = instance->info->val; val; val = val->next)
717 val->change = NO_CHANGE;
721 static widget_creation_function
722 find_in_table (type, table)
723 char* type;
724 widget_creation_entry* table;
726 widget_creation_entry* cur;
727 for (cur = table; cur->type; cur++)
728 if (!my_strcasecmp (type, cur->type))
729 return cur->function;
730 return NULL;
733 static Boolean
734 dialog_spec_p (name)
735 char* name;
737 /* return True if name matches [EILPQeilpq][1-9][Bb] or
738 [EILPQeilpq][1-9][Bb][Rr][1-9] */
739 if (!name)
740 return False;
742 switch (name [0])
744 case 'E': case 'I': case 'L': case 'P': case 'Q':
745 case 'e': case 'i': case 'l': case 'p': case 'q':
746 if (name [1] >= '0' && name [1] <= '9')
748 if (name [2] != 'B' && name [2] != 'b')
749 return False;
750 if (!name [3])
751 return True;
752 if ((name [3] == 'T' || name [3] == 't') && !name [4])
753 return True;
754 if ((name [3] == 'R' || name [3] == 'r')
755 && name [4] >= '0' && name [4] <= '9' && !name [5])
756 return True;
757 return False;
759 else
760 return False;
762 default:
763 return False;
767 static void
768 instantiate_widget_instance (instance)
769 widget_instance* instance;
771 widget_creation_function function = NULL;
773 #if defined (USE_LUCID)
774 if (!function)
775 function = find_in_table (instance->info->type, xlw_creation_table);
776 #endif
777 #if defined(USE_MOTIF)
778 if (!function)
779 function = find_in_table (instance->info->type, xm_creation_table);
780 #endif
781 #if defined (USE_OLIT)
782 if (!function)
783 function = find_in_table (instance->info->type, xol_creation_table);
784 #endif
785 #if defined (USE_XAW)
786 if (!function)
787 function = find_in_table (instance->info->type, xaw_creation_table);
788 #endif
790 if (!function)
792 if (dialog_spec_p (instance->info->type))
794 #if defined (USE_LUCID)
795 /* not yet */
796 #endif
797 #if defined(USE_MOTIF)
798 if (!function)
799 function = xm_create_dialog;
800 #endif
801 #if defined (USE_XAW)
802 if (!function)
803 function = xaw_create_dialog;
804 #endif
805 #if defined (USE_OLIT)
806 /* not yet */
807 #endif
811 if (!function)
813 printf ("No creation function for widget type %s\n",
814 instance->info->type);
815 abort ();
818 instance->widget = (*function) (instance);
820 if (!instance->widget)
821 abort ();
823 /* XtRealizeWidget (instance->widget);*/
826 void
827 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
828 char* type;
829 char* name;
830 LWLIB_ID id;
831 widget_value* val;
832 lw_callback pre_activate_cb;
833 lw_callback selection_cb;
834 lw_callback post_activate_cb;
836 if (!get_widget_info (id, False))
837 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
838 post_activate_cb);
841 Widget
842 lw_get_widget (id, parent, pop_up_p)
843 LWLIB_ID id;
844 Widget parent;
845 Boolean pop_up_p;
847 widget_instance* instance;
849 instance = find_instance (id, parent, pop_up_p);
850 return instance ? instance->widget : NULL;
853 Widget
854 lw_make_widget (id, parent, pop_up_p)
855 LWLIB_ID id;
856 Widget parent;
857 Boolean pop_up_p;
859 widget_instance* instance;
860 widget_info* info;
862 instance = find_instance (id, parent, pop_up_p);
863 if (!instance)
865 info = get_widget_info (id, False);
866 if (!info)
867 return NULL;
868 instance = allocate_widget_instance (info, parent, pop_up_p);
869 initialize_widget_instance (instance);
871 if (!instance->widget)
872 abort ();
873 return instance->widget;
876 Widget
877 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
878 char* type;
879 char* name;
880 LWLIB_ID id;
881 widget_value* val;
882 Widget parent;
883 Boolean pop_up_p;
884 lw_callback pre_activate_cb;
885 lw_callback selection_cb;
886 lw_callback post_activate_cb;
888 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
889 post_activate_cb);
890 return lw_make_widget (id, parent, pop_up_p);
894 /* destroying the widgets */
895 static void
896 destroy_one_instance (instance)
897 widget_instance* instance;
899 /* Remove the destroy callback on the widget; that callback will try to
900 dereference the instance object (to set its widget slot to 0, since the
901 widget is dead.) Since the instance is now dead, we don't have to worry
902 about the fact that its widget is dead too.
904 This happens in the Phase2Destroy of the widget, so this callback would
905 not have been run until arbitrarily long after the instance was freed.
907 if (instance->widget)
908 XtRemoveCallback (instance->widget, XtNdestroyCallback,
909 mark_widget_destroyed, (XtPointer)instance);
911 if (instance->widget)
913 /* The else are pretty tricky here, including the empty statement
914 at the end because it would be very bad to destroy a widget
915 twice. */
916 #if defined (USE_LUCID)
917 if (lw_lucid_widget_p (instance->widget))
918 xlw_destroy_instance (instance);
919 else
920 #endif
921 #if defined (USE_MOTIF)
922 if (lw_motif_widget_p (instance->widget))
923 xm_destroy_instance (instance);
924 else
925 #endif
926 #if defined (USE_OLIT)
927 if (lw_olit_widget_p (instance->widget))
928 xol_destroy_instance (instance);
929 else
930 #endif
931 #if defined (USE_XAW)
932 if (lw_xaw_widget_p (instance->widget))
933 xaw_destroy_instance (instance);
934 else
935 #endif
936 /* do not remove the empty statement */
940 free_widget_instance (instance);
943 void
944 lw_destroy_widget (w)
945 Widget w;
947 widget_instance* instance = get_widget_instance (w, True);
949 if (instance)
951 widget_info *info = instance->info;
952 /* instance has already been removed from the list; free it */
953 destroy_one_instance (instance);
954 /* if there are no instances left, free the info too */
955 if (!info->instances)
956 lw_destroy_all_widgets (info->id);
960 void
961 lw_destroy_all_widgets (id)
962 LWLIB_ID id;
964 widget_info* info = get_widget_info (id, True);
965 widget_instance* instance;
966 widget_instance* next;
968 if (info)
970 for (instance = info->instances; instance; )
972 next = instance->next;
973 destroy_one_instance (instance);
974 instance = next;
976 free_widget_info (info);
980 void
981 lw_destroy_everything ()
983 while (all_widget_info)
984 lw_destroy_all_widgets (all_widget_info->id);
987 void
988 lw_destroy_all_pop_ups ()
990 widget_info* info;
991 widget_info* next;
992 widget_instance* instance;
994 for (info = all_widget_info; info; info = next)
996 next = info->next;
997 instance = info->instances;
998 if (instance && instance->pop_up_p)
999 lw_destroy_all_widgets (info->id);
1003 #ifdef USE_MOTIF
1004 extern Widget first_child (/* Widget */); /* garbage */
1005 #endif
1007 Widget
1008 lw_raise_all_pop_up_widgets ()
1010 widget_info* info;
1011 widget_instance* instance;
1012 Widget result = NULL;
1014 for (info = all_widget_info; info; info = info->next)
1015 for (instance = info->instances; instance; instance = instance->next)
1016 if (instance->pop_up_p)
1018 Widget widget = instance->widget;
1019 if (widget)
1021 if (XtIsManaged (widget)
1022 #ifdef USE_MOTIF
1023 /* What a complete load of crap!!!!
1024 When a dialogShell is on the screen, it is not managed!
1026 || (lw_motif_widget_p (instance->widget) &&
1027 XtIsManaged (first_child (widget)))
1028 #endif
1031 if (!result)
1032 result = widget;
1033 XMapRaised (XtDisplay (widget), XtWindow (widget));
1037 return result;
1040 static void
1041 lw_pop_all_widgets (id, up)
1042 LWLIB_ID id;
1043 Boolean up;
1045 widget_info* info = get_widget_info (id, False);
1046 widget_instance* instance;
1048 if (info)
1049 for (instance = info->instances; instance; instance = instance->next)
1050 if (instance->pop_up_p && instance->widget)
1052 #if defined (USE_LUCID)
1053 if (lw_lucid_widget_p (instance->widget))
1055 XtRealizeWidget (instance->widget);
1056 xlw_pop_instance (instance, up);
1058 #endif
1059 #if defined (USE_MOTIF)
1060 if (lw_motif_widget_p (instance->widget))
1062 XtRealizeWidget (instance->widget);
1063 xm_pop_instance (instance, up);
1065 #endif
1066 #if defined (USE_OLIT)
1067 if (lw_olit_widget_p (instance->widget))
1069 XtRealizeWidget (instance->widget);
1070 xol_pop_instance (instance, up);
1072 #endif
1073 #if defined (USE_XAW)
1074 if (lw_xaw_widget_p (instance->widget))
1076 XtRealizeWidget (XtParent (instance->widget));
1077 XtRealizeWidget (instance->widget);
1078 xaw_pop_instance (instance, up);
1080 #endif
1084 void
1085 lw_pop_up_all_widgets (id)
1086 LWLIB_ID id;
1088 lw_pop_all_widgets (id, True);
1091 void
1092 lw_pop_down_all_widgets (id)
1093 LWLIB_ID id;
1095 lw_pop_all_widgets (id, False);
1098 void
1099 lw_popup_menu (widget, event)
1100 Widget widget;
1101 XEvent *event;
1103 #if defined (USE_LUCID)
1104 if (lw_lucid_widget_p (widget))
1105 xlw_popup_menu (widget, event);
1106 #endif
1107 #if defined (USE_MOTIF)
1108 if (lw_motif_widget_p (widget))
1109 xm_popup_menu (widget, event);
1110 #endif
1111 #if defined (USE_OLIT)
1112 if (lw_olit_widget_p (widget))
1113 xol_popup_menu (widget, event);
1114 #endif
1115 #if defined (USE_XAW)
1116 if (lw_xaw_widget_p (widget))
1117 xaw_popup_menu (widget, event);
1118 #endif
1121 \f/* get the values back */
1122 static Boolean
1123 get_one_value (instance, val)
1124 widget_instance* instance;
1125 widget_value* val;
1127 Widget widget = name_to_widget (instance, val->name);
1129 if (widget)
1131 #if defined (USE_LUCID)
1132 if (lw_lucid_widget_p (instance->widget))
1133 xlw_update_one_value (instance, widget, val);
1134 #endif
1135 #if defined (USE_MOTIF)
1136 if (lw_motif_widget_p (instance->widget))
1137 xm_update_one_value (instance, widget, val);
1138 #endif
1139 #if defined (USE_OLIT)
1140 if (lw_olit_widget_p (instance->widget))
1141 xol_update_one_value (instance, widget, val);
1142 #endif
1143 #if defined (USE_XAW)
1144 if (lw_xaw_widget_p (instance->widget))
1145 xaw_update_one_value (instance, widget, val);
1146 #endif
1147 return True;
1149 else
1150 return False;
1153 Boolean
1154 lw_get_some_values (id, val_out)
1155 LWLIB_ID id;
1156 widget_value* val_out;
1158 widget_info* info = get_widget_info (id, False);
1159 widget_instance* instance;
1160 widget_value* val;
1161 Boolean result = False;
1163 if (!info)
1164 return False;
1166 instance = info->instances;
1167 if (!instance)
1168 return False;
1170 for (val = val_out; val; val = val->next)
1171 if (get_one_value (instance, val))
1172 result = True;
1174 return result;
1177 widget_value*
1178 lw_get_all_values (id)
1179 LWLIB_ID id;
1181 widget_info* info = get_widget_info (id, False);
1182 widget_value* val = info->val;
1183 if (lw_get_some_values (id, val))
1184 return val;
1185 else
1186 return NULL;
1189 /* internal function used by the library dependent implementation to get the
1190 widget_value for a given widget in an instance */
1191 widget_value*
1192 lw_get_widget_value_for_widget (instance, w)
1193 widget_instance* instance;
1194 Widget w;
1196 char* name = XtName (w);
1197 widget_value* cur;
1198 for (cur = instance->info->val; cur; cur = cur->next)
1199 if (!strcmp (cur->name, name))
1200 return cur;
1201 return NULL;
1204 \f/* update other instances value when one thing changed */
1206 /* To forbid recursive calls */
1207 static Boolean lwlib_updating;
1209 /* This function can be used as a an XtCallback for the widgets that get
1210 modified to update other instances of the widgets. Closure should be the
1211 widget_instance. */
1212 void
1213 lw_internal_update_other_instances (widget, closure, call_data)
1214 Widget widget;
1215 XtPointer closure;
1216 XtPointer call_data;
1218 widget_instance* instance = (widget_instance*)closure;
1219 char* name = XtName (widget);
1220 widget_info* info;
1221 widget_instance* cur;
1222 widget_value* val;
1224 /* Avoid possibly infinite recursion. */
1225 if (lwlib_updating)
1226 return;
1228 /* protect against the widget being destroyed */
1229 if (XtWidgetBeingDestroyedP (widget))
1230 return;
1232 /* Return immediately if there are no other instances */
1233 info = instance->info;
1234 if (!info->instances->next)
1235 return;
1237 lwlib_updating = True;
1239 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1241 if (val && get_one_value (instance, val))
1242 for (cur = info->instances; cur; cur = cur->next)
1243 if (cur != instance)
1244 set_one_value (cur, val, True);
1246 lwlib_updating = False;
1250 \f/* get the id */
1252 LWLIB_ID
1253 lw_get_widget_id (w)
1254 Widget w;
1256 widget_instance* instance = get_widget_instance (w, False);
1258 return instance ? instance->info->id : 0;
1261 \f/* set the keyboard focus */
1262 void
1263 lw_set_keyboard_focus (parent, w)
1264 Widget parent;
1265 Widget w;
1267 #if defined (USE_MOTIF)
1268 xm_set_keyboard_focus (parent, w);
1269 #else
1270 XtSetKeyboardFocus (parent, w);
1271 #endif
1274 \f/* Show busy */
1275 static void
1276 show_one_widget_busy (w, flag)
1277 Widget w;
1278 Boolean flag;
1280 Pixel foreground = 0;
1281 Pixel background = 1;
1282 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1283 if (!widget_to_invert)
1284 widget_to_invert = w;
1286 XtVaGetValues (widget_to_invert,
1287 XtNforeground, &foreground,
1288 XtNbackground, &background,
1290 XtVaSetValues (widget_to_invert,
1291 XtNforeground, background,
1292 XtNbackground, foreground,
1296 void
1297 lw_show_busy (w, busy)
1298 Widget w;
1299 Boolean busy;
1301 widget_instance* instance = get_widget_instance (w, False);
1302 widget_info* info;
1303 widget_instance* next;
1305 if (instance)
1307 info = instance->info;
1308 if (info->busy != busy)
1310 for (next = info->instances; next; next = next->next)
1311 if (next->widget)
1312 show_one_widget_busy (next->widget, busy);
1313 info->busy = busy;
1318 /* This hack exists because Lucid/Athena need to execute the strange
1319 function below to support geometry management. */
1320 void
1321 lw_refigure_widget (w, doit)
1322 Widget w;
1323 Boolean doit;
1325 #if defined (USE_XAW)
1326 XawPanedSetRefigureMode (w, doit);
1327 #endif
1328 #if defined (USE_MOTIF)
1329 if (doit)
1330 XtManageChild (w);
1331 else
1332 XtUnmanageChild (w);
1333 #endif
1336 /* Toolkit independent way of determining if an event window is in the
1337 menubar. */
1338 Boolean
1339 lw_window_is_in_menubar (win, menubar_widget)
1340 Window win;
1341 Widget menubar_widget;
1343 return menubar_widget
1344 #if defined (USE_LUCID)
1345 && XtWindow (menubar_widget) == win;
1346 #endif
1347 #if defined (USE_MOTIF)
1348 && ((XtWindow (menubar_widget) == win)
1349 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1350 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1351 == menubar_widget)));
1352 #endif
1355 /* Motif hack to set the main window areas. */
1356 void
1357 lw_set_main_areas (parent, menubar, work_area)
1358 Widget parent;
1359 Widget menubar;
1360 Widget work_area;
1362 #if defined (USE_MOTIF)
1363 xm_set_main_areas (parent, menubar, work_area);
1364 #endif
1367 /* Manage resizing for Motif. This disables resizing when the menubar
1368 is about to be modified. */
1369 void
1370 lw_allow_resizing (w, flag)
1371 Widget w;
1372 Boolean flag;
1374 #if defined (USE_MOTIF)
1375 xm_manage_resizing (w, flag);
1376 #endif