Fixed bug with M-;.
[emacs.git] / lwlib / lwlib.c
blob57edebcd085f5ab443c0cd5e46f84319116d4ed7
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 /* List of all widgets managed by the library. */
57 static widget_info*
58 all_widget_info = NULL;
60 \f/* Forward declarations */
61 static void
62 instanciate_widget_instance (/* widget_instance* instance */);
64 lwlib_memset (address, value, length)
65 char *address;
66 int value;
67 int length;
69 int i;
71 for (i = 0; i < length; i++)
72 address[i] = value;
75 lwlib_bcopy (from, to, length)
76 char *from;
77 char *to;
78 int length;
80 int i;
82 for (i = 0; i < length; i++)
83 to[i] = from[i];
85 \f/* utility functions for widget_instance and widget_info */
86 char *
87 safe_strdup (s)
88 char *s;
90 char *result;
91 if (! s) return 0;
92 result = (char *) malloc (strlen (s) + 1);
93 if (! result)
94 return 0;
95 strcpy (result, s);
96 return result;
99 /* Like strcmp but ignore differences in case. */
101 static int
102 my_strcasecmp (s1, s2)
103 char *s1, *s2;
105 while (1)
107 int c1 = *s1++;
108 int c2 = *s2++;
109 if (isupper (c1))
110 c1 = tolower (c1);
111 if (isupper (c2))
112 c2 = tolower (c2);
113 if (c1 != c2)
114 return (c1 > c2 ? 1 : -1);
115 if (c1 == 0)
116 return 0;
120 static void
121 safe_free_str (s)
122 char *s;
124 if (s) free (s);
127 static widget_value *widget_value_free_list = 0;
128 static int malloc_cpt = 0;
130 widget_value *
131 malloc_widget_value ()
133 widget_value *wv;
134 if (widget_value_free_list)
136 wv = widget_value_free_list;
137 widget_value_free_list = wv->free_list;
138 wv->free_list = 0;
140 else
142 wv = (widget_value *) malloc (sizeof (widget_value));
143 malloc_cpt++;
145 lwlib_memset (wv, 0, sizeof (widget_value));
146 return wv;
149 /* this is analagous to free(). It frees only what was allocated
150 by malloc_widget_value(), and no substructures.
152 void
153 free_widget_value (wv)
154 widget_value *wv;
156 if (wv->free_list)
157 abort ();
159 if (malloc_cpt > 25)
161 /* When the number of already allocated cells is too big,
162 We free it. */
163 free (wv);
164 malloc_cpt--;
166 else
168 wv->free_list = widget_value_free_list;
169 widget_value_free_list = wv;
173 static void
174 free_widget_value_tree (wv)
175 widget_value *wv;
177 if (!wv)
178 return;
180 if (wv->name) free (wv->name);
181 if (wv->value) free (wv->value);
182 if (wv->key) free (wv->key);
184 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
186 if (wv->toolkit_data && wv->free_toolkit_data)
188 free (wv->toolkit_data);
189 wv->toolkit_data = (void *) 0xDEADBEEF;
192 if (wv->contents && (wv->contents != (widget_value*)1))
194 free_widget_value_tree (wv->contents);
195 wv->contents = (widget_value *) 0xDEADBEEF;
197 if (wv->next)
199 free_widget_value_tree (wv->next);
200 wv->next = (widget_value *) 0xDEADBEEF;
202 free_widget_value (wv);
205 static widget_value *
206 copy_widget_value_tree (val, change)
207 widget_value* val;
208 change_type change;
210 widget_value* copy;
212 if (!val)
213 return NULL;
214 if (val == (widget_value *) 1)
215 return val;
217 copy = malloc_widget_value ();
218 copy->name = safe_strdup (val->name);
219 copy->value = safe_strdup (val->value);
220 copy->key = safe_strdup (val->key);
221 copy->enabled = val->enabled;
222 copy->selected = val->selected;
223 copy->edited = False;
224 copy->change = change;
225 copy->contents = copy_widget_value_tree (val->contents, change);
226 copy->call_data = val->call_data;
227 copy->next = copy_widget_value_tree (val->next, change);
228 copy->toolkit_data = NULL;
229 copy->free_toolkit_data = False;
230 return copy;
233 static widget_info *
234 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
235 char* type;
236 char* name;
237 LWLIB_ID id;
238 widget_value* val;
239 lw_callback pre_activate_cb;
240 lw_callback selection_cb;
241 lw_callback post_activate_cb;
243 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
244 info->type = safe_strdup (type);
245 info->name = safe_strdup (name);
246 info->id = id;
247 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
248 info->busy = False;
249 info->pre_activate_cb = pre_activate_cb;
250 info->selection_cb = selection_cb;
251 info->post_activate_cb = post_activate_cb;
252 info->instances = NULL;
254 info->next = all_widget_info;
255 all_widget_info = info;
257 return info;
260 static void
261 free_widget_info (info)
262 widget_info* info;
264 safe_free_str (info->type);
265 safe_free_str (info->name);
266 free_widget_value_tree (info->val);
267 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
268 free (info);
271 static void
272 mark_widget_destroyed (widget, closure, call_data)
273 Widget widget;
274 XtPointer closure;
275 XtPointer call_data;
277 widget_instance* instance = (widget_instance*)closure;
279 /* be very conservative */
280 if (instance->widget == widget)
281 instance->widget = NULL;
284 static widget_instance *
285 allocate_widget_instance (info, parent, pop_up_p)
286 widget_info* info;
287 Widget parent;
288 Boolean pop_up_p;
290 widget_instance* instance =
291 (widget_instance*)malloc (sizeof (widget_instance));
292 instance->parent = parent;
293 instance->pop_up_p = pop_up_p;
294 instance->info = info;
295 instance->next = info->instances;
296 info->instances = instance;
298 instanciate_widget_instance (instance);
300 XtAddCallback (instance->widget, XtNdestroyCallback,
301 mark_widget_destroyed, (XtPointer)instance);
302 return instance;
305 static void
306 free_widget_instance (instance)
307 widget_instance* instance;
309 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
310 free (instance);
313 static widget_info *
314 get_widget_info (id, remove_p)
315 LWLIB_ID id;
316 Boolean remove_p;
318 widget_info* info;
319 widget_info* prev;
320 for (prev = NULL, info = all_widget_info;
321 info;
322 prev = info, info = info->next)
323 if (info->id == id)
325 if (remove_p)
327 if (prev)
328 prev->next = info->next;
329 else
330 all_widget_info = info->next;
332 return info;
334 return NULL;
337 /* Internal function used by the library dependent implementation to get the
338 widget_value for a given widget in an instance */
339 widget_info *
340 lw_get_widget_info (id)
341 LWLIB_ID id;
343 return get_widget_info (id, 0);
346 static widget_instance *
347 get_widget_instance (widget, remove_p)
348 Widget widget;
349 Boolean remove_p;
351 widget_info* info;
352 widget_instance* instance;
353 widget_instance* prev;
354 for (info = all_widget_info; info; info = info->next)
355 for (prev = NULL, instance = info->instances;
356 instance;
357 prev = instance, instance = instance->next)
358 if (instance->widget == widget)
360 if (remove_p)
362 if (prev)
363 prev->next = instance->next;
364 else
365 info->instances = instance->next;
367 return instance;
369 return (widget_instance *) 0;
372 static widget_instance*
373 find_instance (id, parent, pop_up_p)
374 LWLIB_ID id;
375 Widget parent;
376 Boolean pop_up_p;
378 widget_info* info = get_widget_info (id, False);
379 widget_instance* instance;
381 if (info)
382 for (instance = info->instances; instance; instance = instance->next)
383 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
384 return instance;
386 return NULL;
390 /* utility function for widget_value */
391 static Boolean
392 safe_strcmp (s1, s2)
393 char* s1;
394 char* s2;
396 if (!!s1 ^ !!s2) return True;
397 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
400 static int
401 max (i1, i2)
402 int i1;
403 int i2;
405 return i1 > i2 ? i1 : i2;
409 #if 0
410 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
411 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
412 name, \
413 (oc == NO_CHANGE ? "none" : \
414 (oc == INVISIBLE_CHANGE ? "invisible" : \
415 (oc == VISIBLE_CHANGE ? "visible" : \
416 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
417 oc, \
418 (nc == NO_CHANGE ? "none" : \
419 (nc == INVISIBLE_CHANGE ? "invisible" : \
420 (nc == VISIBLE_CHANGE ? "visible" : \
421 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
422 nc, desc, a1, a2)
423 #else
424 # define EXPLAIN(name, oc, nc, desc, a1, a2)
425 #endif
428 static widget_value *
429 merge_widget_value (val1, val2, level)
430 widget_value* val1;
431 widget_value* val2;
432 int level;
434 change_type change;
435 widget_value* merged_next;
436 widget_value* merged_contents;
438 if (!val1)
440 if (val2)
441 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
442 else
443 return NULL;
445 if (!val2)
447 free_widget_value_tree (val1);
448 return NULL;
451 change = NO_CHANGE;
453 if (safe_strcmp (val1->name, val2->name))
455 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
456 val1->name, val2->name);
457 change = max (change, STRUCTURAL_CHANGE);
458 safe_free_str (val1->name);
459 val1->name = safe_strdup (val2->name);
461 if (safe_strcmp (val1->value, val2->value))
463 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
464 val1->value, val2->value);
465 change = max (change, VISIBLE_CHANGE);
466 safe_free_str (val1->value);
467 val1->value = safe_strdup (val2->value);
469 if (safe_strcmp (val1->key, val2->key))
471 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
472 val1->key, val2->key);
473 change = max (change, VISIBLE_CHANGE);
474 safe_free_str (val1->key);
475 val1->key = safe_strdup (val2->key);
477 if (val1->enabled != val2->enabled)
479 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
480 val1->enabled, val2->enabled);
481 change = max (change, VISIBLE_CHANGE);
482 val1->enabled = val2->enabled;
484 if (val1->selected != val2->selected)
486 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
487 val1->selected, val2->selected);
488 change = max (change, VISIBLE_CHANGE);
489 val1->selected = val2->selected;
491 if (val1->call_data != val2->call_data)
493 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
494 val1->call_data, val2->call_data);
495 change = max (change, INVISIBLE_CHANGE);
496 val1->call_data = val2->call_data;
499 if (level > 0)
501 merged_contents =
502 merge_widget_value (val1->contents, val2->contents, level - 1);
504 if (val1->contents && !merged_contents)
506 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
507 0, 0);
508 change = max (change, INVISIBLE_CHANGE);
510 else if (merged_contents && merged_contents->change != NO_CHANGE)
512 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
513 0, 0);
514 change = max (change, INVISIBLE_CHANGE);
517 val1->contents = merged_contents;
520 merged_next = merge_widget_value (val1->next, val2->next, level);
522 if (val1->next && !merged_next)
524 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
525 0, 0);
526 change = max (change, STRUCTURAL_CHANGE);
528 else if (merged_next)
530 if (merged_next->change)
531 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
532 0, 0);
533 change = max (change, merged_next->change);
536 val1->next = merged_next;
538 val1->change = change;
540 if (change > NO_CHANGE && val1->toolkit_data)
542 if (val1->free_toolkit_data)
543 free (val1->toolkit_data);
544 val1->toolkit_data = NULL;
547 return val1;
551 /* modifying the widgets */
552 static Widget
553 name_to_widget (instance, name)
554 widget_instance* instance;
555 char* name;
557 Widget widget = NULL;
559 if (!instance->widget)
560 return NULL;
562 if (!strcmp (XtName (instance->widget), name))
563 widget = instance->widget;
564 else
566 int length = strlen (name) + 2;
567 char* real_name = (char *) xmalloc (length);
568 real_name [0] = '*';
569 strcpy (real_name + 1, name);
571 widget = XtNameToWidget (instance->widget, real_name);
573 free (real_name);
575 return widget;
578 static void
579 set_one_value (instance, val, deep_p)
580 widget_instance* instance;
581 widget_value* val;
582 Boolean deep_p;
584 Widget widget = name_to_widget (instance, val->name);
586 if (widget)
588 #if defined (USE_LUCID)
589 if (lw_lucid_widget_p (instance->widget))
590 xlw_update_one_widget (instance, widget, val, deep_p);
591 #endif
592 #if defined (USE_MOTIF)
593 if (lw_motif_widget_p (instance->widget))
594 xm_update_one_widget (instance, widget, val, deep_p);
595 #endif
596 #if defined (USE_OLIT)
597 if (lw_olit_widget_p (instance->widget))
598 xol_update_one_widget (instance, widget, val, deep_p);
599 #endif
600 #if defined (USE_XAW)
601 if (lw_xaw_widget_p (instance->widget))
602 xaw_update_one_widget (instance, widget, val, deep_p);
603 #endif
607 static void
608 update_one_widget_instance (instance, deep_p)
609 widget_instance* instance;
610 Boolean deep_p;
612 widget_value *val;
614 if (!instance->widget)
615 /* the widget was destroyed */
616 return;
618 for (val = instance->info->val; val; val = val->next)
619 if (val->change != NO_CHANGE)
620 set_one_value (instance, val, deep_p);
623 static void
624 update_all_widget_values (info, deep_p)
625 widget_info* info;
626 Boolean deep_p;
628 widget_instance* instance;
629 widget_value* val;
631 for (instance = info->instances; instance; instance = instance->next)
632 update_one_widget_instance (instance, deep_p);
634 for (val = info->val; val; val = val->next)
635 val->change = NO_CHANGE;
638 void
639 lw_modify_all_widgets (id, val, deep_p)
640 LWLIB_ID id;
641 widget_value* val;
642 Boolean deep_p;
644 widget_info* info = get_widget_info (id, False);
645 widget_value* new_val;
646 widget_value* next_new_val;
647 widget_value* cur;
648 widget_value* prev;
649 widget_value* next;
650 int found;
652 if (!info)
653 return;
655 for (new_val = val; new_val; new_val = new_val->next)
657 next_new_val = new_val->next;
658 new_val->next = NULL;
659 found = False;
660 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
661 if (!strcmp (cur->name, new_val->name))
663 found = True;
664 next = cur->next;
665 cur->next = NULL;
666 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
667 if (prev)
668 prev->next = cur ? cur : next;
669 else
670 info->val = cur ? cur : next;
671 if (cur)
672 cur->next = next;
673 break;
675 if (!found)
677 /* Could not find it, add it */
678 if (prev)
679 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
680 else
681 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
683 new_val->next = next_new_val;
686 update_all_widget_values (info, deep_p);
690 /* creating the widgets */
692 static void
693 initialize_widget_instance (instance)
694 widget_instance* instance;
696 widget_value* val;
698 for (val = instance->info->val; val; val = val->next)
699 val->change = STRUCTURAL_CHANGE;
701 update_one_widget_instance (instance, True);
703 for (val = instance->info->val; val; val = val->next)
704 val->change = NO_CHANGE;
708 static widget_creation_function
709 find_in_table (type, table)
710 char* type;
711 widget_creation_entry* table;
713 widget_creation_entry* cur;
714 for (cur = table; cur->type; cur++)
715 if (!my_strcasecmp (type, cur->type))
716 return cur->function;
717 return NULL;
720 static Boolean
721 dialog_spec_p (name)
722 char* name;
724 /* return True if name matches [EILPQeilpq][1-9][Bb] or
725 [EILPQeilpq][1-9][Bb][Rr][1-9] */
726 if (!name)
727 return False;
729 switch (name [0])
731 case 'E': case 'I': case 'L': case 'P': case 'Q':
732 case 'e': case 'i': case 'l': case 'p': case 'q':
733 if (name [1] >= '0' && name [1] <= '9')
735 if (name [2] != 'B' && name [2] != 'b')
736 return False;
737 if (!name [3])
738 return True;
739 if ((name [3] == 'T' || name [3] == 't') && !name [4])
740 return True;
741 if ((name [3] == 'R' || name [3] == 'r')
742 && name [4] >= '0' && name [4] <= '9' && !name [5])
743 return True;
744 return False;
746 else
747 return False;
749 default:
750 return False;
754 static void
755 instanciate_widget_instance (instance)
756 widget_instance* instance;
758 widget_creation_function function = NULL;
760 #if defined (USE_LUCID)
761 if (!function)
762 function = find_in_table (instance->info->type, xlw_creation_table);
763 #endif
764 #if defined(USE_MOTIF)
765 if (!function)
766 function = find_in_table (instance->info->type, xm_creation_table);
767 #endif
768 #if defined (USE_OLIT)
769 if (!function)
770 function = find_in_table (instance->info->type, xol_creation_table);
771 #endif
772 #if defined (USE_XAW)
773 if (!function)
774 function = find_in_table (instance->info->type, xaw_creation_table);
775 #endif
777 if (!function)
779 if (dialog_spec_p (instance->info->type))
781 #if defined (USE_LUCID)
782 /* not yet */
783 #endif
784 #if defined(USE_MOTIF)
785 if (!function)
786 function = xm_create_dialog;
787 #endif
788 #if defined (USE_XAW)
789 if (!function)
790 function = xaw_create_dialog;
791 #endif
792 #if defined (USE_OLIT)
793 /* not yet */
794 #endif
798 if (!function)
800 printf ("No creation function for widget type %s\n",
801 instance->info->type);
802 abort ();
805 instance->widget = (*function) (instance);
807 if (!instance->widget)
808 abort ();
810 /* XtRealizeWidget (instance->widget);*/
813 void
814 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
815 char* type;
816 char* name;
817 LWLIB_ID id;
818 widget_value* val;
819 lw_callback pre_activate_cb;
820 lw_callback selection_cb;
821 lw_callback post_activate_cb;
823 if (!get_widget_info (id, False))
824 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
825 post_activate_cb);
828 Widget
829 lw_get_widget (id, parent, pop_up_p)
830 LWLIB_ID id;
831 Widget parent;
832 Boolean pop_up_p;
834 widget_instance* instance;
836 instance = find_instance (id, parent, pop_up_p);
837 return instance ? instance->widget : NULL;
840 Widget
841 lw_make_widget (id, parent, pop_up_p)
842 LWLIB_ID id;
843 Widget parent;
844 Boolean pop_up_p;
846 widget_instance* instance;
847 widget_info* info;
849 instance = find_instance (id, parent, pop_up_p);
850 if (!instance)
852 info = get_widget_info (id, False);
853 if (!info)
854 return NULL;
855 instance = allocate_widget_instance (info, parent, pop_up_p);
856 initialize_widget_instance (instance);
858 if (!instance->widget)
859 abort ();
860 return instance->widget;
863 Widget
864 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
865 char* type;
866 char* name;
867 LWLIB_ID id;
868 widget_value* val;
869 Widget parent;
870 Boolean pop_up_p;
871 lw_callback pre_activate_cb;
872 lw_callback selection_cb;
873 lw_callback post_activate_cb;
875 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
876 post_activate_cb);
877 return lw_make_widget (id, parent, pop_up_p);
881 /* destroying the widgets */
882 static void
883 destroy_one_instance (instance)
884 widget_instance* instance;
886 /* Remove the destroy callback on the widget; that callback will try to
887 dereference the instance object (to set its widget slot to 0, since the
888 widget is dead.) Since the instance is now dead, we don't have to worry
889 about the fact that its widget is dead too.
891 This happens in the Phase2Destroy of the widget, so this callback would
892 not have been run until arbitrarily long after the instance was freed.
894 if (instance->widget)
895 XtRemoveCallback (instance->widget, XtNdestroyCallback,
896 mark_widget_destroyed, (XtPointer)instance);
898 if (instance->widget)
900 /* The else are pretty tricky here, including the empty statement
901 at the end because it would be very bad to destroy a widget
902 twice. */
903 #if defined (USE_LUCID)
904 if (lw_lucid_widget_p (instance->widget))
905 xlw_destroy_instance (instance);
906 else
907 #endif
908 #if defined (USE_MOTIF)
909 if (lw_motif_widget_p (instance->widget))
910 xm_destroy_instance (instance);
911 else
912 #endif
913 #if defined (USE_OLIT)
914 if (lw_olit_widget_p (instance->widget))
915 xol_destroy_instance (instance);
916 else
917 #endif
918 #if defined (USE_XAW)
919 if (lw_xaw_widget_p (instance->widget))
920 xaw_destroy_instance (instance);
921 else
922 #endif
923 /* do not remove the empty statement */
927 free_widget_instance (instance);
930 void
931 lw_destroy_widget (w)
932 Widget w;
934 widget_instance* instance = get_widget_instance (w, True);
936 if (instance)
938 widget_info *info = instance->info;
939 /* instance has already been removed from the list; free it */
940 destroy_one_instance (instance);
941 /* if there are no instances left, free the info too */
942 if (!info->instances)
943 lw_destroy_all_widgets (info->id);
947 void
948 lw_destroy_all_widgets (id)
949 LWLIB_ID id;
951 widget_info* info = get_widget_info (id, True);
952 widget_instance* instance;
953 widget_instance* next;
955 if (info)
957 for (instance = info->instances; instance; )
959 next = instance->next;
960 destroy_one_instance (instance);
961 instance = next;
963 free_widget_info (info);
967 void
968 lw_destroy_everything ()
970 while (all_widget_info)
971 lw_destroy_all_widgets (all_widget_info->id);
974 void
975 lw_destroy_all_pop_ups ()
977 widget_info* info;
978 widget_info* next;
979 widget_instance* instance;
981 for (info = all_widget_info; info; info = next)
983 next = info->next;
984 instance = info->instances;
985 if (instance && instance->pop_up_p)
986 lw_destroy_all_widgets (info->id);
990 #ifdef USE_MOTIF
991 extern Widget first_child (Widget); /* garbage */
992 #endif
994 Widget
995 lw_raise_all_pop_up_widgets ()
997 widget_info* info;
998 widget_instance* instance;
999 Widget result = NULL;
1001 for (info = all_widget_info; info; info = info->next)
1002 for (instance = info->instances; instance; instance = instance->next)
1003 if (instance->pop_up_p)
1005 Widget widget = instance->widget;
1006 if (widget)
1008 if (XtIsManaged (widget)
1009 #ifdef USE_MOTIF
1010 /* What a complete load of crap!!!!
1011 When a dialogShell is on the screen, it is not managed!
1013 || (lw_motif_widget_p (instance->widget) &&
1014 XtIsManaged (first_child (widget)))
1015 #endif
1018 if (!result)
1019 result = widget;
1020 XMapRaised (XtDisplay (widget), XtWindow (widget));
1024 return result;
1027 static void
1028 lw_pop_all_widgets (id, up)
1029 LWLIB_ID id;
1030 Boolean up;
1032 widget_info* info = get_widget_info (id, False);
1033 widget_instance* instance;
1035 if (info)
1036 for (instance = info->instances; instance; instance = instance->next)
1037 if (instance->pop_up_p && instance->widget)
1039 #if defined (USE_LUCID)
1040 if (lw_lucid_widget_p (instance->widget))
1042 XtRealizeWidget (instance->widget);
1043 xlw_pop_instance (instance, up);
1045 #endif
1046 #if defined (USE_MOTIF)
1047 if (lw_motif_widget_p (instance->widget))
1049 XtRealizeWidget (instance->widget);
1050 xm_pop_instance (instance, up);
1052 #endif
1053 #if defined (USE_OLIT)
1054 if (lw_olit_widget_p (instance->widget))
1056 XtRealizeWidget (instance->widget);
1057 xol_pop_instance (instance, up);
1059 #endif
1060 #if defined (USE_XAW)
1061 if (lw_xaw_widget_p (instance->widget))
1063 XtRealizeWidget (XtParent (instance->widget));
1064 XtRealizeWidget (instance->widget);
1065 xaw_pop_instance (instance, up);
1067 #endif
1071 void
1072 lw_pop_up_all_widgets (id)
1073 LWLIB_ID id;
1075 lw_pop_all_widgets (id, True);
1078 void
1079 lw_pop_down_all_widgets (id)
1080 LWLIB_ID id;
1082 lw_pop_all_widgets (id, False);
1085 void
1086 lw_popup_menu (widget)
1087 Widget widget;
1089 #if defined (USE_LUCID)
1090 if (lw_lucid_widget_p (widget))
1091 xlw_popup_menu (widget);
1092 #endif
1093 #if defined (USE_MOTIF)
1094 if (lw_motif_widget_p (widget))
1095 xm_popup_menu (widget);
1096 #endif
1097 #if defined (USE_OLIT)
1098 if (lw_olit_widget_p (widget))
1099 xol_popup_menu (widget);
1100 #endif
1101 #if defined (USE_XAW)
1102 if (lw_xaw_widget_p (widget))
1103 xaw_popup_menu (widget);
1104 #endif
1107 \f/* get the values back */
1108 static Boolean
1109 get_one_value (instance, val)
1110 widget_instance* instance;
1111 widget_value* val;
1113 Widget widget = name_to_widget (instance, val->name);
1115 if (widget)
1117 #if defined (USE_LUCID)
1118 if (lw_lucid_widget_p (instance->widget))
1119 xlw_update_one_value (instance, widget, val);
1120 #endif
1121 #if defined (USE_MOTIF)
1122 if (lw_motif_widget_p (instance->widget))
1123 xm_update_one_value (instance, widget, val);
1124 #endif
1125 #if defined (USE_OLIT)
1126 if (lw_olit_widget_p (instance->widget))
1127 xol_update_one_value (instance, widget, val);
1128 #endif
1129 #if defined (USE_XAW)
1130 if (lw_xaw_widget_p (instance->widget))
1131 xaw_update_one_value (instance, widget, val);
1132 #endif
1133 return True;
1135 else
1136 return False;
1139 Boolean
1140 lw_get_some_values (id, val_out)
1141 LWLIB_ID id;
1142 widget_value* val_out;
1144 widget_info* info = get_widget_info (id, False);
1145 widget_instance* instance;
1146 widget_value* val;
1147 Boolean result = False;
1149 if (!info)
1150 return False;
1152 instance = info->instances;
1153 if (!instance)
1154 return False;
1156 for (val = val_out; val; val = val->next)
1157 if (get_one_value (instance, val))
1158 result = True;
1160 return result;
1163 widget_value*
1164 lw_get_all_values (id)
1165 LWLIB_ID id;
1167 widget_info* info = get_widget_info (id, False);
1168 widget_value* val = info->val;
1169 if (lw_get_some_values (id, val))
1170 return val;
1171 else
1172 return NULL;
1175 /* internal function used by the library dependent implementation to get the
1176 widget_value for a given widget in an instance */
1177 widget_value*
1178 lw_get_widget_value_for_widget (instance, w)
1179 widget_instance* instance;
1180 Widget w;
1182 char* name = XtName (w);
1183 widget_value* cur;
1184 for (cur = instance->info->val; cur; cur = cur->next)
1185 if (!strcmp (cur->name, name))
1186 return cur;
1187 return NULL;
1190 \f/* update other instances value when one thing changed */
1191 /* This function can be used as a an XtCallback for the widgets that get
1192 modified to update other instances of the widgets. Closure should be the
1193 widget_instance. */
1194 void
1195 lw_internal_update_other_instances (widget, closure, call_data)
1196 Widget widget;
1197 XtPointer closure;
1198 XtPointer call_data;
1200 /* To forbid recursive calls */
1201 static Boolean updating;
1203 widget_instance* instance = (widget_instance*)closure;
1204 char* name = XtName (widget);
1205 widget_info* info;
1206 widget_instance* cur;
1207 widget_value* val;
1209 /* never recurse as this could cause infinite recursions. */
1210 if (updating)
1211 return;
1213 /* protect against the widget being destroyed */
1214 if (XtWidgetBeingDestroyedP (widget))
1215 return;
1217 /* Return immediately if there are no other instances */
1218 info = instance->info;
1219 if (!info->instances->next)
1220 return;
1222 updating = True;
1224 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1226 if (val && get_one_value (instance, val))
1227 for (cur = info->instances; cur; cur = cur->next)
1228 if (cur != instance)
1229 set_one_value (cur, val, True);
1231 updating = False;
1235 \f/* get the id */
1237 LWLIB_ID
1238 lw_get_widget_id (w)
1239 Widget w;
1241 widget_instance* instance = get_widget_instance (w, False);
1243 return instance ? instance->info->id : 0;
1246 \f/* set the keyboard focus */
1247 void
1248 lw_set_keyboard_focus (parent, w)
1249 Widget parent;
1250 Widget w;
1252 #if defined (USE_MOTIF)
1253 xm_set_keyboard_focus (parent, w);
1254 #else
1255 XtSetKeyboardFocus (parent, w);
1256 #endif
1259 \f/* Show busy */
1260 static void
1261 show_one_widget_busy (w, flag)
1262 Widget w;
1263 Boolean flag;
1265 Pixel foreground = 0;
1266 Pixel background = 1;
1267 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1268 if (!widget_to_invert)
1269 widget_to_invert = w;
1271 XtVaGetValues (widget_to_invert,
1272 XtNforeground, &foreground,
1273 XtNbackground, &background,
1275 XtVaSetValues (widget_to_invert,
1276 XtNforeground, background,
1277 XtNbackground, foreground,
1281 void
1282 lw_show_busy (w, busy)
1283 Widget w;
1284 Boolean busy;
1286 widget_instance* instance = get_widget_instance (w, False);
1287 widget_info* info;
1288 widget_instance* next;
1290 if (instance)
1292 info = instance->info;
1293 if (info->busy != busy)
1295 for (next = info->instances; next; next = next->next)
1296 if (next->widget)
1297 show_one_widget_busy (next->widget, busy);
1298 info->busy = busy;