Moved (define-key menu-bar-ediff-menu ...) to ediff-hook.el:
[emacs.git] / lwlib / lwlib.c
blob5dd4f1d8133af9864b5a6fd36b24fcda2db91887
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 #ifdef __osf__
32 #include <string.h>
33 #include <stdlib.h>
34 extern long *xmalloc();
35 #endif
37 #if defined (USE_LUCID)
38 #include "lwlib-Xlw.h"
39 #endif
40 #if defined (USE_MOTIF)
41 #include "lwlib-Xm.h"
42 #else /* not USE_MOTIF */
43 #if defined (USE_LUCID)
44 #define USE_XAW
45 #endif /* not USE_MOTIF && USE_LUCID */
46 #endif
47 #if defined (USE_OLIT)
48 #include "lwlib-Xol.h"
49 #endif
50 #if defined (USE_XAW)
51 #include "lwlib-Xaw.h"
52 #endif
54 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
55 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
56 #endif
58 #if defined (USE_MOTIF) && defined (USE_OLIT)
59 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
60 #endif
62 #ifndef max
63 #define max(x, y) ((x) > (y) ? (x) : (y))
64 #endif
66 /* List of all widgets managed by the library. */
67 static widget_info*
68 all_widget_info = NULL;
70 #ifdef USE_MOTIF
71 char *lwlib_toolkit_type = "motif";
72 #else
73 char *lwlib_toolkit_type = "lucid";
74 #endif
75 \f/* Forward declarations */
76 static void
77 instanciate_widget_instance (/* widget_instance* instance */);
79 lwlib_memset (address, value, length)
80 char *address;
81 int value;
82 int length;
84 int i;
86 for (i = 0; i < length; i++)
87 address[i] = value;
90 lwlib_bcopy (from, to, length)
91 char *from;
92 char *to;
93 int length;
95 int i;
97 for (i = 0; i < length; i++)
98 to[i] = from[i];
100 \f/* utility functions for widget_instance and widget_info */
101 char *
102 safe_strdup (s)
103 char *s;
105 char *result;
106 if (! s) return 0;
107 result = (char *) malloc (strlen (s) + 1);
108 if (! result)
109 return 0;
110 strcpy (result, s);
111 return result;
114 /* Like strcmp but ignore differences in case. */
116 static int
117 my_strcasecmp (s1, s2)
118 char *s1, *s2;
120 while (1)
122 int c1 = *s1++;
123 int c2 = *s2++;
124 if (isupper (c1))
125 c1 = tolower (c1);
126 if (isupper (c2))
127 c2 = tolower (c2);
128 if (c1 != c2)
129 return (c1 > c2 ? 1 : -1);
130 if (c1 == 0)
131 return 0;
135 static void
136 safe_free_str (s)
137 char *s;
139 if (s) free (s);
142 static widget_value *widget_value_free_list = 0;
143 static int malloc_cpt = 0;
145 widget_value *
146 malloc_widget_value ()
148 widget_value *wv;
149 if (widget_value_free_list)
151 wv = widget_value_free_list;
152 widget_value_free_list = wv->free_list;
153 wv->free_list = 0;
155 else
157 wv = (widget_value *) malloc (sizeof (widget_value));
158 malloc_cpt++;
160 lwlib_memset (wv, 0, sizeof (widget_value));
161 return wv;
164 /* this is analagous to free(). It frees only what was allocated
165 by malloc_widget_value(), and no substructures.
167 void
168 free_widget_value (wv)
169 widget_value *wv;
171 if (wv->free_list)
172 abort ();
174 if (malloc_cpt > 25)
176 /* When the number of already allocated cells is too big,
177 We free it. */
178 free (wv);
179 malloc_cpt--;
181 else
183 wv->free_list = widget_value_free_list;
184 widget_value_free_list = wv;
188 static void
189 free_widget_value_tree (wv)
190 widget_value *wv;
192 if (!wv)
193 return;
195 if (wv->name) free (wv->name);
196 if (wv->value) free (wv->value);
197 if (wv->key) free (wv->key);
199 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
201 if (wv->toolkit_data && wv->free_toolkit_data)
203 free (wv->toolkit_data);
204 wv->toolkit_data = (void *) 0xDEADBEEF;
207 if (wv->contents && (wv->contents != (widget_value*)1))
209 free_widget_value_tree (wv->contents);
210 wv->contents = (widget_value *) 0xDEADBEEF;
212 if (wv->next)
214 free_widget_value_tree (wv->next);
215 wv->next = (widget_value *) 0xDEADBEEF;
217 free_widget_value (wv);
220 static widget_value *
221 copy_widget_value_tree (val, change)
222 widget_value* val;
223 change_type change;
225 widget_value* copy;
227 if (!val)
228 return NULL;
229 if (val == (widget_value *) 1)
230 return val;
232 copy = malloc_widget_value ();
233 copy->name = safe_strdup (val->name);
234 copy->value = safe_strdup (val->value);
235 copy->key = safe_strdup (val->key);
236 copy->enabled = val->enabled;
237 copy->selected = val->selected;
238 copy->edited = False;
239 copy->change = change;
240 copy->contents = copy_widget_value_tree (val->contents, change);
241 copy->call_data = val->call_data;
242 copy->next = copy_widget_value_tree (val->next, change);
243 copy->toolkit_data = NULL;
244 copy->free_toolkit_data = False;
245 return copy;
248 static widget_info *
249 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
250 char* type;
251 char* name;
252 LWLIB_ID id;
253 widget_value* val;
254 lw_callback pre_activate_cb;
255 lw_callback selection_cb;
256 lw_callback post_activate_cb;
258 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
259 info->type = safe_strdup (type);
260 info->name = safe_strdup (name);
261 info->id = id;
262 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
263 info->busy = False;
264 info->pre_activate_cb = pre_activate_cb;
265 info->selection_cb = selection_cb;
266 info->post_activate_cb = post_activate_cb;
267 info->instances = NULL;
269 info->next = all_widget_info;
270 all_widget_info = info;
272 return info;
275 static void
276 free_widget_info (info)
277 widget_info* info;
279 safe_free_str (info->type);
280 safe_free_str (info->name);
281 free_widget_value_tree (info->val);
282 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
283 free (info);
286 static void
287 mark_widget_destroyed (widget, closure, call_data)
288 Widget widget;
289 XtPointer closure;
290 XtPointer call_data;
292 widget_instance* instance = (widget_instance*)closure;
294 /* be very conservative */
295 if (instance->widget == widget)
296 instance->widget = NULL;
299 static widget_instance *
300 allocate_widget_instance (info, parent, pop_up_p)
301 widget_info* info;
302 Widget parent;
303 Boolean pop_up_p;
305 widget_instance* instance =
306 (widget_instance*)malloc (sizeof (widget_instance));
307 instance->parent = parent;
308 instance->pop_up_p = pop_up_p;
309 instance->info = info;
310 instance->next = info->instances;
311 info->instances = instance;
313 instanciate_widget_instance (instance);
315 XtAddCallback (instance->widget, XtNdestroyCallback,
316 mark_widget_destroyed, (XtPointer)instance);
317 return instance;
320 static void
321 free_widget_instance (instance)
322 widget_instance* instance;
324 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
325 free (instance);
328 static widget_info *
329 get_widget_info (id, remove_p)
330 LWLIB_ID id;
331 Boolean remove_p;
333 widget_info* info;
334 widget_info* prev;
335 for (prev = NULL, info = all_widget_info;
336 info;
337 prev = info, info = info->next)
338 if (info->id == id)
340 if (remove_p)
342 if (prev)
343 prev->next = info->next;
344 else
345 all_widget_info = info->next;
347 return info;
349 return NULL;
352 /* Internal function used by the library dependent implementation to get the
353 widget_value for a given widget in an instance */
354 widget_info *
355 lw_get_widget_info (id)
356 LWLIB_ID id;
358 return get_widget_info (id, 0);
361 static widget_instance *
362 get_widget_instance (widget, remove_p)
363 Widget widget;
364 Boolean remove_p;
366 widget_info* info;
367 widget_instance* instance;
368 widget_instance* prev;
369 for (info = all_widget_info; info; info = info->next)
370 for (prev = NULL, instance = info->instances;
371 instance;
372 prev = instance, instance = instance->next)
373 if (instance->widget == widget)
375 if (remove_p)
377 if (prev)
378 prev->next = instance->next;
379 else
380 info->instances = instance->next;
382 return instance;
384 return (widget_instance *) 0;
387 static widget_instance*
388 find_instance (id, parent, pop_up_p)
389 LWLIB_ID id;
390 Widget parent;
391 Boolean pop_up_p;
393 widget_info* info = get_widget_info (id, False);
394 widget_instance* instance;
396 if (info)
397 for (instance = info->instances; instance; instance = instance->next)
398 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
399 return instance;
401 return NULL;
405 /* utility function for widget_value */
406 static Boolean
407 safe_strcmp (s1, s2)
408 char* s1;
409 char* s2;
411 if (!!s1 ^ !!s2) return True;
412 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
416 #if 0
417 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
418 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
419 name, \
420 (oc == NO_CHANGE ? "none" : \
421 (oc == INVISIBLE_CHANGE ? "invisible" : \
422 (oc == VISIBLE_CHANGE ? "visible" : \
423 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
424 oc, \
425 (nc == NO_CHANGE ? "none" : \
426 (nc == INVISIBLE_CHANGE ? "invisible" : \
427 (nc == VISIBLE_CHANGE ? "visible" : \
428 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
429 nc, desc, a1, a2)
430 #else
431 # define EXPLAIN(name, oc, nc, desc, a1, a2)
432 #endif
435 static widget_value *
436 merge_widget_value (val1, val2, level)
437 widget_value* val1;
438 widget_value* val2;
439 int level;
441 change_type change;
442 widget_value* merged_next;
443 widget_value* merged_contents;
445 if (!val1)
447 if (val2)
448 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
449 else
450 return NULL;
452 if (!val2)
454 free_widget_value_tree (val1);
455 return NULL;
458 change = NO_CHANGE;
460 if (safe_strcmp (val1->name, val2->name))
462 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
463 val1->name, val2->name);
464 change = max (change, STRUCTURAL_CHANGE);
465 safe_free_str (val1->name);
466 val1->name = safe_strdup (val2->name);
468 if (safe_strcmp (val1->value, val2->value))
470 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
471 val1->value, val2->value);
472 change = max (change, VISIBLE_CHANGE);
473 safe_free_str (val1->value);
474 val1->value = safe_strdup (val2->value);
476 if (safe_strcmp (val1->key, val2->key))
478 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
479 val1->key, val2->key);
480 change = max (change, VISIBLE_CHANGE);
481 safe_free_str (val1->key);
482 val1->key = safe_strdup (val2->key);
484 if (val1->enabled != val2->enabled)
486 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
487 val1->enabled, val2->enabled);
488 change = max (change, VISIBLE_CHANGE);
489 val1->enabled = val2->enabled;
491 if (val1->selected != val2->selected)
493 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
494 val1->selected, val2->selected);
495 change = max (change, VISIBLE_CHANGE);
496 val1->selected = val2->selected;
498 if (val1->call_data != val2->call_data)
500 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
501 val1->call_data, val2->call_data);
502 change = max (change, INVISIBLE_CHANGE);
503 val1->call_data = val2->call_data;
506 if (level > 0)
508 merged_contents =
509 merge_widget_value (val1->contents, val2->contents, level - 1);
511 if (val1->contents && !merged_contents)
513 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
514 0, 0);
515 change = max (change, INVISIBLE_CHANGE);
517 else if (merged_contents && merged_contents->change != NO_CHANGE)
519 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
520 0, 0);
521 change = max (change, INVISIBLE_CHANGE);
524 val1->contents = merged_contents;
527 merged_next = merge_widget_value (val1->next, val2->next, level);
529 if (val1->next && !merged_next)
531 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
532 0, 0);
533 change = max (change, STRUCTURAL_CHANGE);
535 else if (merged_next)
537 if (merged_next->change)
538 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
539 0, 0);
540 change = max (change, merged_next->change);
543 val1->next = merged_next;
545 val1->change = change;
547 if (change > NO_CHANGE && val1->toolkit_data)
549 if (val1->free_toolkit_data)
550 free (val1->toolkit_data);
551 val1->toolkit_data = NULL;
554 return val1;
558 /* modifying the widgets */
559 static Widget
560 name_to_widget (instance, name)
561 widget_instance* instance;
562 char* name;
564 Widget widget = NULL;
566 if (!instance->widget)
567 return NULL;
569 if (!strcmp (XtName (instance->widget), name))
570 widget = instance->widget;
571 else
573 int length = strlen (name) + 2;
574 char* real_name = (char *) xmalloc (length);
575 real_name [0] = '*';
576 strcpy (real_name + 1, name);
578 widget = XtNameToWidget (instance->widget, real_name);
580 free (real_name);
582 return widget;
585 static void
586 set_one_value (instance, val, deep_p)
587 widget_instance* instance;
588 widget_value* val;
589 Boolean deep_p;
591 Widget widget = name_to_widget (instance, val->name);
593 if (widget)
595 #if defined (USE_LUCID)
596 if (lw_lucid_widget_p (instance->widget))
597 xlw_update_one_widget (instance, widget, val, deep_p);
598 #endif
599 #if defined (USE_MOTIF)
600 if (lw_motif_widget_p (instance->widget))
601 xm_update_one_widget (instance, widget, val, deep_p);
602 #endif
603 #if defined (USE_OLIT)
604 if (lw_olit_widget_p (instance->widget))
605 xol_update_one_widget (instance, widget, val, deep_p);
606 #endif
607 #if defined (USE_XAW)
608 if (lw_xaw_widget_p (instance->widget))
609 xaw_update_one_widget (instance, widget, val, deep_p);
610 #endif
614 static void
615 update_one_widget_instance (instance, deep_p)
616 widget_instance* instance;
617 Boolean deep_p;
619 widget_value *val;
621 if (!instance->widget)
622 /* the widget was destroyed */
623 return;
625 for (val = instance->info->val; val; val = val->next)
626 if (val->change != NO_CHANGE)
627 set_one_value (instance, val, deep_p);
630 static void
631 update_all_widget_values (info, deep_p)
632 widget_info* info;
633 Boolean deep_p;
635 widget_instance* instance;
636 widget_value* val;
638 for (instance = info->instances; instance; instance = instance->next)
639 update_one_widget_instance (instance, deep_p);
641 for (val = info->val; val; val = val->next)
642 val->change = NO_CHANGE;
645 void
646 lw_modify_all_widgets (id, val, deep_p)
647 LWLIB_ID id;
648 widget_value* val;
649 Boolean deep_p;
651 widget_info* info = get_widget_info (id, False);
652 widget_value* new_val;
653 widget_value* next_new_val;
654 widget_value* cur;
655 widget_value* prev;
656 widget_value* next;
657 int found;
659 if (!info)
660 return;
662 for (new_val = val; new_val; new_val = new_val->next)
664 next_new_val = new_val->next;
665 new_val->next = NULL;
666 found = False;
667 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
668 if (!strcmp (cur->name, new_val->name))
670 found = True;
671 next = cur->next;
672 cur->next = NULL;
673 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
674 if (prev)
675 prev->next = cur ? cur : next;
676 else
677 info->val = cur ? cur : next;
678 if (cur)
679 cur->next = next;
680 break;
682 if (!found)
684 /* Could not find it, add it */
685 if (prev)
686 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
687 else
688 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
690 new_val->next = next_new_val;
693 update_all_widget_values (info, deep_p);
697 /* creating the widgets */
699 static void
700 initialize_widget_instance (instance)
701 widget_instance* instance;
703 widget_value* val;
705 for (val = instance->info->val; val; val = val->next)
706 val->change = STRUCTURAL_CHANGE;
708 update_one_widget_instance (instance, True);
710 for (val = instance->info->val; val; val = val->next)
711 val->change = NO_CHANGE;
715 static widget_creation_function
716 find_in_table (type, table)
717 char* type;
718 widget_creation_entry* table;
720 widget_creation_entry* cur;
721 for (cur = table; cur->type; cur++)
722 if (!my_strcasecmp (type, cur->type))
723 return cur->function;
724 return NULL;
727 static Boolean
728 dialog_spec_p (name)
729 char* name;
731 /* return True if name matches [EILPQeilpq][1-9][Bb] or
732 [EILPQeilpq][1-9][Bb][Rr][1-9] */
733 if (!name)
734 return False;
736 switch (name [0])
738 case 'E': case 'I': case 'L': case 'P': case 'Q':
739 case 'e': case 'i': case 'l': case 'p': case 'q':
740 if (name [1] >= '0' && name [1] <= '9')
742 if (name [2] != 'B' && name [2] != 'b')
743 return False;
744 if (!name [3])
745 return True;
746 if ((name [3] == 'T' || name [3] == 't') && !name [4])
747 return True;
748 if ((name [3] == 'R' || name [3] == 'r')
749 && name [4] >= '0' && name [4] <= '9' && !name [5])
750 return True;
751 return False;
753 else
754 return False;
756 default:
757 return False;
761 static void
762 instanciate_widget_instance (instance)
763 widget_instance* instance;
765 widget_creation_function function = NULL;
767 #if defined (USE_LUCID)
768 if (!function)
769 function = find_in_table (instance->info->type, xlw_creation_table);
770 #endif
771 #if defined(USE_MOTIF)
772 if (!function)
773 function = find_in_table (instance->info->type, xm_creation_table);
774 #endif
775 #if defined (USE_OLIT)
776 if (!function)
777 function = find_in_table (instance->info->type, xol_creation_table);
778 #endif
779 #if defined (USE_XAW)
780 if (!function)
781 function = find_in_table (instance->info->type, xaw_creation_table);
782 #endif
784 if (!function)
786 if (dialog_spec_p (instance->info->type))
788 #if defined (USE_LUCID)
789 /* not yet */
790 #endif
791 #if defined(USE_MOTIF)
792 if (!function)
793 function = xm_create_dialog;
794 #endif
795 #if defined (USE_XAW)
796 if (!function)
797 function = xaw_create_dialog;
798 #endif
799 #if defined (USE_OLIT)
800 /* not yet */
801 #endif
805 if (!function)
807 printf ("No creation function for widget type %s\n",
808 instance->info->type);
809 abort ();
812 instance->widget = (*function) (instance);
814 if (!instance->widget)
815 abort ();
817 /* XtRealizeWidget (instance->widget);*/
820 void
821 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
822 char* type;
823 char* name;
824 LWLIB_ID id;
825 widget_value* val;
826 lw_callback pre_activate_cb;
827 lw_callback selection_cb;
828 lw_callback post_activate_cb;
830 if (!get_widget_info (id, False))
831 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
832 post_activate_cb);
835 Widget
836 lw_get_widget (id, parent, pop_up_p)
837 LWLIB_ID id;
838 Widget parent;
839 Boolean pop_up_p;
841 widget_instance* instance;
843 instance = find_instance (id, parent, pop_up_p);
844 return instance ? instance->widget : NULL;
847 Widget
848 lw_make_widget (id, parent, pop_up_p)
849 LWLIB_ID id;
850 Widget parent;
851 Boolean pop_up_p;
853 widget_instance* instance;
854 widget_info* info;
856 instance = find_instance (id, parent, pop_up_p);
857 if (!instance)
859 info = get_widget_info (id, False);
860 if (!info)
861 return NULL;
862 instance = allocate_widget_instance (info, parent, pop_up_p);
863 initialize_widget_instance (instance);
865 if (!instance->widget)
866 abort ();
867 return instance->widget;
870 Widget
871 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
872 char* type;
873 char* name;
874 LWLIB_ID id;
875 widget_value* val;
876 Widget parent;
877 Boolean pop_up_p;
878 lw_callback pre_activate_cb;
879 lw_callback selection_cb;
880 lw_callback post_activate_cb;
882 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
883 post_activate_cb);
884 return lw_make_widget (id, parent, pop_up_p);
888 /* destroying the widgets */
889 static void
890 destroy_one_instance (instance)
891 widget_instance* instance;
893 /* Remove the destroy callback on the widget; that callback will try to
894 dereference the instance object (to set its widget slot to 0, since the
895 widget is dead.) Since the instance is now dead, we don't have to worry
896 about the fact that its widget is dead too.
898 This happens in the Phase2Destroy of the widget, so this callback would
899 not have been run until arbitrarily long after the instance was freed.
901 if (instance->widget)
902 XtRemoveCallback (instance->widget, XtNdestroyCallback,
903 mark_widget_destroyed, (XtPointer)instance);
905 if (instance->widget)
907 /* The else are pretty tricky here, including the empty statement
908 at the end because it would be very bad to destroy a widget
909 twice. */
910 #if defined (USE_LUCID)
911 if (lw_lucid_widget_p (instance->widget))
912 xlw_destroy_instance (instance);
913 else
914 #endif
915 #if defined (USE_MOTIF)
916 if (lw_motif_widget_p (instance->widget))
917 xm_destroy_instance (instance);
918 else
919 #endif
920 #if defined (USE_OLIT)
921 if (lw_olit_widget_p (instance->widget))
922 xol_destroy_instance (instance);
923 else
924 #endif
925 #if defined (USE_XAW)
926 if (lw_xaw_widget_p (instance->widget))
927 xaw_destroy_instance (instance);
928 else
929 #endif
930 /* do not remove the empty statement */
934 free_widget_instance (instance);
937 void
938 lw_destroy_widget (w)
939 Widget w;
941 widget_instance* instance = get_widget_instance (w, True);
943 if (instance)
945 widget_info *info = instance->info;
946 /* instance has already been removed from the list; free it */
947 destroy_one_instance (instance);
948 /* if there are no instances left, free the info too */
949 if (!info->instances)
950 lw_destroy_all_widgets (info->id);
954 void
955 lw_destroy_all_widgets (id)
956 LWLIB_ID id;
958 widget_info* info = get_widget_info (id, True);
959 widget_instance* instance;
960 widget_instance* next;
962 if (info)
964 for (instance = info->instances; instance; )
966 next = instance->next;
967 destroy_one_instance (instance);
968 instance = next;
970 free_widget_info (info);
974 void
975 lw_destroy_everything ()
977 while (all_widget_info)
978 lw_destroy_all_widgets (all_widget_info->id);
981 void
982 lw_destroy_all_pop_ups ()
984 widget_info* info;
985 widget_info* next;
986 widget_instance* instance;
988 for (info = all_widget_info; info; info = next)
990 next = info->next;
991 instance = info->instances;
992 if (instance && instance->pop_up_p)
993 lw_destroy_all_widgets (info->id);
997 #ifdef USE_MOTIF
998 extern Widget first_child (/* Widget */); /* garbage */
999 #endif
1001 Widget
1002 lw_raise_all_pop_up_widgets ()
1004 widget_info* info;
1005 widget_instance* instance;
1006 Widget result = NULL;
1008 for (info = all_widget_info; info; info = info->next)
1009 for (instance = info->instances; instance; instance = instance->next)
1010 if (instance->pop_up_p)
1012 Widget widget = instance->widget;
1013 if (widget)
1015 if (XtIsManaged (widget)
1016 #ifdef USE_MOTIF
1017 /* What a complete load of crap!!!!
1018 When a dialogShell is on the screen, it is not managed!
1020 || (lw_motif_widget_p (instance->widget) &&
1021 XtIsManaged (first_child (widget)))
1022 #endif
1025 if (!result)
1026 result = widget;
1027 XMapRaised (XtDisplay (widget), XtWindow (widget));
1031 return result;
1034 static void
1035 lw_pop_all_widgets (id, up)
1036 LWLIB_ID id;
1037 Boolean up;
1039 widget_info* info = get_widget_info (id, False);
1040 widget_instance* instance;
1042 if (info)
1043 for (instance = info->instances; instance; instance = instance->next)
1044 if (instance->pop_up_p && instance->widget)
1046 #if defined (USE_LUCID)
1047 if (lw_lucid_widget_p (instance->widget))
1049 XtRealizeWidget (instance->widget);
1050 xlw_pop_instance (instance, up);
1052 #endif
1053 #if defined (USE_MOTIF)
1054 if (lw_motif_widget_p (instance->widget))
1056 XtRealizeWidget (instance->widget);
1057 xm_pop_instance (instance, up);
1059 #endif
1060 #if defined (USE_OLIT)
1061 if (lw_olit_widget_p (instance->widget))
1063 XtRealizeWidget (instance->widget);
1064 xol_pop_instance (instance, up);
1066 #endif
1067 #if defined (USE_XAW)
1068 if (lw_xaw_widget_p (instance->widget))
1070 XtRealizeWidget (XtParent (instance->widget));
1071 XtRealizeWidget (instance->widget);
1072 xaw_pop_instance (instance, up);
1074 #endif
1078 void
1079 lw_pop_up_all_widgets (id)
1080 LWLIB_ID id;
1082 lw_pop_all_widgets (id, True);
1085 void
1086 lw_pop_down_all_widgets (id)
1087 LWLIB_ID id;
1089 lw_pop_all_widgets (id, False);
1092 void
1093 lw_popup_menu (widget, event)
1094 Widget widget;
1095 XEvent *event;
1097 #if defined (USE_LUCID)
1098 if (lw_lucid_widget_p (widget))
1099 xlw_popup_menu (widget, event);
1100 #endif
1101 #if defined (USE_MOTIF)
1102 if (lw_motif_widget_p (widget))
1103 xm_popup_menu (widget, event);
1104 #endif
1105 #if defined (USE_OLIT)
1106 if (lw_olit_widget_p (widget))
1107 xol_popup_menu (widget, event);
1108 #endif
1109 #if defined (USE_XAW)
1110 if (lw_xaw_widget_p (widget))
1111 xaw_popup_menu (widget, event);
1112 #endif
1115 \f/* get the values back */
1116 static Boolean
1117 get_one_value (instance, val)
1118 widget_instance* instance;
1119 widget_value* val;
1121 Widget widget = name_to_widget (instance, val->name);
1123 if (widget)
1125 #if defined (USE_LUCID)
1126 if (lw_lucid_widget_p (instance->widget))
1127 xlw_update_one_value (instance, widget, val);
1128 #endif
1129 #if defined (USE_MOTIF)
1130 if (lw_motif_widget_p (instance->widget))
1131 xm_update_one_value (instance, widget, val);
1132 #endif
1133 #if defined (USE_OLIT)
1134 if (lw_olit_widget_p (instance->widget))
1135 xol_update_one_value (instance, widget, val);
1136 #endif
1137 #if defined (USE_XAW)
1138 if (lw_xaw_widget_p (instance->widget))
1139 xaw_update_one_value (instance, widget, val);
1140 #endif
1141 return True;
1143 else
1144 return False;
1147 Boolean
1148 lw_get_some_values (id, val_out)
1149 LWLIB_ID id;
1150 widget_value* val_out;
1152 widget_info* info = get_widget_info (id, False);
1153 widget_instance* instance;
1154 widget_value* val;
1155 Boolean result = False;
1157 if (!info)
1158 return False;
1160 instance = info->instances;
1161 if (!instance)
1162 return False;
1164 for (val = val_out; val; val = val->next)
1165 if (get_one_value (instance, val))
1166 result = True;
1168 return result;
1171 widget_value*
1172 lw_get_all_values (id)
1173 LWLIB_ID id;
1175 widget_info* info = get_widget_info (id, False);
1176 widget_value* val = info->val;
1177 if (lw_get_some_values (id, val))
1178 return val;
1179 else
1180 return NULL;
1183 /* internal function used by the library dependent implementation to get the
1184 widget_value for a given widget in an instance */
1185 widget_value*
1186 lw_get_widget_value_for_widget (instance, w)
1187 widget_instance* instance;
1188 Widget w;
1190 char* name = XtName (w);
1191 widget_value* cur;
1192 for (cur = instance->info->val; cur; cur = cur->next)
1193 if (!strcmp (cur->name, name))
1194 return cur;
1195 return NULL;
1198 \f/* update other instances value when one thing changed */
1199 /* This function can be used as a an XtCallback for the widgets that get
1200 modified to update other instances of the widgets. Closure should be the
1201 widget_instance. */
1202 void
1203 lw_internal_update_other_instances (widget, closure, call_data)
1204 Widget widget;
1205 XtPointer closure;
1206 XtPointer call_data;
1208 /* To forbid recursive calls */
1209 static Boolean updating;
1211 widget_instance* instance = (widget_instance*)closure;
1212 char* name = XtName (widget);
1213 widget_info* info;
1214 widget_instance* cur;
1215 widget_value* val;
1217 /* never recurse as this could cause infinite recursions. */
1218 if (updating)
1219 return;
1221 /* protect against the widget being destroyed */
1222 if (XtWidgetBeingDestroyedP (widget))
1223 return;
1225 /* Return immediately if there are no other instances */
1226 info = instance->info;
1227 if (!info->instances->next)
1228 return;
1230 updating = True;
1232 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1234 if (val && get_one_value (instance, val))
1235 for (cur = info->instances; cur; cur = cur->next)
1236 if (cur != instance)
1237 set_one_value (cur, val, True);
1239 updating = False;
1243 \f/* get the id */
1245 LWLIB_ID
1246 lw_get_widget_id (w)
1247 Widget w;
1249 widget_instance* instance = get_widget_instance (w, False);
1251 return instance ? instance->info->id : 0;
1254 \f/* set the keyboard focus */
1255 void
1256 lw_set_keyboard_focus (parent, w)
1257 Widget parent;
1258 Widget w;
1260 #if defined (USE_MOTIF)
1261 xm_set_keyboard_focus (parent, w);
1262 #else
1263 XtSetKeyboardFocus (parent, w);
1264 #endif
1267 \f/* Show busy */
1268 static void
1269 show_one_widget_busy (w, flag)
1270 Widget w;
1271 Boolean flag;
1273 Pixel foreground = 0;
1274 Pixel background = 1;
1275 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1276 if (!widget_to_invert)
1277 widget_to_invert = w;
1279 XtVaGetValues (widget_to_invert,
1280 XtNforeground, &foreground,
1281 XtNbackground, &background,
1283 XtVaSetValues (widget_to_invert,
1284 XtNforeground, background,
1285 XtNbackground, foreground,
1289 void
1290 lw_show_busy (w, busy)
1291 Widget w;
1292 Boolean busy;
1294 widget_instance* instance = get_widget_instance (w, False);
1295 widget_info* info;
1296 widget_instance* next;
1298 if (instance)
1300 info = instance->info;
1301 if (info->busy != busy)
1303 for (next = info->instances; next; next = next->next)
1304 if (next->widget)
1305 show_one_widget_busy (next->widget, busy);
1306 info->busy = busy;
1311 /* This hack exists because Lucid/Athena need to execute the strange
1312 function below to support geometry management. */
1313 void
1314 lw_refigure_widget (w, doit)
1315 Widget w;
1316 Boolean doit;
1318 #if defined (USE_XAW)
1319 XawPanedSetRefigureMode (w, doit);
1320 #endif
1321 #if defined (USE_MOTIF)
1322 if (doit)
1323 XtManageChild (w);
1324 else
1325 XtUnmanageChild (w);
1326 #endif
1329 /* Toolkit independent way of determining if an event window is in the
1330 menubar. */
1331 Boolean
1332 lw_window_is_in_menubar (win, menubar_widget)
1333 Window win;
1334 Widget menubar_widget;
1336 return menubar_widget
1337 #if defined (USE_LUCID)
1338 && XtWindow (menubar_widget) == win;
1339 #endif
1340 #if defined (USE_MOTIF)
1341 && XtWindowToWidget (XtDisplay (menubar_widget), win)
1342 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1343 == menubar_widget);
1344 #endif
1347 /* Motif hack to set the main window areas. */
1348 void
1349 lw_set_main_areas (parent, menubar, work_area)
1350 Widget parent;
1351 Widget menubar;
1352 Widget work_area;
1354 #if defined (USE_MOTIF)
1355 xm_set_main_areas (parent, menubar, work_area);
1356 #endif
1359 /* Manage resizing for Motif. This disables resizing when the menubar
1360 is about to be modified. */
1361 void
1362 lw_allow_resizing (w, flag)
1363 Widget w;
1364 Boolean flag;
1366 #if defined (USE_MOTIF)
1367 xm_manage_resizing (w, flag);
1368 #endif