(set-visited-file-name): New optional arg NO-QUERY.
[emacs.git] / lwlib / lwlib.c
blobaea3c3b87ca4bf17f39cce8edd2e05a197c5ec55
1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifdef NeXT
22 #undef __STRICT_BSD__ /* ick */
23 #endif
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include "lwlib-int.h"
29 #include "lwlib-utils.h"
30 #include <X11/StringDefs.h>
32 #ifdef __osf__
33 #include <string.h>
34 #include <stdlib.h>
35 extern long *xmalloc();
36 #endif
38 #if defined (USE_LUCID)
39 #include "lwlib-Xlw.h"
40 #endif
41 #if defined (USE_MOTIF)
42 #include "lwlib-Xm.h"
43 #else /* not USE_MOTIF */
44 #if defined (USE_LUCID)
45 #define USE_XAW
46 #endif /* not USE_MOTIF && USE_LUCID */
47 #endif
48 #if defined (USE_OLIT)
49 #include "lwlib-Xol.h"
50 #endif
51 #if defined (USE_XAW)
52 #include "lwlib-Xaw.h"
53 #endif
55 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
56 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
57 #endif
59 #if defined (USE_MOTIF) && defined (USE_OLIT)
60 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
61 #endif
63 #ifndef max
64 #define max(x, y) ((x) > (y) ? (x) : (y))
65 #endif
67 /* List of all widgets managed by the library. */
68 static widget_info*
69 all_widget_info = NULL;
71 #ifdef USE_MOTIF
72 char *lwlib_toolkit_type = "motif";
73 #else
74 char *lwlib_toolkit_type = "lucid";
75 #endif
76 \f/* Forward declarations */
77 static void
78 instantiate_widget_instance (/* widget_instance* instance */);
80 lwlib_memset (address, value, length)
81 char *address;
82 int value;
83 int length;
85 int i;
87 for (i = 0; i < length; i++)
88 address[i] = value;
91 lwlib_bcopy (from, to, length)
92 char *from;
93 char *to;
94 int length;
96 int i;
98 for (i = 0; i < length; i++)
99 to[i] = from[i];
101 \f/* utility functions for widget_instance and widget_info */
102 char *
103 safe_strdup (s)
104 char *s;
106 char *result;
107 if (! s) return 0;
108 result = (char *) malloc (strlen (s) + 1);
109 if (! result)
110 return 0;
111 strcpy (result, s);
112 return result;
115 /* Like strcmp but ignore differences in case. */
117 static int
118 my_strcasecmp (s1, s2)
119 char *s1, *s2;
121 while (1)
123 int c1 = *s1++;
124 int c2 = *s2++;
125 if (isupper (c1))
126 c1 = tolower (c1);
127 if (isupper (c2))
128 c2 = tolower (c2);
129 if (c1 != c2)
130 return (c1 > c2 ? 1 : -1);
131 if (c1 == 0)
132 return 0;
136 static void
137 safe_free_str (s)
138 char *s;
140 if (s) free (s);
143 static widget_value *widget_value_free_list = 0;
144 static int malloc_cpt = 0;
146 widget_value *
147 malloc_widget_value ()
149 widget_value *wv;
150 if (widget_value_free_list)
152 wv = widget_value_free_list;
153 widget_value_free_list = wv->free_list;
154 wv->free_list = 0;
156 else
158 wv = (widget_value *) malloc (sizeof (widget_value));
159 malloc_cpt++;
161 lwlib_memset (wv, 0, sizeof (widget_value));
162 return wv;
165 /* this is analogous to free(). It frees only what was allocated
166 by malloc_widget_value(), and no substructures.
168 void
169 free_widget_value (wv)
170 widget_value *wv;
172 if (wv->free_list)
173 abort ();
175 if (malloc_cpt > 25)
177 /* When the number of already allocated cells is too big,
178 We free it. */
179 free (wv);
180 malloc_cpt--;
182 else
184 wv->free_list = widget_value_free_list;
185 widget_value_free_list = wv;
189 static void
190 free_widget_value_tree (wv)
191 widget_value *wv;
193 if (!wv)
194 return;
196 if (wv->name) free (wv->name);
197 if (wv->value) free (wv->value);
198 if (wv->key) free (wv->key);
200 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
202 if (wv->toolkit_data && wv->free_toolkit_data)
204 XtFree (wv->toolkit_data);
205 wv->toolkit_data = (void *) 0xDEADBEEF;
208 if (wv->contents && (wv->contents != (widget_value*)1))
210 free_widget_value_tree (wv->contents);
211 wv->contents = (widget_value *) 0xDEADBEEF;
213 if (wv->next)
215 free_widget_value_tree (wv->next);
216 wv->next = (widget_value *) 0xDEADBEEF;
218 free_widget_value (wv);
221 static widget_value *
222 copy_widget_value_tree (val, change)
223 widget_value* val;
224 change_type change;
226 widget_value* copy;
228 if (!val)
229 return NULL;
230 if (val == (widget_value *) 1)
231 return val;
233 copy = malloc_widget_value ();
234 copy->name = safe_strdup (val->name);
235 copy->value = safe_strdup (val->value);
236 copy->key = safe_strdup (val->key);
237 copy->enabled = val->enabled;
238 copy->selected = val->selected;
239 copy->edited = False;
240 copy->change = change;
241 copy->this_one_change = change;
242 copy->contents = copy_widget_value_tree (val->contents, change);
243 copy->call_data = val->call_data;
244 copy->next = copy_widget_value_tree (val->next, change);
245 copy->toolkit_data = NULL;
246 copy->free_toolkit_data = False;
247 return copy;
250 static widget_info *
251 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
252 char* type;
253 char* name;
254 LWLIB_ID id;
255 widget_value* val;
256 lw_callback pre_activate_cb;
257 lw_callback selection_cb;
258 lw_callback post_activate_cb;
260 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
261 info->type = safe_strdup (type);
262 info->name = safe_strdup (name);
263 info->id = id;
264 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
265 info->busy = False;
266 info->pre_activate_cb = pre_activate_cb;
267 info->selection_cb = selection_cb;
268 info->post_activate_cb = post_activate_cb;
269 info->instances = NULL;
271 info->next = all_widget_info;
272 all_widget_info = info;
274 return info;
277 static void
278 free_widget_info (info)
279 widget_info* info;
281 safe_free_str (info->type);
282 safe_free_str (info->name);
283 free_widget_value_tree (info->val);
284 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
285 free (info);
288 static void
289 mark_widget_destroyed (widget, closure, call_data)
290 Widget widget;
291 XtPointer closure;
292 XtPointer call_data;
294 widget_instance* instance = (widget_instance*)closure;
296 /* be very conservative */
297 if (instance->widget == widget)
298 instance->widget = NULL;
301 static widget_instance *
302 allocate_widget_instance (info, parent, pop_up_p)
303 widget_info* info;
304 Widget parent;
305 Boolean pop_up_p;
307 widget_instance* instance =
308 (widget_instance*)malloc (sizeof (widget_instance));
309 instance->parent = parent;
310 instance->pop_up_p = pop_up_p;
311 instance->info = info;
312 instance->next = info->instances;
313 info->instances = instance;
315 instantiate_widget_instance (instance);
317 XtAddCallback (instance->widget, XtNdestroyCallback,
318 mark_widget_destroyed, (XtPointer)instance);
319 return instance;
322 static void
323 free_widget_instance (instance)
324 widget_instance* instance;
326 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
327 free (instance);
330 static widget_info *
331 get_widget_info (id, remove_p)
332 LWLIB_ID id;
333 Boolean remove_p;
335 widget_info* info;
336 widget_info* prev;
337 for (prev = NULL, info = all_widget_info;
338 info;
339 prev = info, info = info->next)
340 if (info->id == id)
342 if (remove_p)
344 if (prev)
345 prev->next = info->next;
346 else
347 all_widget_info = info->next;
349 return info;
351 return NULL;
354 /* Internal function used by the library dependent implementation to get the
355 widget_value for a given widget in an instance */
356 widget_info *
357 lw_get_widget_info (id)
358 LWLIB_ID id;
360 return get_widget_info (id, 0);
363 static widget_instance *
364 get_widget_instance (widget, remove_p)
365 Widget widget;
366 Boolean remove_p;
368 widget_info* info;
369 widget_instance* instance;
370 widget_instance* prev;
371 for (info = all_widget_info; info; info = info->next)
372 for (prev = NULL, instance = info->instances;
373 instance;
374 prev = instance, instance = instance->next)
375 if (instance->widget == widget)
377 if (remove_p)
379 if (prev)
380 prev->next = instance->next;
381 else
382 info->instances = instance->next;
384 return instance;
386 return (widget_instance *) 0;
389 static widget_instance*
390 find_instance (id, parent, pop_up_p)
391 LWLIB_ID id;
392 Widget parent;
393 Boolean pop_up_p;
395 widget_info* info = get_widget_info (id, False);
396 widget_instance* instance;
398 if (info)
399 for (instance = info->instances; instance; instance = instance->next)
400 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
401 return instance;
403 return NULL;
407 /* utility function for widget_value */
408 static Boolean
409 safe_strcmp (s1, s2)
410 char* s1;
411 char* s2;
413 if (!!s1 ^ !!s2) return True;
414 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
418 #if 0
419 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
420 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
421 name, \
422 (oc == NO_CHANGE ? "none" : \
423 (oc == INVISIBLE_CHANGE ? "invisible" : \
424 (oc == VISIBLE_CHANGE ? "visible" : \
425 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
426 oc, \
427 (nc == NO_CHANGE ? "none" : \
428 (nc == INVISIBLE_CHANGE ? "invisible" : \
429 (nc == VISIBLE_CHANGE ? "visible" : \
430 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
431 nc, desc, a1, a2)
432 #else
433 # define EXPLAIN(name, oc, nc, desc, a1, a2)
434 #endif
437 static widget_value *
438 merge_widget_value (val1, val2, level)
439 widget_value* val1;
440 widget_value* val2;
441 int level;
443 change_type change, this_one_change;
444 widget_value* merged_next;
445 widget_value* merged_contents;
447 if (!val1)
449 if (val2)
450 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
451 else
452 return NULL;
454 if (!val2)
456 free_widget_value_tree (val1);
457 return NULL;
460 change = NO_CHANGE;
462 if (safe_strcmp (val1->name, val2->name))
464 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
465 val1->name, val2->name);
466 change = max (change, STRUCTURAL_CHANGE);
467 safe_free_str (val1->name);
468 val1->name = safe_strdup (val2->name);
470 if (safe_strcmp (val1->value, val2->value))
472 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
473 val1->value, val2->value);
474 change = max (change, VISIBLE_CHANGE);
475 safe_free_str (val1->value);
476 val1->value = safe_strdup (val2->value);
478 if (safe_strcmp (val1->key, val2->key))
480 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
481 val1->key, val2->key);
482 change = max (change, VISIBLE_CHANGE);
483 safe_free_str (val1->key);
484 val1->key = safe_strdup (val2->key);
486 if (val1->enabled != val2->enabled)
488 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
489 val1->enabled, val2->enabled);
490 change = max (change, VISIBLE_CHANGE);
491 val1->enabled = val2->enabled;
493 if (val1->selected != val2->selected)
495 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
496 val1->selected, val2->selected);
497 change = max (change, VISIBLE_CHANGE);
498 val1->selected = val2->selected;
500 if (val1->call_data != val2->call_data)
502 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
503 val1->call_data, val2->call_data);
504 change = max (change, INVISIBLE_CHANGE);
505 val1->call_data = val2->call_data;
508 if (level > 0)
510 merged_contents =
511 merge_widget_value (val1->contents, val2->contents, level - 1);
513 if (val1->contents && !merged_contents)
515 /* This used to say INVISIBLE_CHANGE,
516 but it is visible and vitally important when
517 the contents of the menu bar itself are entirely deleted.
519 But maybe it doesn't matter. This fails to fix the bug. */
520 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
521 0, 0);
522 change = max (change, STRUCTURAL_CHANGE);
524 else if (merged_contents && merged_contents->change != NO_CHANGE)
526 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
527 0, 0);
528 change = max (change, INVISIBLE_CHANGE);
531 val1->contents = merged_contents;
534 this_one_change = change;
536 merged_next = merge_widget_value (val1->next, val2->next, level);
538 if (val1->next && !merged_next)
540 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
541 0, 0);
542 change = max (change, STRUCTURAL_CHANGE);
544 else if (merged_next)
546 if (merged_next->change)
547 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
548 0, 0);
549 change = max (change, merged_next->change);
552 val1->next = merged_next;
554 val1->this_one_change = this_one_change;
555 val1->change = change;
557 if (change > NO_CHANGE && val1->toolkit_data)
559 if (val1->free_toolkit_data)
560 XtFree (val1->toolkit_data);
561 val1->toolkit_data = NULL;
564 return val1;
568 /* modifying the widgets */
569 static Widget
570 name_to_widget (instance, name)
571 widget_instance* instance;
572 char* name;
574 Widget widget = NULL;
576 if (!instance->widget)
577 return NULL;
579 if (!strcmp (XtName (instance->widget), name))
580 widget = instance->widget;
581 else
583 int length = strlen (name) + 2;
584 char* real_name = (char *) xmalloc (length);
585 real_name [0] = '*';
586 strcpy (real_name + 1, name);
588 widget = XtNameToWidget (instance->widget, real_name);
590 free (real_name);
592 return widget;
595 static void
596 set_one_value (instance, val, deep_p)
597 widget_instance* instance;
598 widget_value* val;
599 Boolean deep_p;
601 Widget widget = name_to_widget (instance, val->name);
603 if (widget)
605 #if defined (USE_LUCID)
606 if (lw_lucid_widget_p (instance->widget))
607 xlw_update_one_widget (instance, widget, val, deep_p);
608 #endif
609 #if defined (USE_MOTIF)
610 if (lw_motif_widget_p (instance->widget))
611 xm_update_one_widget (instance, widget, val, deep_p);
612 #endif
613 #if defined (USE_OLIT)
614 if (lw_olit_widget_p (instance->widget))
615 xol_update_one_widget (instance, widget, val, deep_p);
616 #endif
617 #if defined (USE_XAW)
618 if (lw_xaw_widget_p (instance->widget))
619 xaw_update_one_widget (instance, widget, val, deep_p);
620 #endif
624 static void
625 update_one_widget_instance (instance, deep_p)
626 widget_instance* instance;
627 Boolean deep_p;
629 widget_value *val;
631 if (!instance->widget)
632 /* the widget was destroyed */
633 return;
635 for (val = instance->info->val; val; val = val->next)
636 if (val->change != NO_CHANGE)
637 set_one_value (instance, val, deep_p);
640 static void
641 update_all_widget_values (info, deep_p)
642 widget_info* info;
643 Boolean deep_p;
645 widget_instance* instance;
646 widget_value* val;
648 for (instance = info->instances; instance; instance = instance->next)
649 update_one_widget_instance (instance, deep_p);
651 for (val = info->val; val; val = val->next)
652 val->change = NO_CHANGE;
655 void
656 lw_modify_all_widgets (id, val, deep_p)
657 LWLIB_ID id;
658 widget_value* val;
659 Boolean deep_p;
661 widget_info* info = get_widget_info (id, False);
662 widget_value* new_val;
663 widget_value* next_new_val;
664 widget_value* cur;
665 widget_value* prev;
666 widget_value* next;
667 int found;
669 if (!info)
670 return;
672 for (new_val = val; new_val; new_val = new_val->next)
674 next_new_val = new_val->next;
675 new_val->next = NULL;
676 found = False;
677 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
678 if (!strcmp (cur->name, new_val->name))
680 found = True;
681 next = cur->next;
682 cur->next = NULL;
683 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
684 if (prev)
685 prev->next = cur ? cur : next;
686 else
687 info->val = cur ? cur : next;
688 if (cur)
689 cur->next = next;
690 break;
692 if (!found)
694 /* Could not find it, add it */
695 if (prev)
696 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
697 else
698 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
700 new_val->next = next_new_val;
703 update_all_widget_values (info, deep_p);
707 /* creating the widgets */
709 static void
710 initialize_widget_instance (instance)
711 widget_instance* instance;
713 widget_value* val;
715 for (val = instance->info->val; val; val = val->next)
716 val->change = STRUCTURAL_CHANGE;
718 update_one_widget_instance (instance, True);
720 for (val = instance->info->val; val; val = val->next)
721 val->change = NO_CHANGE;
725 static widget_creation_function
726 find_in_table (type, table)
727 char* type;
728 widget_creation_entry* table;
730 widget_creation_entry* cur;
731 for (cur = table; cur->type; cur++)
732 if (!my_strcasecmp (type, cur->type))
733 return cur->function;
734 return NULL;
737 static Boolean
738 dialog_spec_p (name)
739 char* name;
741 /* return True if name matches [EILPQeilpq][1-9][Bb] or
742 [EILPQeilpq][1-9][Bb][Rr][1-9] */
743 if (!name)
744 return False;
746 switch (name [0])
748 case 'E': case 'I': case 'L': case 'P': case 'Q':
749 case 'e': case 'i': case 'l': case 'p': case 'q':
750 if (name [1] >= '0' && name [1] <= '9')
752 if (name [2] != 'B' && name [2] != 'b')
753 return False;
754 if (!name [3])
755 return True;
756 if ((name [3] == 'T' || name [3] == 't') && !name [4])
757 return True;
758 if ((name [3] == 'R' || name [3] == 'r')
759 && name [4] >= '0' && name [4] <= '9' && !name [5])
760 return True;
761 return False;
763 else
764 return False;
766 default:
767 return False;
771 static void
772 instantiate_widget_instance (instance)
773 widget_instance* instance;
775 widget_creation_function function = NULL;
777 #if defined (USE_LUCID)
778 if (!function)
779 function = find_in_table (instance->info->type, xlw_creation_table);
780 #endif
781 #if defined(USE_MOTIF)
782 if (!function)
783 function = find_in_table (instance->info->type, xm_creation_table);
784 #endif
785 #if defined (USE_OLIT)
786 if (!function)
787 function = find_in_table (instance->info->type, xol_creation_table);
788 #endif
789 #if defined (USE_XAW)
790 if (!function)
791 function = find_in_table (instance->info->type, xaw_creation_table);
792 #endif
794 if (!function)
796 if (dialog_spec_p (instance->info->type))
798 #if defined (USE_LUCID)
799 /* not yet */
800 #endif
801 #if defined(USE_MOTIF)
802 if (!function)
803 function = xm_create_dialog;
804 #endif
805 #if defined (USE_XAW)
806 if (!function)
807 function = xaw_create_dialog;
808 #endif
809 #if defined (USE_OLIT)
810 /* not yet */
811 #endif
815 if (!function)
817 printf ("No creation function for widget type %s\n",
818 instance->info->type);
819 abort ();
822 instance->widget = (*function) (instance);
824 if (!instance->widget)
825 abort ();
827 /* XtRealizeWidget (instance->widget);*/
830 void
831 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
832 char* type;
833 char* name;
834 LWLIB_ID id;
835 widget_value* val;
836 lw_callback pre_activate_cb;
837 lw_callback selection_cb;
838 lw_callback post_activate_cb;
840 if (!get_widget_info (id, False))
841 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
842 post_activate_cb);
845 Widget
846 lw_get_widget (id, parent, pop_up_p)
847 LWLIB_ID id;
848 Widget parent;
849 Boolean pop_up_p;
851 widget_instance* instance;
853 instance = find_instance (id, parent, pop_up_p);
854 return instance ? instance->widget : NULL;
857 Widget
858 lw_make_widget (id, parent, pop_up_p)
859 LWLIB_ID id;
860 Widget parent;
861 Boolean pop_up_p;
863 widget_instance* instance;
864 widget_info* info;
866 instance = find_instance (id, parent, pop_up_p);
867 if (!instance)
869 info = get_widget_info (id, False);
870 if (!info)
871 return NULL;
872 instance = allocate_widget_instance (info, parent, pop_up_p);
873 initialize_widget_instance (instance);
875 if (!instance->widget)
876 abort ();
877 return instance->widget;
880 Widget
881 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
882 char* type;
883 char* name;
884 LWLIB_ID id;
885 widget_value* val;
886 Widget parent;
887 Boolean pop_up_p;
888 lw_callback pre_activate_cb;
889 lw_callback selection_cb;
890 lw_callback post_activate_cb;
892 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
893 post_activate_cb);
894 return lw_make_widget (id, parent, pop_up_p);
898 /* destroying the widgets */
899 static void
900 destroy_one_instance (instance)
901 widget_instance* instance;
903 /* Remove the destroy callback on the widget; that callback will try to
904 dereference the instance object (to set its widget slot to 0, since the
905 widget is dead.) Since the instance is now dead, we don't have to worry
906 about the fact that its widget is dead too.
908 This happens in the Phase2Destroy of the widget, so this callback would
909 not have been run until arbitrarily long after the instance was freed.
911 if (instance->widget)
912 XtRemoveCallback (instance->widget, XtNdestroyCallback,
913 mark_widget_destroyed, (XtPointer)instance);
915 if (instance->widget)
917 /* The else are pretty tricky here, including the empty statement
918 at the end because it would be very bad to destroy a widget
919 twice. */
920 #if defined (USE_LUCID)
921 if (lw_lucid_widget_p (instance->widget))
922 xlw_destroy_instance (instance);
923 else
924 #endif
925 #if defined (USE_MOTIF)
926 if (lw_motif_widget_p (instance->widget))
927 xm_destroy_instance (instance);
928 else
929 #endif
930 #if defined (USE_OLIT)
931 if (lw_olit_widget_p (instance->widget))
932 xol_destroy_instance (instance);
933 else
934 #endif
935 #if defined (USE_XAW)
936 if (lw_xaw_widget_p (instance->widget))
937 xaw_destroy_instance (instance);
938 else
939 #endif
940 /* do not remove the empty statement */
944 free_widget_instance (instance);
947 void
948 lw_destroy_widget (w)
949 Widget w;
951 widget_instance* instance = get_widget_instance (w, True);
953 if (instance)
955 widget_info *info = instance->info;
956 /* instance has already been removed from the list; free it */
957 destroy_one_instance (instance);
958 /* if there are no instances left, free the info too */
959 if (!info->instances)
960 lw_destroy_all_widgets (info->id);
964 void
965 lw_destroy_all_widgets (id)
966 LWLIB_ID id;
968 widget_info* info = get_widget_info (id, True);
969 widget_instance* instance;
970 widget_instance* next;
972 if (info)
974 for (instance = info->instances; instance; )
976 next = instance->next;
977 destroy_one_instance (instance);
978 instance = next;
980 free_widget_info (info);
984 void
985 lw_destroy_everything ()
987 while (all_widget_info)
988 lw_destroy_all_widgets (all_widget_info->id);
991 void
992 lw_destroy_all_pop_ups ()
994 widget_info* info;
995 widget_info* next;
996 widget_instance* instance;
998 for (info = all_widget_info; info; info = next)
1000 next = info->next;
1001 instance = info->instances;
1002 if (instance && instance->pop_up_p)
1003 lw_destroy_all_widgets (info->id);
1007 #ifdef USE_MOTIF
1008 extern Widget first_child (/* Widget */); /* garbage */
1009 #endif
1011 Widget
1012 lw_raise_all_pop_up_widgets ()
1014 widget_info* info;
1015 widget_instance* instance;
1016 Widget result = NULL;
1018 for (info = all_widget_info; info; info = info->next)
1019 for (instance = info->instances; instance; instance = instance->next)
1020 if (instance->pop_up_p)
1022 Widget widget = instance->widget;
1023 if (widget)
1025 if (XtIsManaged (widget)
1026 #ifdef USE_MOTIF
1027 /* What a complete load of crap!!!!
1028 When a dialogShell is on the screen, it is not managed!
1030 || (lw_motif_widget_p (instance->widget) &&
1031 XtIsManaged (first_child (widget)))
1032 #endif
1035 if (!result)
1036 result = widget;
1037 XMapRaised (XtDisplay (widget), XtWindow (widget));
1041 return result;
1044 static void
1045 lw_pop_all_widgets (id, up)
1046 LWLIB_ID id;
1047 Boolean up;
1049 widget_info* info = get_widget_info (id, False);
1050 widget_instance* instance;
1052 if (info)
1053 for (instance = info->instances; instance; instance = instance->next)
1054 if (instance->pop_up_p && instance->widget)
1056 #if defined (USE_LUCID)
1057 if (lw_lucid_widget_p (instance->widget))
1059 XtRealizeWidget (instance->widget);
1060 xlw_pop_instance (instance, up);
1062 #endif
1063 #if defined (USE_MOTIF)
1064 if (lw_motif_widget_p (instance->widget))
1066 XtRealizeWidget (instance->widget);
1067 xm_pop_instance (instance, up);
1069 #endif
1070 #if defined (USE_OLIT)
1071 if (lw_olit_widget_p (instance->widget))
1073 XtRealizeWidget (instance->widget);
1074 xol_pop_instance (instance, up);
1076 #endif
1077 #if defined (USE_XAW)
1078 if (lw_xaw_widget_p (instance->widget))
1080 XtRealizeWidget (XtParent (instance->widget));
1081 XtRealizeWidget (instance->widget);
1082 xaw_pop_instance (instance, up);
1084 #endif
1088 void
1089 lw_pop_up_all_widgets (id)
1090 LWLIB_ID id;
1092 lw_pop_all_widgets (id, True);
1095 void
1096 lw_pop_down_all_widgets (id)
1097 LWLIB_ID id;
1099 lw_pop_all_widgets (id, False);
1102 void
1103 lw_popup_menu (widget, event)
1104 Widget widget;
1105 XEvent *event;
1107 #if defined (USE_LUCID)
1108 if (lw_lucid_widget_p (widget))
1109 xlw_popup_menu (widget, event);
1110 #endif
1111 #if defined (USE_MOTIF)
1112 if (lw_motif_widget_p (widget))
1113 xm_popup_menu (widget, event);
1114 #endif
1115 #if defined (USE_OLIT)
1116 if (lw_olit_widget_p (widget))
1117 xol_popup_menu (widget, event);
1118 #endif
1119 #if defined (USE_XAW)
1120 if (lw_xaw_widget_p (widget))
1121 xaw_popup_menu (widget, event);
1122 #endif
1125 \f/* get the values back */
1126 static Boolean
1127 get_one_value (instance, val)
1128 widget_instance* instance;
1129 widget_value* val;
1131 Widget widget = name_to_widget (instance, val->name);
1133 if (widget)
1135 #if defined (USE_LUCID)
1136 if (lw_lucid_widget_p (instance->widget))
1137 xlw_update_one_value (instance, widget, val);
1138 #endif
1139 #if defined (USE_MOTIF)
1140 if (lw_motif_widget_p (instance->widget))
1141 xm_update_one_value (instance, widget, val);
1142 #endif
1143 #if defined (USE_OLIT)
1144 if (lw_olit_widget_p (instance->widget))
1145 xol_update_one_value (instance, widget, val);
1146 #endif
1147 #if defined (USE_XAW)
1148 if (lw_xaw_widget_p (instance->widget))
1149 xaw_update_one_value (instance, widget, val);
1150 #endif
1151 return True;
1153 else
1154 return False;
1157 Boolean
1158 lw_get_some_values (id, val_out)
1159 LWLIB_ID id;
1160 widget_value* val_out;
1162 widget_info* info = get_widget_info (id, False);
1163 widget_instance* instance;
1164 widget_value* val;
1165 Boolean result = False;
1167 if (!info)
1168 return False;
1170 instance = info->instances;
1171 if (!instance)
1172 return False;
1174 for (val = val_out; val; val = val->next)
1175 if (get_one_value (instance, val))
1176 result = True;
1178 return result;
1181 widget_value*
1182 lw_get_all_values (id)
1183 LWLIB_ID id;
1185 widget_info* info = get_widget_info (id, False);
1186 widget_value* val = info->val;
1187 if (lw_get_some_values (id, val))
1188 return val;
1189 else
1190 return NULL;
1193 /* internal function used by the library dependent implementation to get the
1194 widget_value for a given widget in an instance */
1195 widget_value*
1196 lw_get_widget_value_for_widget (instance, w)
1197 widget_instance* instance;
1198 Widget w;
1200 char* name = XtName (w);
1201 widget_value* cur;
1202 for (cur = instance->info->val; cur; cur = cur->next)
1203 if (!strcmp (cur->name, name))
1204 return cur;
1205 return NULL;
1208 \f/* update other instances value when one thing changed */
1210 /* To forbid recursive calls */
1211 static Boolean lwlib_updating;
1213 /* This function can be used as a an XtCallback for the widgets that get
1214 modified to update other instances of the widgets. Closure should be the
1215 widget_instance. */
1216 void
1217 lw_internal_update_other_instances (widget, closure, call_data)
1218 Widget widget;
1219 XtPointer closure;
1220 XtPointer call_data;
1222 widget_instance* instance = (widget_instance*)closure;
1223 char* name = XtName (widget);
1224 widget_info* info;
1225 widget_instance* cur;
1226 widget_value* val;
1228 /* Avoid possibly infinite recursion. */
1229 if (lwlib_updating)
1230 return;
1232 /* protect against the widget being destroyed */
1233 if (XtWidgetBeingDestroyedP (widget))
1234 return;
1236 /* Return immediately if there are no other instances */
1237 info = instance->info;
1238 if (!info->instances->next)
1239 return;
1241 lwlib_updating = True;
1243 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1245 if (val && get_one_value (instance, val))
1246 for (cur = info->instances; cur; cur = cur->next)
1247 if (cur != instance)
1248 set_one_value (cur, val, True);
1250 lwlib_updating = False;
1254 \f/* get the id */
1256 LWLIB_ID
1257 lw_get_widget_id (w)
1258 Widget w;
1260 widget_instance* instance = get_widget_instance (w, False);
1262 return instance ? instance->info->id : 0;
1265 \f/* set the keyboard focus */
1266 void
1267 lw_set_keyboard_focus (parent, w)
1268 Widget parent;
1269 Widget w;
1271 #if defined (USE_MOTIF)
1272 xm_set_keyboard_focus (parent, w);
1273 #else
1274 XtSetKeyboardFocus (parent, w);
1275 #endif
1278 \f/* Show busy */
1279 static void
1280 show_one_widget_busy (w, flag)
1281 Widget w;
1282 Boolean flag;
1284 Pixel foreground = 0;
1285 Pixel background = 1;
1286 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1287 if (!widget_to_invert)
1288 widget_to_invert = w;
1290 XtVaGetValues (widget_to_invert,
1291 XtNforeground, &foreground,
1292 XtNbackground, &background,
1294 XtVaSetValues (widget_to_invert,
1295 XtNforeground, background,
1296 XtNbackground, foreground,
1300 void
1301 lw_show_busy (w, busy)
1302 Widget w;
1303 Boolean busy;
1305 widget_instance* instance = get_widget_instance (w, False);
1306 widget_info* info;
1307 widget_instance* next;
1309 if (instance)
1311 info = instance->info;
1312 if (info->busy != busy)
1314 for (next = info->instances; next; next = next->next)
1315 if (next->widget)
1316 show_one_widget_busy (next->widget, busy);
1317 info->busy = busy;
1322 /* This hack exists because Lucid/Athena need to execute the strange
1323 function below to support geometry management. */
1324 void
1325 lw_refigure_widget (w, doit)
1326 Widget w;
1327 Boolean doit;
1329 #if defined (USE_XAW)
1330 XawPanedSetRefigureMode (w, doit);
1331 #endif
1332 #if defined (USE_MOTIF)
1333 if (doit)
1334 XtManageChild (w);
1335 else
1336 XtUnmanageChild (w);
1337 #endif
1340 /* Toolkit independent way of determining if an event window is in the
1341 menubar. */
1342 Boolean
1343 lw_window_is_in_menubar (win, menubar_widget)
1344 Window win;
1345 Widget menubar_widget;
1347 return menubar_widget
1348 #if defined (USE_LUCID)
1349 && XtWindow (menubar_widget) == win;
1350 #endif
1351 #if defined (USE_MOTIF)
1352 && ((XtWindow (menubar_widget) == win)
1353 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1354 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1355 == menubar_widget)));
1356 #endif
1359 /* Motif hack to set the main window areas. */
1360 void
1361 lw_set_main_areas (parent, menubar, work_area)
1362 Widget parent;
1363 Widget menubar;
1364 Widget work_area;
1366 #if defined (USE_MOTIF)
1367 xm_set_main_areas (parent, menubar, work_area);
1368 #endif
1371 /* Manage resizing for Motif. This disables resizing when the menubar
1372 is about to be modified. */
1373 void
1374 lw_allow_resizing (w, flag)
1375 Widget w;
1376 Boolean flag;
1378 #if defined (USE_MOTIF)
1379 xm_manage_resizing (w, flag);
1380 #endif