(defvar_display): Declare this function.
[emacs.git] / lwlib / lwlib.c
blobe18f95b68c9f10ebd8eb0b2ff95249e4693adb1e
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 <sys/types.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include "lwlib-int.h"
28 #include "lwlib-utils.h"
29 #include <X11/StringDefs.h>
31 #if defined (USE_LUCID)
32 #include "lwlib-Xlw.h"
33 #endif
34 #if defined (USE_MOTIF)
35 #include "lwlib-Xm.h"
36 #else /* not USE_MOTIF */
37 #if defined (USE_LUCID)
38 #define USE_XAW
39 #endif /* not USE_MOTIF && USE_LUCID */
40 #endif
41 #if defined (USE_OLIT)
42 #include "lwlib-Xol.h"
43 #endif
44 #if defined (USE_XAW)
45 #include "lwlib-Xaw.h"
46 #endif
48 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
49 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
50 #endif
52 #if defined (USE_MOTIF) && defined (USE_OLIT)
53 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
54 #endif
56 #ifndef max
57 #define max(x, y) ((x) > (y) ? (x) : (y))
58 #endif
60 /* List of all widgets managed by the library. */
61 static widget_info*
62 all_widget_info = NULL;
64 \f/* Forward declarations */
65 static void
66 instanciate_widget_instance (/* widget_instance* instance */);
68 lwlib_memset (address, value, length)
69 char *address;
70 int value;
71 int length;
73 int i;
75 for (i = 0; i < length; i++)
76 address[i] = value;
79 lwlib_bcopy (from, to, length)
80 char *from;
81 char *to;
82 int length;
84 int i;
86 for (i = 0; i < length; i++)
87 to[i] = from[i];
89 \f/* utility functions for widget_instance and widget_info */
90 char *
91 safe_strdup (s)
92 char *s;
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;
103 /* Like strcmp but ignore differences in case. */
105 static int
106 my_strcasecmp (s1, s2)
107 char *s1, *s2;
109 while (1)
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;
124 static void
125 safe_free_str (s)
126 char *s;
128 if (s) free (s);
131 static widget_value *widget_value_free_list = 0;
132 static int malloc_cpt = 0;
134 widget_value *
135 malloc_widget_value ()
137 widget_value *wv;
138 if (widget_value_free_list)
140 wv = widget_value_free_list;
141 widget_value_free_list = wv->free_list;
142 wv->free_list = 0;
144 else
146 wv = (widget_value *) malloc (sizeof (widget_value));
147 malloc_cpt++;
149 lwlib_memset (wv, 0, sizeof (widget_value));
150 return wv;
153 /* this is analagous to free(). It frees only what was allocated
154 by malloc_widget_value(), and no substructures.
156 void
157 free_widget_value (wv)
158 widget_value *wv;
160 if (wv->free_list)
161 abort ();
163 if (malloc_cpt > 25)
165 /* When the number of already allocated cells is too big,
166 We free it. */
167 free (wv);
168 malloc_cpt--;
170 else
172 wv->free_list = widget_value_free_list;
173 widget_value_free_list = wv;
177 static void
178 free_widget_value_tree (wv)
179 widget_value *wv;
181 if (!wv)
182 return;
184 if (wv->name) free (wv->name);
185 if (wv->value) free (wv->value);
186 if (wv->key) free (wv->key);
188 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
190 if (wv->toolkit_data && wv->free_toolkit_data)
192 free (wv->toolkit_data);
193 wv->toolkit_data = (void *) 0xDEADBEEF;
196 if (wv->contents && (wv->contents != (widget_value*)1))
198 free_widget_value_tree (wv->contents);
199 wv->contents = (widget_value *) 0xDEADBEEF;
201 if (wv->next)
203 free_widget_value_tree (wv->next);
204 wv->next = (widget_value *) 0xDEADBEEF;
206 free_widget_value (wv);
209 static widget_value *
210 copy_widget_value_tree (val, change)
211 widget_value* val;
212 change_type change;
214 widget_value* copy;
216 if (!val)
217 return NULL;
218 if (val == (widget_value *) 1)
219 return val;
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;
237 static widget_info *
238 allocate_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;
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;
258 info->next = all_widget_info;
259 all_widget_info = info;
261 return info;
264 static void
265 free_widget_info (info)
266 widget_info* info;
268 safe_free_str (info->type);
269 safe_free_str (info->name);
270 free_widget_value_tree (info->val);
271 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
272 free (info);
275 static void
276 mark_widget_destroyed (widget, closure, call_data)
277 Widget widget;
278 XtPointer closure;
279 XtPointer call_data;
281 widget_instance* instance = (widget_instance*)closure;
283 /* be very conservative */
284 if (instance->widget == widget)
285 instance->widget = NULL;
288 static widget_instance *
289 allocate_widget_instance (info, parent, pop_up_p)
290 widget_info* info;
291 Widget parent;
292 Boolean pop_up_p;
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;
302 instanciate_widget_instance (instance);
304 XtAddCallback (instance->widget, XtNdestroyCallback,
305 mark_widget_destroyed, (XtPointer)instance);
306 return instance;
309 static void
310 free_widget_instance (instance)
311 widget_instance* instance;
313 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
314 free (instance);
317 static widget_info *
318 get_widget_info (id, remove_p)
319 LWLIB_ID id;
320 Boolean remove_p;
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)
329 if (remove_p)
331 if (prev)
332 prev->next = info->next;
333 else
334 all_widget_info = info->next;
336 return info;
338 return NULL;
341 /* Internal function used by the library dependent implementation to get the
342 widget_value for a given widget in an instance */
343 widget_info *
344 lw_get_widget_info (id)
345 LWLIB_ID id;
347 return get_widget_info (id, 0);
350 static widget_instance *
351 get_widget_instance (widget, remove_p)
352 Widget widget;
353 Boolean remove_p;
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)
364 if (remove_p)
366 if (prev)
367 prev->next = instance->next;
368 else
369 info->instances = instance->next;
371 return instance;
373 return (widget_instance *) 0;
376 static widget_instance*
377 find_instance (id, parent, pop_up_p)
378 LWLIB_ID id;
379 Widget parent;
380 Boolean pop_up_p;
382 widget_info* info = get_widget_info (id, False);
383 widget_instance* instance;
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;
390 return NULL;
394 /* utility function for widget_value */
395 static Boolean
396 safe_strcmp (s1, s2)
397 char* s1;
398 char* s2;
400 if (!!s1 ^ !!s2) return True;
401 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
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
424 static widget_value *
425 merge_widget_value (val1, val2, level)
426 widget_value* val1;
427 widget_value* val2;
428 int level;
430 change_type change;
431 widget_value* merged_next;
432 widget_value* merged_contents;
434 if (!val1)
436 if (val2)
437 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
438 else
439 return NULL;
441 if (!val2)
443 free_widget_value_tree (val1);
444 return NULL;
447 change = NO_CHANGE;
449 if (safe_strcmp (val1->name, val2->name))
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);
457 if (safe_strcmp (val1->value, val2->value))
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);
465 if (safe_strcmp (val1->key, val2->key))
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);
473 if (val1->enabled != val2->enabled)
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;
480 if (val1->selected != val2->selected)
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;
487 if (val1->call_data != val2->call_data)
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;
495 if (level > 0)
497 merged_contents =
498 merge_widget_value (val1->contents, val2->contents, level - 1);
500 if (val1->contents && !merged_contents)
502 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
503 0, 0);
504 change = max (change, INVISIBLE_CHANGE);
506 else if (merged_contents && merged_contents->change != NO_CHANGE)
508 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
509 0, 0);
510 change = max (change, INVISIBLE_CHANGE);
513 val1->contents = merged_contents;
516 merged_next = merge_widget_value (val1->next, val2->next, level);
518 if (val1->next && !merged_next)
520 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
521 0, 0);
522 change = max (change, STRUCTURAL_CHANGE);
524 else if (merged_next)
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);
532 val1->next = merged_next;
534 val1->change = change;
536 if (change > NO_CHANGE && val1->toolkit_data)
538 if (val1->free_toolkit_data)
539 free (val1->toolkit_data);
540 val1->toolkit_data = NULL;
543 return val1;
547 /* modifying the widgets */
548 static Widget
549 name_to_widget (instance, name)
550 widget_instance* instance;
551 char* name;
553 Widget widget = NULL;
555 if (!instance->widget)
556 return NULL;
558 if (!strcmp (XtName (instance->widget), name))
559 widget = instance->widget;
560 else
562 int length = strlen (name) + 2;
563 char* real_name = (char *) xmalloc (length);
564 real_name [0] = '*';
565 strcpy (real_name + 1, name);
567 widget = XtNameToWidget (instance->widget, real_name);
569 free (real_name);
571 return widget;
574 static void
575 set_one_value (instance, val, deep_p)
576 widget_instance* instance;
577 widget_value* val;
578 Boolean deep_p;
580 Widget widget = name_to_widget (instance, val->name);
582 if (widget)
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);
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);
599 #endif
603 static void
604 update_one_widget_instance (instance, deep_p)
605 widget_instance* instance;
606 Boolean deep_p;
608 widget_value *val;
610 if (!instance->widget)
611 /* the widget was destroyed */
612 return;
614 for (val = instance->info->val; val; val = val->next)
615 if (val->change != NO_CHANGE)
616 set_one_value (instance, val, deep_p);
619 static void
620 update_all_widget_values (info, deep_p)
621 widget_info* info;
622 Boolean deep_p;
624 widget_instance* instance;
625 widget_value* val;
627 for (instance = info->instances; instance; instance = instance->next)
628 update_one_widget_instance (instance, deep_p);
630 for (val = info->val; val; val = val->next)
631 val->change = NO_CHANGE;
634 void
635 lw_modify_all_widgets (id, val, deep_p)
636 LWLIB_ID id;
637 widget_value* val;
638 Boolean deep_p;
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;
648 if (!info)
649 return;
651 for (new_val = val; new_val; new_val = new_val->next)
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))
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;
671 if (!found)
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);
679 new_val->next = next_new_val;
682 update_all_widget_values (info, deep_p);
686 /* creating the widgets */
688 static void
689 initialize_widget_instance (instance)
690 widget_instance* instance;
692 widget_value* val;
694 for (val = instance->info->val; val; val = val->next)
695 val->change = STRUCTURAL_CHANGE;
697 update_one_widget_instance (instance, True);
699 for (val = instance->info->val; val; val = val->next)
700 val->change = NO_CHANGE;
704 static widget_creation_function
705 find_in_table (type, table)
706 char* type;
707 widget_creation_entry* table;
709 widget_creation_entry* cur;
710 for (cur = table; cur->type; cur++)
711 if (!my_strcasecmp (type, cur->type))
712 return cur->function;
713 return NULL;
716 static Boolean
717 dialog_spec_p (name)
718 char* name;
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;
725 switch (name [0])
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')
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;
742 else
743 return False;
745 default:
746 return False;
750 static void
751 instanciate_widget_instance (instance)
752 widget_instance* instance;
754 widget_creation_function function = NULL;
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
768 #if defined (USE_XAW)
769 if (!function)
770 function = find_in_table (instance->info->type, xaw_creation_table);
771 #endif
773 if (!function)
775 if (dialog_spec_p (instance->info->type))
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
784 #if defined (USE_XAW)
785 if (!function)
786 function = xaw_create_dialog;
787 #endif
788 #if defined (USE_OLIT)
789 /* not yet */
790 #endif
794 if (!function)
796 printf ("No creation function for widget type %s\n",
797 instance->info->type);
798 abort ();
801 instance->widget = (*function) (instance);
803 if (!instance->widget)
804 abort ();
806 /* XtRealizeWidget (instance->widget);*/
809 void
810 lw_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;
819 if (!get_widget_info (id, False))
820 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
821 post_activate_cb);
824 Widget
825 lw_get_widget (id, parent, pop_up_p)
826 LWLIB_ID id;
827 Widget parent;
828 Boolean pop_up_p;
830 widget_instance* instance;
832 instance = find_instance (id, parent, pop_up_p);
833 return instance ? instance->widget : NULL;
836 Widget
837 lw_make_widget (id, parent, pop_up_p)
838 LWLIB_ID id;
839 Widget parent;
840 Boolean pop_up_p;
842 widget_instance* instance;
843 widget_info* info;
845 instance = find_instance (id, parent, pop_up_p);
846 if (!instance)
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);
854 if (!instance->widget)
855 abort ();
856 return instance->widget;
859 Widget
860 lw_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;
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);
877 /* destroying the widgets */
878 static void
879 destroy_one_instance (instance)
880 widget_instance* instance;
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.
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.
890 if (instance->widget)
891 XtRemoveCallback (instance->widget, XtNdestroyCallback,
892 mark_widget_destroyed, (XtPointer)instance);
894 if (instance->widget)
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
913 #endif
914 #if defined (USE_XAW)
915 if (lw_xaw_widget_p (instance->widget))
916 xaw_destroy_instance (instance);
917 else
918 #endif
919 /* do not remove the empty statement */
923 free_widget_instance (instance);
926 void
927 lw_destroy_widget (w)
928 Widget w;
930 widget_instance* instance = get_widget_instance (w, True);
932 if (instance)
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);
943 void
944 lw_destroy_all_widgets (id)
945 LWLIB_ID id;
947 widget_info* info = get_widget_info (id, True);
948 widget_instance* instance;
949 widget_instance* next;
951 if (info)
953 for (instance = info->instances; instance; )
955 next = instance->next;
956 destroy_one_instance (instance);
957 instance = next;
959 free_widget_info (info);
963 void
964 lw_destroy_everything ()
966 while (all_widget_info)
967 lw_destroy_all_widgets (all_widget_info->id);
970 void
971 lw_destroy_all_pop_ups ()
973 widget_info* info;
974 widget_info* next;
975 widget_instance* instance;
977 for (info = all_widget_info; info; info = next)
979 next = info->next;
980 instance = info->instances;
981 if (instance && instance->pop_up_p)
982 lw_destroy_all_widgets (info->id);
986 #ifdef USE_MOTIF
987 extern Widget first_child (Widget); /* garbage */
988 #endif
990 Widget
991 lw_raise_all_pop_up_widgets ()
993 widget_info* info;
994 widget_instance* instance;
995 Widget result = NULL;
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)
1001 Widget widget = instance->widget;
1002 if (widget)
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!
1009 || (lw_motif_widget_p (instance->widget) &&
1010 XtIsManaged (first_child (widget)))
1011 #endif
1014 if (!result)
1015 result = widget;
1016 XMapRaised (XtDisplay (widget), XtWindow (widget));
1020 return result;
1023 static void
1024 lw_pop_all_widgets (id, up)
1025 LWLIB_ID id;
1026 Boolean up;
1028 widget_info* info = get_widget_info (id, False);
1029 widget_instance* instance;
1031 if (info)
1032 for (instance = info->instances; instance; instance = instance->next)
1033 if (instance->pop_up_p && instance->widget)
1035 #if defined (USE_LUCID)
1036 if (lw_lucid_widget_p (instance->widget))
1038 XtRealizeWidget (instance->widget);
1039 xlw_pop_instance (instance, up);
1041 #endif
1042 #if defined (USE_MOTIF)
1043 if (lw_motif_widget_p (instance->widget))
1045 XtRealizeWidget (instance->widget);
1046 xm_pop_instance (instance, up);
1048 #endif
1049 #if defined (USE_OLIT)
1050 if (lw_olit_widget_p (instance->widget))
1052 XtRealizeWidget (instance->widget);
1053 xol_pop_instance (instance, up);
1055 #endif
1056 #if defined (USE_XAW)
1057 if (lw_xaw_widget_p (instance->widget))
1059 XtRealizeWidget (XtParent (instance->widget));
1060 XtRealizeWidget (instance->widget);
1061 xaw_pop_instance (instance, up);
1063 #endif
1067 void
1068 lw_pop_up_all_widgets (id)
1069 LWLIB_ID id;
1071 lw_pop_all_widgets (id, True);
1074 void
1075 lw_pop_down_all_widgets (id)
1076 LWLIB_ID id;
1078 lw_pop_all_widgets (id, False);
1081 void
1082 lw_popup_menu (widget)
1083 Widget widget;
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
1097 #if defined (USE_XAW)
1098 if (lw_xaw_widget_p (widget))
1099 xaw_popup_menu (widget);
1100 #endif
1103 \f/* get the values back */
1104 static Boolean
1105 get_one_value (instance, val)
1106 widget_instance* instance;
1107 widget_value* val;
1109 Widget widget = name_to_widget (instance, val->name);
1111 if (widget)
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);
1124 #endif
1125 #if defined (USE_XAW)
1126 if (lw_xaw_widget_p (instance->widget))
1127 xaw_update_one_value (instance, widget, val);
1128 #endif
1129 return True;
1131 else
1132 return False;
1135 Boolean
1136 lw_get_some_values (id, val_out)
1137 LWLIB_ID id;
1138 widget_value* val_out;
1140 widget_info* info = get_widget_info (id, False);
1141 widget_instance* instance;
1142 widget_value* val;
1143 Boolean result = False;
1145 if (!info)
1146 return False;
1148 instance = info->instances;
1149 if (!instance)
1150 return False;
1152 for (val = val_out; val; val = val->next)
1153 if (get_one_value (instance, val))
1154 result = True;
1156 return result;
1159 widget_value*
1160 lw_get_all_values (id)
1161 LWLIB_ID id;
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;
1171 /* internal function used by the library dependent implementation to get the
1172 widget_value for a given widget in an instance */
1173 widget_value*
1174 lw_get_widget_value_for_widget (instance, w)
1175 widget_instance* instance;
1176 Widget w;
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;
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. */
1190 void
1191 lw_internal_update_other_instances (widget, closure, call_data)
1192 Widget widget;
1193 XtPointer closure;
1194 XtPointer call_data;
1196 /* To forbid recursive calls */
1197 static Boolean updating;
1199 widget_instance* instance = (widget_instance*)closure;
1200 char* name = XtName (widget);
1201 widget_info* info;
1202 widget_instance* cur;
1203 widget_value* val;
1205 /* never recurse as this could cause infinite recursions. */
1206 if (updating)
1207 return;
1209 /* protect against the widget being destroyed */
1210 if (XtWidgetBeingDestroyedP (widget))
1211 return;
1213 /* Return immediately if there are no other instances */
1214 info = instance->info;
1215 if (!info->instances->next)
1216 return;
1218 updating = True;
1220 for (val = info->val; val && strcmp (val->name, name); val = val->next);
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);
1227 updating = False;
1231 \f/* get the id */
1233 LWLIB_ID
1234 lw_get_widget_id (w)
1235 Widget w;
1237 widget_instance* instance = get_widget_instance (w, False);
1239 return instance ? instance->info->id : 0;
1242 \f/* set the keyboard focus */
1243 void
1244 lw_set_keyboard_focus (parent, w)
1245 Widget parent;
1246 Widget w;
1248 #if defined (USE_MOTIF)
1249 xm_set_keyboard_focus (parent, w);
1250 #else
1251 XtSetKeyboardFocus (parent, w);
1252 #endif
1255 \f/* Show busy */
1256 static void
1257 show_one_widget_busy (w, flag)
1258 Widget w;
1259 Boolean flag;
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;
1267 XtVaGetValues (widget_to_invert,
1268 XtNforeground, &foreground,
1269 XtNbackground, &background,
1271 XtVaSetValues (widget_to_invert,
1272 XtNforeground, background,
1273 XtNbackground, foreground,
1277 void
1278 lw_show_busy (w, busy)
1279 Widget w;
1280 Boolean busy;
1282 widget_instance* instance = get_widget_instance (w, False);
1283 widget_info* info;
1284 widget_instance* next;
1286 if (instance)
1288 info = instance->info;
1289 if (info->busy != busy)
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;
1299 /* This hack exists because Lucid/Athena need to execute the strange
1300 function below to support geometry management. */
1301 void
1302 lw_refigure_widget (w, doit)
1303 Widget w;
1304 Boolean doit;
1306 #if defined (USE_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
1317 /* Toolkit independent way of determining if an event window is in the
1318 menubar. */
1319 Boolean
1320 lw_window_is_in_menubar (win, menubar_widget)
1321 Window win;
1322 Widget menubar_widget;
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
1335 /* Motif hack to set the main window areas. */
1336 void
1337 lw_set_main_areas (parent, menubar, work_area)
1338 Widget parent;
1339 Widget menubar;
1340 Widget work_area;
1342 #if defined (USE_MOTIF)
1343 xm_set_main_areas (parent, menubar, work_area);
1344 #endif
1347 /* Manage resizing for Motif. This disables resizing when the menubar
1348 is about to be modified. */
1349 void
1350 lw_allow_resizing (w, flag)
1351 Widget w;
1352 Boolean flag;
1354 #if defined (USE_MOTIF)
1355 xm_manage_resizing (w, flag);
1356 #endif