(describe_map_tree): gcpro some things.
[emacs.git] / lwlib / lwlib.c
blob4e7e807f80d2e326ed8dae6334cc10794e42a4c2
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #ifdef NeXT
21 #undef __STRICT_BSD__ /* ick */
22 #endif
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include "lwlib-int.h"
31 #include "lwlib-utils.h"
32 #include <X11/StringDefs.h>
34 #if defined(__GNUC__) && !defined(alloca)
35 #define alloca __builtin_alloca
36 #endif
38 #if ((!__GNUC__) && !defined(__hpux)) && !defined(_AIX)
39 #include <alloca.h>
40 #endif
42 #if defined(_AIX)
43 #pragma alloca
44 #endif
46 #if defined (USE_LUCID)
47 #include "lwlib-Xlw.h"
48 #endif
49 #if defined (USE_MOTIF)
50 #include "lwlib-Xm.h"
51 #else /* not USE_MOTIF */
52 #if defined (USE_LUCID)
53 #define USE_XAW
54 #endif /* not USE_MOTIF && USE_LUCID */
55 #endif
56 #if defined (USE_OLIT)
57 #include "lwlib-Xol.h"
58 #endif
59 #if defined (USE_XAW)
60 #include "lwlib-Xaw.h"
61 #endif
63 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
64 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
65 #endif
67 #if defined (USE_MOTIF) && defined (USE_OLIT)
68 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
69 #endif
71 /* List of all widgets managed by the library. */
72 static widget_info*
73 all_widget_info = NULL;
75 \f/* Forward declarations */
76 static void
77 instanciate_widget_instance (/* widget_instance* instance */);
79 \f/* utility functions for widget_instance and widget_info */
80 static char *
81 safe_strdup (s)
82 char *s;
84 char *result;
85 if (! s) return 0;
86 result = (char *) malloc (strlen (s) + 1);
87 if (! result)
88 return 0;
89 strcpy (result, s);
90 return result;
93 /* Like strcmp but ignore differences in case. */
95 static int
96 my_strcasecmp (s1, s2)
97 char *s1, *s2;
99 while (1)
101 int c1 = *s1++;
102 int c2 = *s2++;
103 if (isupper (c1))
104 c1 = tolower (c1);
105 if (isupper (c2))
106 c2 = tolower (c2);
107 if (c1 != c2)
108 return (c1 > c2 ? 1 : -1);
109 if (c1 == 0)
110 return 0;
114 static void
115 safe_free_str (s)
116 char *s;
118 if (s) free (s);
121 static widget_value *widget_value_free_list = 0;
122 static int malloc_cpt = 0;
124 widget_value *
125 malloc_widget_value ()
127 widget_value *wv;
128 if (widget_value_free_list)
130 wv = widget_value_free_list;
131 widget_value_free_list = wv->free_list;
132 wv->free_list = 0;
134 else
136 wv = (widget_value *) malloc (sizeof (widget_value));
137 malloc_cpt++;
139 memset (wv, 0, sizeof (widget_value));
140 return wv;
143 /* this is analagous to free(). It frees only what was allocated
144 by malloc_widget_value(), and no substructures.
146 void
147 free_widget_value (wv)
148 widget_value *wv;
150 if (wv->free_list)
151 abort ();
153 if (malloc_cpt > 25)
155 /* When the number of already allocated cells is too big,
156 We free it. */
157 free (wv);
158 malloc_cpt--;
160 else
162 wv->free_list = widget_value_free_list;
163 widget_value_free_list = wv;
167 static void
168 free_widget_value_tree (wv)
169 widget_value *wv;
171 if (!wv)
172 return;
174 if (wv->name) free (wv->name);
175 if (wv->value) free (wv->value);
176 if (wv->key) free (wv->key);
178 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
180 if (wv->toolkit_data && wv->free_toolkit_data)
182 free (wv->toolkit_data);
183 wv->toolkit_data = (void *) 0xDEADBEEF;
186 if (wv->contents && (wv->contents != (widget_value*)1))
188 free_widget_value_tree (wv->contents);
189 wv->contents = (widget_value *) 0xDEADBEEF;
191 if (wv->next)
193 free_widget_value_tree (wv->next);
194 wv->next = (widget_value *) 0xDEADBEEF;
196 free_widget_value (wv);
199 static widget_value *
200 copy_widget_value_tree (val, change)
201 widget_value* val;
202 change_type change;
204 widget_value* copy;
206 if (!val)
207 return NULL;
208 if (val == (widget_value *) 1)
209 return val;
211 copy = malloc_widget_value ();
212 copy->name = safe_strdup (val->name);
213 copy->value = safe_strdup (val->value);
214 copy->key = safe_strdup (val->key);
215 copy->enabled = val->enabled;
216 copy->selected = val->selected;
217 copy->edited = False;
218 copy->change = change;
219 copy->contents = copy_widget_value_tree (val->contents, change);
220 copy->call_data = val->call_data;
221 copy->next = copy_widget_value_tree (val->next, change);
222 copy->toolkit_data = NULL;
223 copy->free_toolkit_data = False;
224 return copy;
227 static widget_info *
228 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
229 char* type;
230 char* name;
231 LWLIB_ID id;
232 widget_value* val;
233 lw_callback pre_activate_cb;
234 lw_callback selection_cb;
235 lw_callback post_activate_cb;
237 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
238 info->type = safe_strdup (type);
239 info->name = safe_strdup (name);
240 info->id = id;
241 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
242 info->busy = False;
243 info->pre_activate_cb = pre_activate_cb;
244 info->selection_cb = selection_cb;
245 info->post_activate_cb = post_activate_cb;
246 info->instances = NULL;
248 info->next = all_widget_info;
249 all_widget_info = info;
251 return info;
254 static void
255 free_widget_info (info)
256 widget_info* info;
258 safe_free_str (info->type);
259 safe_free_str (info->name);
260 free_widget_value_tree (info->val);
261 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
262 free (info);
265 static void
266 mark_widget_destroyed (widget, closure, call_data)
267 Widget widget;
268 XtPointer closure;
269 XtPointer call_data;
271 widget_instance* instance = (widget_instance*)closure;
273 /* be very conservative */
274 if (instance->widget == widget)
275 instance->widget = NULL;
278 static widget_instance *
279 allocate_widget_instance (info, parent, pop_up_p)
280 widget_info* info;
281 Widget parent;
282 Boolean pop_up_p;
284 widget_instance* instance =
285 (widget_instance*)malloc (sizeof (widget_instance));
286 instance->parent = parent;
287 instance->pop_up_p = pop_up_p;
288 instance->info = info;
289 instance->next = info->instances;
290 info->instances = instance;
292 instanciate_widget_instance (instance);
294 XtAddCallback (instance->widget, XtNdestroyCallback,
295 mark_widget_destroyed, (XtPointer)instance);
296 return instance;
299 static void
300 free_widget_instance (instance)
301 widget_instance* instance;
303 memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
304 free (instance);
307 static widget_info *
308 get_widget_info (id, remove_p)
309 LWLIB_ID id;
310 Boolean remove_p;
312 widget_info* info;
313 widget_info* prev;
314 for (prev = NULL, info = all_widget_info;
315 info;
316 prev = info, info = info->next)
317 if (info->id == id)
319 if (remove_p)
321 if (prev)
322 prev->next = info->next;
323 else
324 all_widget_info = info->next;
326 return info;
328 return NULL;
331 /* Internal function used by the library dependent implementation to get the
332 widget_value for a given widget in an instance */
333 widget_info *
334 lw_get_widget_info (id)
335 LWLIB_ID id;
337 return get_widget_info (id, 0);
340 static widget_instance *
341 get_widget_instance (widget, remove_p)
342 Widget widget;
343 Boolean remove_p;
345 widget_info* info;
346 widget_instance* instance;
347 widget_instance* prev;
348 for (info = all_widget_info; info; info = info->next)
349 for (prev = NULL, instance = info->instances;
350 instance;
351 prev = instance, instance = instance->next)
352 if (instance->widget == widget)
354 if (remove_p)
356 if (prev)
357 prev->next = instance->next;
358 else
359 info->instances = instance->next;
361 return instance;
363 return (widget_instance *) 0;
366 static widget_instance*
367 find_instance (id, parent, pop_up_p)
368 LWLIB_ID id;
369 Widget parent;
370 Boolean pop_up_p;
372 widget_info* info = get_widget_info (id, False);
373 widget_instance* instance;
375 if (info)
376 for (instance = info->instances; instance; instance = instance->next)
377 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
378 return instance;
380 return NULL;
384 /* utility function for widget_value */
385 static Boolean
386 safe_strcmp (s1, s2)
387 char* s1;
388 char* s2;
390 if (!!s1 ^ !!s2) return True;
391 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
394 static int
395 max (i1, i2)
396 int i1;
397 int i2;
399 return i1 > i2 ? i1 : i2;
403 #if 0
404 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
405 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
406 name, \
407 (oc == NO_CHANGE ? "none" : \
408 (oc == INVISIBLE_CHANGE ? "invisible" : \
409 (oc == VISIBLE_CHANGE ? "visible" : \
410 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
411 oc, \
412 (nc == NO_CHANGE ? "none" : \
413 (nc == INVISIBLE_CHANGE ? "invisible" : \
414 (nc == VISIBLE_CHANGE ? "visible" : \
415 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
416 nc, desc, a1, a2)
417 #else
418 # define EXPLAIN(name, oc, nc, desc, a1, a2)
419 #endif
422 static widget_value *
423 merge_widget_value (val1, val2, level)
424 widget_value* val1;
425 widget_value* val2;
426 int level;
428 change_type change;
429 widget_value* merged_next;
430 widget_value* merged_contents;
432 if (!val1)
434 if (val2)
435 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
436 else
437 return NULL;
439 if (!val2)
441 free_widget_value_tree (val1);
442 return NULL;
445 change = NO_CHANGE;
447 if (safe_strcmp (val1->name, val2->name))
449 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
450 val1->name, val2->name);
451 change = max (change, STRUCTURAL_CHANGE);
452 safe_free_str (val1->name);
453 val1->name = safe_strdup (val2->name);
455 if (safe_strcmp (val1->value, val2->value))
457 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
458 val1->value, val2->value);
459 change = max (change, VISIBLE_CHANGE);
460 safe_free_str (val1->value);
461 val1->value = safe_strdup (val2->value);
463 if (safe_strcmp (val1->key, val2->key))
465 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
466 val1->key, val2->key);
467 change = max (change, VISIBLE_CHANGE);
468 safe_free_str (val1->key);
469 val1->key = safe_strdup (val2->key);
471 if (val1->enabled != val2->enabled)
473 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
474 val1->enabled, val2->enabled);
475 change = max (change, VISIBLE_CHANGE);
476 val1->enabled = val2->enabled;
478 if (val1->selected != val2->selected)
480 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
481 val1->selected, val2->selected);
482 change = max (change, VISIBLE_CHANGE);
483 val1->selected = val2->selected;
485 if (val1->call_data != val2->call_data)
487 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
488 val1->call_data, val2->call_data);
489 change = max (change, INVISIBLE_CHANGE);
490 val1->call_data = val2->call_data;
493 if (level > 0)
495 merged_contents =
496 merge_widget_value (val1->contents, val2->contents, level - 1);
498 if (val1->contents && !merged_contents)
500 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
501 0, 0);
502 change = max (change, INVISIBLE_CHANGE);
504 else if (merged_contents && merged_contents->change != NO_CHANGE)
506 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
507 0, 0);
508 change = max (change, INVISIBLE_CHANGE);
511 val1->contents = merged_contents;
514 merged_next = merge_widget_value (val1->next, val2->next, level);
516 if (val1->next && !merged_next)
518 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
519 0, 0);
520 change = max (change, STRUCTURAL_CHANGE);
522 else if (merged_next)
524 if (merged_next->change)
525 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
526 0, 0);
527 change = max (change, merged_next->change);
530 val1->next = merged_next;
532 val1->change = change;
534 if (change > NO_CHANGE && val1->toolkit_data)
536 if (val1->free_toolkit_data)
537 free (val1->toolkit_data);
538 val1->toolkit_data = NULL;
541 return val1;
545 /* modifying the widgets */
546 static Widget
547 name_to_widget (instance, name)
548 widget_instance* instance;
549 char* name;
551 Widget widget = NULL;
553 if (!instance->widget)
554 return NULL;
556 if (!strcmp (XtName (instance->widget), name))
557 widget = instance->widget;
558 else
560 int length = strlen (name) + 2;
561 char* real_name = (char *) alloca (length);
562 real_name [0] = '*';
563 strcpy (real_name + 1, name);
565 widget = XtNameToWidget (instance->widget, real_name);
567 return widget;
570 static void
571 set_one_value (instance, val, deep_p)
572 widget_instance* instance;
573 widget_value* val;
574 Boolean deep_p;
576 Widget widget = name_to_widget (instance, val->name);
578 if (widget)
580 #if defined (USE_LUCID)
581 if (lw_lucid_widget_p (instance->widget))
582 xlw_update_one_widget (instance, widget, val, deep_p);
583 #endif
584 #if defined (USE_MOTIF)
585 if (lw_motif_widget_p (instance->widget))
586 xm_update_one_widget (instance, widget, val, deep_p);
587 #endif
588 #if defined (USE_OLIT)
589 if (lw_olit_widget_p (instance->widget))
590 xol_update_one_widget (instance, widget, val, deep_p);
591 #endif
592 #if defined (USE_XAW)
593 if (lw_xaw_widget_p (instance->widget))
594 xaw_update_one_widget (instance, widget, val, deep_p);
595 #endif
599 static void
600 update_one_widget_instance (instance, deep_p)
601 widget_instance* instance;
602 Boolean deep_p;
604 widget_value *val;
606 if (!instance->widget)
607 /* the widget was destroyed */
608 return;
610 for (val = instance->info->val; val; val = val->next)
611 if (val->change != NO_CHANGE)
612 set_one_value (instance, val, deep_p);
615 static void
616 update_all_widget_values (info, deep_p)
617 widget_info* info;
618 Boolean deep_p;
620 widget_instance* instance;
621 widget_value* val;
623 for (instance = info->instances; instance; instance = instance->next)
624 update_one_widget_instance (instance, deep_p);
626 for (val = info->val; val; val = val->next)
627 val->change = NO_CHANGE;
630 void
631 lw_modify_all_widgets (id, val, deep_p)
632 LWLIB_ID id;
633 widget_value* val;
634 Boolean deep_p;
636 widget_info* info = get_widget_info (id, False);
637 widget_value* new_val;
638 widget_value* next_new_val;
639 widget_value* cur;
640 widget_value* prev;
641 widget_value* next;
642 int found;
644 if (!info)
645 return;
647 for (new_val = val; new_val; new_val = new_val->next)
649 next_new_val = new_val->next;
650 new_val->next = NULL;
651 found = False;
652 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
653 if (!strcmp (cur->name, new_val->name))
655 found = True;
656 next = cur->next;
657 cur->next = NULL;
658 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
659 if (prev)
660 prev->next = cur ? cur : next;
661 else
662 info->val = cur ? cur : next;
663 if (cur)
664 cur->next = next;
665 break;
667 if (!found)
669 /* Could not find it, add it */
670 if (prev)
671 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
672 else
673 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
675 new_val->next = next_new_val;
678 update_all_widget_values (info, deep_p);
682 /* creating the widgets */
684 static void
685 initialize_widget_instance (instance)
686 widget_instance* instance;
688 widget_value* val;
690 for (val = instance->info->val; val; val = val->next)
691 val->change = STRUCTURAL_CHANGE;
693 update_one_widget_instance (instance, True);
695 for (val = instance->info->val; val; val = val->next)
696 val->change = NO_CHANGE;
700 static widget_creation_function
701 find_in_table (type, table)
702 char* type;
703 widget_creation_entry* table;
705 widget_creation_entry* cur;
706 for (cur = table; cur->type; cur++)
707 if (!my_strcasecmp (type, cur->type))
708 return cur->function;
709 return NULL;
712 static Boolean
713 dialog_spec_p (name)
714 char* name;
716 /* return True if name matches [EILPQeilpq][1-9][Bb] or
717 [EILPQeilpq][1-9][Bb][Rr][1-9] */
718 if (!name)
719 return False;
721 switch (name [0])
723 case 'E': case 'I': case 'L': case 'P': case 'Q':
724 case 'e': case 'i': case 'l': case 'p': case 'q':
725 if (name [1] >= '0' && name [1] <= '9')
727 if (name [2] != 'B' && name [2] != 'b')
728 return False;
729 if (!name [3])
730 return True;
731 if ((name [3] == 'T' || name [3] == 't') && !name [4])
732 return True;
733 if ((name [3] == 'R' || name [3] == 'r')
734 && name [4] >= '0' && name [4] <= '9' && !name [5])
735 return True;
736 return False;
738 else
739 return False;
741 default:
742 return False;
746 static void
747 instanciate_widget_instance (instance)
748 widget_instance* instance;
750 widget_creation_function function = NULL;
752 #if defined (USE_LUCID)
753 if (!function)
754 function = find_in_table (instance->info->type, xlw_creation_table);
755 #endif
756 #if defined(USE_MOTIF)
757 if (!function)
758 function = find_in_table (instance->info->type, xm_creation_table);
759 #endif
760 #if defined (USE_OLIT)
761 if (!function)
762 function = find_in_table (instance->info->type, xol_creation_table);
763 #endif
764 #if defined (USE_XAW)
765 if (!function)
766 function = find_in_table (instance->info->type, xaw_creation_table);
767 #endif
769 if (!function)
771 if (dialog_spec_p (instance->info->type))
773 #if defined (USE_LUCID)
774 /* not yet */
775 #endif
776 #if defined(USE_MOTIF)
777 if (!function)
778 function = xm_create_dialog;
779 #endif
780 #if defined (USE_XAW)
781 if (!function)
782 function = xaw_create_dialog;
783 #endif
784 #if defined (USE_OLIT)
785 /* not yet */
786 #endif
790 if (!function)
792 printf ("No creation function for widget type %s\n",
793 instance->info->type);
794 abort ();
797 instance->widget = (*function) (instance);
799 if (!instance->widget)
800 abort ();
802 /* XtRealizeWidget (instance->widget);*/
805 void
806 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
807 char* type;
808 char* name;
809 LWLIB_ID id;
810 widget_value* val;
811 lw_callback pre_activate_cb;
812 lw_callback selection_cb;
813 lw_callback post_activate_cb;
815 if (!get_widget_info (id, False))
816 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
817 post_activate_cb);
820 Widget
821 lw_get_widget (id, parent, pop_up_p)
822 LWLIB_ID id;
823 Widget parent;
824 Boolean pop_up_p;
826 widget_instance* instance;
828 instance = find_instance (id, parent, pop_up_p);
829 return instance ? instance->widget : NULL;
832 Widget
833 lw_make_widget (id, parent, pop_up_p)
834 LWLIB_ID id;
835 Widget parent;
836 Boolean pop_up_p;
838 widget_instance* instance;
839 widget_info* info;
841 instance = find_instance (id, parent, pop_up_p);
842 if (!instance)
844 info = get_widget_info (id, False);
845 if (!info)
846 return NULL;
847 instance = allocate_widget_instance (info, parent, pop_up_p);
848 initialize_widget_instance (instance);
850 if (!instance->widget)
851 abort ();
852 return instance->widget;
855 Widget
856 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
857 char* type;
858 char* name;
859 LWLIB_ID id;
860 widget_value* val;
861 Widget parent;
862 Boolean pop_up_p;
863 lw_callback pre_activate_cb;
864 lw_callback selection_cb;
865 lw_callback post_activate_cb;
867 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
868 post_activate_cb);
869 return lw_make_widget (id, parent, pop_up_p);
873 /* destroying the widgets */
874 static void
875 destroy_one_instance (instance)
876 widget_instance* instance;
878 /* Remove the destroy callback on the widget; that callback will try to
879 dereference the instance object (to set its widget slot to 0, since the
880 widget is dead.) Since the instance is now dead, we don't have to worry
881 about the fact that its widget is dead too.
883 This happens in the Phase2Destroy of the widget, so this callback would
884 not have been run until arbitrarily long after the instance was freed.
886 if (instance->widget)
887 XtRemoveCallback (instance->widget, XtNdestroyCallback,
888 mark_widget_destroyed, (XtPointer)instance);
890 if (instance->widget)
892 /* The else are pretty tricky here, including the empty statement
893 at the end because it would be very bad to destroy a widget
894 twice. */
895 #if defined (USE_LUCID)
896 if (lw_lucid_widget_p (instance->widget))
897 xlw_destroy_instance (instance);
898 else
899 #endif
900 #if defined (USE_MOTIF)
901 if (lw_motif_widget_p (instance->widget))
902 xm_destroy_instance (instance);
903 else
904 #endif
905 #if defined (USE_OLIT)
906 if (lw_olit_widget_p (instance->widget))
907 xol_destroy_instance (instance);
908 else
909 #endif
910 #if defined (USE_XAW)
911 if (lw_xaw_widget_p (instance->widget))
912 xaw_destroy_instance (instance);
913 else
914 #endif
915 /* do not remove the empty statement */
919 free_widget_instance (instance);
922 void
923 lw_destroy_widget (w)
924 Widget w;
926 widget_instance* instance = get_widget_instance (w, True);
928 if (instance)
930 widget_info *info = instance->info;
931 /* instance has already been removed from the list; free it */
932 destroy_one_instance (instance);
933 /* if there are no instances left, free the info too */
934 if (!info->instances)
935 lw_destroy_all_widgets (info->id);
939 void
940 lw_destroy_all_widgets (id)
941 LWLIB_ID id;
943 widget_info* info = get_widget_info (id, True);
944 widget_instance* instance;
945 widget_instance* next;
947 if (info)
949 for (instance = info->instances; instance; )
951 next = instance->next;
952 destroy_one_instance (instance);
953 instance = next;
955 free_widget_info (info);
959 void
960 lw_destroy_everything ()
962 while (all_widget_info)
963 lw_destroy_all_widgets (all_widget_info->id);
966 void
967 lw_destroy_all_pop_ups ()
969 widget_info* info;
970 widget_info* next;
971 widget_instance* instance;
973 for (info = all_widget_info; info; info = next)
975 next = info->next;
976 instance = info->instances;
977 if (instance && instance->pop_up_p)
978 lw_destroy_all_widgets (info->id);
982 #ifdef USE_MOTIF
983 extern Widget first_child (Widget); /* garbage */
984 #endif
986 Widget
987 lw_raise_all_pop_up_widgets ()
989 widget_info* info;
990 widget_instance* instance;
991 Widget result = NULL;
993 for (info = all_widget_info; info; info = info->next)
994 for (instance = info->instances; instance; instance = instance->next)
995 if (instance->pop_up_p)
997 Widget widget = instance->widget;
998 if (widget)
1000 if (XtIsManaged (widget)
1001 #ifdef USE_MOTIF
1002 /* What a complete load of crap!!!!
1003 When a dialogShell is on the screen, it is not managed!
1005 || (lw_motif_widget_p (instance->widget) &&
1006 XtIsManaged (first_child (widget)))
1007 #endif
1010 if (!result)
1011 result = widget;
1012 XMapRaised (XtDisplay (widget), XtWindow (widget));
1016 return result;
1019 static void
1020 lw_pop_all_widgets (id, up)
1021 LWLIB_ID id;
1022 Boolean up;
1024 widget_info* info = get_widget_info (id, False);
1025 widget_instance* instance;
1027 if (info)
1028 for (instance = info->instances; instance; instance = instance->next)
1029 if (instance->pop_up_p && instance->widget)
1031 #if defined (USE_LUCID)
1032 if (lw_lucid_widget_p (instance->widget))
1034 XtRealizeWidget (instance->widget);
1035 xlw_pop_instance (instance, up);
1037 #endif
1038 #if defined (USE_MOTIF)
1039 if (lw_motif_widget_p (instance->widget))
1041 XtRealizeWidget (instance->widget);
1042 xm_pop_instance (instance, up);
1044 #endif
1045 #if defined (USE_OLIT)
1046 if (lw_olit_widget_p (instance->widget))
1048 XtRealizeWidget (instance->widget);
1049 xol_pop_instance (instance, up);
1051 #endif
1052 #if defined (USE_XAW)
1053 if (lw_xaw_widget_p (instance->widget))
1055 XtRealizeWidget (XtParent (instance->widget));
1056 XtRealizeWidget (instance->widget);
1057 xaw_pop_instance (instance, up);
1059 #endif
1063 void
1064 lw_pop_up_all_widgets (id)
1065 LWLIB_ID id;
1067 lw_pop_all_widgets (id, True);
1070 void
1071 lw_pop_down_all_widgets (id)
1072 LWLIB_ID id;
1074 lw_pop_all_widgets (id, False);
1077 void
1078 lw_popup_menu (widget)
1079 Widget widget;
1081 #if defined (USE_LUCID)
1082 if (lw_lucid_widget_p (widget))
1083 xlw_popup_menu (widget);
1084 #endif
1085 #if defined (USE_MOTIF)
1086 if (lw_motif_widget_p (widget))
1087 xm_popup_menu (widget);
1088 #endif
1089 #if defined (USE_OLIT)
1090 if (lw_olit_widget_p (widget))
1091 xol_popup_menu (widget);
1092 #endif
1093 #if defined (USE_XAW)
1094 if (lw_xaw_widget_p (widget))
1095 xaw_popup_menu (widget);
1096 #endif
1099 \f/* get the values back */
1100 static Boolean
1101 get_one_value (instance, val)
1102 widget_instance* instance;
1103 widget_value* val;
1105 Widget widget = name_to_widget (instance, val->name);
1107 if (widget)
1109 #if defined (USE_LUCID)
1110 if (lw_lucid_widget_p (instance->widget))
1111 xlw_update_one_value (instance, widget, val);
1112 #endif
1113 #if defined (USE_MOTIF)
1114 if (lw_motif_widget_p (instance->widget))
1115 xm_update_one_value (instance, widget, val);
1116 #endif
1117 #if defined (USE_OLIT)
1118 if (lw_olit_widget_p (instance->widget))
1119 xol_update_one_value (instance, widget, val);
1120 #endif
1121 #if defined (USE_XAW)
1122 if (lw_xaw_widget_p (instance->widget))
1123 xaw_update_one_value (instance, widget, val);
1124 #endif
1125 return True;
1127 else
1128 return False;
1131 Boolean
1132 lw_get_some_values (id, val_out)
1133 LWLIB_ID id;
1134 widget_value* val_out;
1136 widget_info* info = get_widget_info (id, False);
1137 widget_instance* instance;
1138 widget_value* val;
1139 Boolean result = False;
1141 if (!info)
1142 return False;
1144 instance = info->instances;
1145 if (!instance)
1146 return False;
1148 for (val = val_out; val; val = val->next)
1149 if (get_one_value (instance, val))
1150 result = True;
1152 return result;
1155 widget_value*
1156 lw_get_all_values (id)
1157 LWLIB_ID id;
1159 widget_info* info = get_widget_info (id, False);
1160 widget_value* val = info->val;
1161 if (lw_get_some_values (id, val))
1162 return val;
1163 else
1164 return NULL;
1167 /* internal function used by the library dependent implementation to get the
1168 widget_value for a given widget in an instance */
1169 widget_value*
1170 lw_get_widget_value_for_widget (instance, w)
1171 widget_instance* instance;
1172 Widget w;
1174 char* name = XtName (w);
1175 widget_value* cur;
1176 for (cur = instance->info->val; cur; cur = cur->next)
1177 if (!strcmp (cur->name, name))
1178 return cur;
1179 return NULL;
1182 \f/* update other instances value when one thing changed */
1183 /* This function can be used as a an XtCallback for the widgets that get
1184 modified to update other instances of the widgets. Closure should be the
1185 widget_instance. */
1186 void
1187 lw_internal_update_other_instances (widget, closure, call_data)
1188 Widget widget;
1189 XtPointer closure;
1190 XtPointer call_data;
1192 /* To forbid recursive calls */
1193 static Boolean updating;
1195 widget_instance* instance = (widget_instance*)closure;
1196 char* name = XtName (widget);
1197 widget_info* info;
1198 widget_instance* cur;
1199 widget_value* val;
1201 /* never recurse as this could cause infinite recursions. */
1202 if (updating)
1203 return;
1205 /* protect against the widget being destroyed */
1206 if (XtWidgetBeingDestroyedP (widget))
1207 return;
1209 /* Return immediately if there are no other instances */
1210 info = instance->info;
1211 if (!info->instances->next)
1212 return;
1214 updating = True;
1216 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1218 if (val && get_one_value (instance, val))
1219 for (cur = info->instances; cur; cur = cur->next)
1220 if (cur != instance)
1221 set_one_value (cur, val, True);
1223 updating = False;
1227 \f/* get the id */
1229 LWLIB_ID
1230 lw_get_widget_id (w)
1231 Widget w;
1233 widget_instance* instance = get_widget_instance (w, False);
1235 return instance ? instance->info->id : 0;
1238 \f/* set the keyboard focus */
1239 void
1240 lw_set_keyboard_focus (parent, w)
1241 Widget parent;
1242 Widget w;
1244 #if defined (USE_MOTIF)
1245 xm_set_keyboard_focus (parent, w);
1246 #else
1247 XtSetKeyboardFocus (parent, w);
1248 #endif
1251 \f/* Show busy */
1252 static void
1253 show_one_widget_busy (w, flag)
1254 Widget w;
1255 Boolean flag;
1257 Pixel foreground = 0;
1258 Pixel background = 1;
1259 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1260 if (!widget_to_invert)
1261 widget_to_invert = w;
1263 XtVaGetValues (widget_to_invert,
1264 XtNforeground, &foreground,
1265 XtNbackground, &background,
1267 XtVaSetValues (widget_to_invert,
1268 XtNforeground, background,
1269 XtNbackground, foreground,
1273 void
1274 lw_show_busy (w, busy)
1275 Widget w;
1276 Boolean busy;
1278 widget_instance* instance = get_widget_instance (w, False);
1279 widget_info* info;
1280 widget_instance* next;
1282 if (instance)
1284 info = instance->info;
1285 if (info->busy != busy)
1287 for (next = info->instances; next; next = next->next)
1288 if (next->widget)
1289 show_one_widget_busy (next->widget, busy);
1290 info->busy = busy;