(decode_mode_spec): Initialize and use `p' (for the termcap case).
[emacs.git] / lwlib / lwlib.c
blob981c92e568654d36e10f43725b2853478fbe6f6c
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);
529 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
530 #ifdef USE_MOTIF
531 change = max (merged_contents->change, change);
532 #endif
533 #endif
536 val1->contents = merged_contents;
539 this_one_change = change;
541 merged_next = merge_widget_value (val1->next, val2->next, level);
543 if (val1->next && !merged_next)
545 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
546 0, 0);
547 change = max (change, STRUCTURAL_CHANGE);
549 else if (merged_next)
551 if (merged_next->change)
552 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
553 0, 0);
554 change = max (change, merged_next->change);
557 val1->next = merged_next;
559 val1->this_one_change = this_one_change;
560 val1->change = change;
562 if (change > NO_CHANGE && val1->toolkit_data)
564 if (val1->free_toolkit_data)
565 XtFree (val1->toolkit_data);
566 val1->toolkit_data = NULL;
569 return val1;
573 /* modifying the widgets */
574 static Widget
575 name_to_widget (instance, name)
576 widget_instance* instance;
577 char* name;
579 Widget widget = NULL;
581 if (!instance->widget)
582 return NULL;
584 if (!strcmp (XtName (instance->widget), name))
585 widget = instance->widget;
586 else
588 int length = strlen (name) + 2;
589 char* real_name = (char *) xmalloc (length);
590 real_name [0] = '*';
591 strcpy (real_name + 1, name);
593 widget = XtNameToWidget (instance->widget, real_name);
595 free (real_name);
597 return widget;
600 static void
601 set_one_value (instance, val, deep_p)
602 widget_instance* instance;
603 widget_value* val;
604 Boolean deep_p;
606 Widget widget = name_to_widget (instance, val->name);
608 if (widget)
610 #if defined (USE_LUCID)
611 if (lw_lucid_widget_p (instance->widget))
612 xlw_update_one_widget (instance, widget, val, deep_p);
613 #endif
614 #if defined (USE_MOTIF)
615 if (lw_motif_widget_p (instance->widget))
616 xm_update_one_widget (instance, widget, val, deep_p);
617 #endif
618 #if defined (USE_OLIT)
619 if (lw_olit_widget_p (instance->widget))
620 xol_update_one_widget (instance, widget, val, deep_p);
621 #endif
622 #if defined (USE_XAW)
623 if (lw_xaw_widget_p (instance->widget))
624 xaw_update_one_widget (instance, widget, val, deep_p);
625 #endif
629 static void
630 update_one_widget_instance (instance, deep_p)
631 widget_instance* instance;
632 Boolean deep_p;
634 widget_value *val;
636 if (!instance->widget)
637 /* the widget was destroyed */
638 return;
640 for (val = instance->info->val; val; val = val->next)
641 if (val->change != NO_CHANGE)
642 set_one_value (instance, val, deep_p);
645 static void
646 update_all_widget_values (info, deep_p)
647 widget_info* info;
648 Boolean deep_p;
650 widget_instance* instance;
651 widget_value* val;
653 for (instance = info->instances; instance; instance = instance->next)
654 update_one_widget_instance (instance, deep_p);
656 for (val = info->val; val; val = val->next)
657 val->change = NO_CHANGE;
660 void
661 lw_modify_all_widgets (id, val, deep_p)
662 LWLIB_ID id;
663 widget_value* val;
664 Boolean deep_p;
666 widget_info* info = get_widget_info (id, False);
667 widget_value* new_val;
668 widget_value* next_new_val;
669 widget_value* cur;
670 widget_value* prev;
671 widget_value* next;
672 int found;
674 if (!info)
675 return;
677 for (new_val = val; new_val; new_val = new_val->next)
679 next_new_val = new_val->next;
680 new_val->next = NULL;
681 found = False;
682 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
683 if (!strcmp (cur->name, new_val->name))
685 found = True;
686 next = cur->next;
687 cur->next = NULL;
688 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
689 if (prev)
690 prev->next = cur ? cur : next;
691 else
692 info->val = cur ? cur : next;
693 if (cur)
694 cur->next = next;
695 break;
697 if (!found)
699 /* Could not find it, add it */
700 if (prev)
701 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
702 else
703 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
705 new_val->next = next_new_val;
708 update_all_widget_values (info, deep_p);
712 /* creating the widgets */
714 static void
715 initialize_widget_instance (instance)
716 widget_instance* instance;
718 widget_value* val;
720 for (val = instance->info->val; val; val = val->next)
721 val->change = STRUCTURAL_CHANGE;
723 update_one_widget_instance (instance, True);
725 for (val = instance->info->val; val; val = val->next)
726 val->change = NO_CHANGE;
730 static widget_creation_function
731 find_in_table (type, table)
732 char* type;
733 widget_creation_entry* table;
735 widget_creation_entry* cur;
736 for (cur = table; cur->type; cur++)
737 if (!my_strcasecmp (type, cur->type))
738 return cur->function;
739 return NULL;
742 static Boolean
743 dialog_spec_p (name)
744 char* name;
746 /* return True if name matches [EILPQeilpq][1-9][Bb] or
747 [EILPQeilpq][1-9][Bb][Rr][1-9] */
748 if (!name)
749 return False;
751 switch (name [0])
753 case 'E': case 'I': case 'L': case 'P': case 'Q':
754 case 'e': case 'i': case 'l': case 'p': case 'q':
755 if (name [1] >= '0' && name [1] <= '9')
757 if (name [2] != 'B' && name [2] != 'b')
758 return False;
759 if (!name [3])
760 return True;
761 if ((name [3] == 'T' || name [3] == 't') && !name [4])
762 return True;
763 if ((name [3] == 'R' || name [3] == 'r')
764 && name [4] >= '0' && name [4] <= '9' && !name [5])
765 return True;
766 return False;
768 else
769 return False;
771 default:
772 return False;
776 static void
777 instantiate_widget_instance (instance)
778 widget_instance* instance;
780 widget_creation_function function = NULL;
782 #if defined (USE_LUCID)
783 if (!function)
784 function = find_in_table (instance->info->type, xlw_creation_table);
785 #endif
786 #if defined(USE_MOTIF)
787 if (!function)
788 function = find_in_table (instance->info->type, xm_creation_table);
789 #endif
790 #if defined (USE_OLIT)
791 if (!function)
792 function = find_in_table (instance->info->type, xol_creation_table);
793 #endif
794 #if defined (USE_XAW)
795 if (!function)
796 function = find_in_table (instance->info->type, xaw_creation_table);
797 #endif
799 if (!function)
801 if (dialog_spec_p (instance->info->type))
803 #if defined (USE_LUCID)
804 /* not yet */
805 #endif
806 #if defined(USE_MOTIF)
807 if (!function)
808 function = xm_create_dialog;
809 #endif
810 #if defined (USE_XAW)
811 if (!function)
812 function = xaw_create_dialog;
813 #endif
814 #if defined (USE_OLIT)
815 /* not yet */
816 #endif
820 if (!function)
822 printf ("No creation function for widget type %s\n",
823 instance->info->type);
824 abort ();
827 instance->widget = (*function) (instance);
829 if (!instance->widget)
830 abort ();
832 /* XtRealizeWidget (instance->widget);*/
835 void
836 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
837 char* type;
838 char* name;
839 LWLIB_ID id;
840 widget_value* val;
841 lw_callback pre_activate_cb;
842 lw_callback selection_cb;
843 lw_callback post_activate_cb;
845 if (!get_widget_info (id, False))
846 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
847 post_activate_cb);
850 Widget
851 lw_get_widget (id, parent, pop_up_p)
852 LWLIB_ID id;
853 Widget parent;
854 Boolean pop_up_p;
856 widget_instance* instance;
858 instance = find_instance (id, parent, pop_up_p);
859 return instance ? instance->widget : NULL;
862 Widget
863 lw_make_widget (id, parent, pop_up_p)
864 LWLIB_ID id;
865 Widget parent;
866 Boolean pop_up_p;
868 widget_instance* instance;
869 widget_info* info;
871 instance = find_instance (id, parent, pop_up_p);
872 if (!instance)
874 info = get_widget_info (id, False);
875 if (!info)
876 return NULL;
877 instance = allocate_widget_instance (info, parent, pop_up_p);
878 initialize_widget_instance (instance);
880 if (!instance->widget)
881 abort ();
882 return instance->widget;
885 Widget
886 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
887 char* type;
888 char* name;
889 LWLIB_ID id;
890 widget_value* val;
891 Widget parent;
892 Boolean pop_up_p;
893 lw_callback pre_activate_cb;
894 lw_callback selection_cb;
895 lw_callback post_activate_cb;
897 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
898 post_activate_cb);
899 return lw_make_widget (id, parent, pop_up_p);
903 /* destroying the widgets */
904 static void
905 destroy_one_instance (instance)
906 widget_instance* instance;
908 /* Remove the destroy callback on the widget; that callback will try to
909 dereference the instance object (to set its widget slot to 0, since the
910 widget is dead.) Since the instance is now dead, we don't have to worry
911 about the fact that its widget is dead too.
913 This happens in the Phase2Destroy of the widget, so this callback would
914 not have been run until arbitrarily long after the instance was freed.
916 if (instance->widget)
917 XtRemoveCallback (instance->widget, XtNdestroyCallback,
918 mark_widget_destroyed, (XtPointer)instance);
920 if (instance->widget)
922 /* The else are pretty tricky here, including the empty statement
923 at the end because it would be very bad to destroy a widget
924 twice. */
925 #if defined (USE_LUCID)
926 if (lw_lucid_widget_p (instance->widget))
927 xlw_destroy_instance (instance);
928 else
929 #endif
930 #if defined (USE_MOTIF)
931 if (lw_motif_widget_p (instance->widget))
932 xm_destroy_instance (instance);
933 else
934 #endif
935 #if defined (USE_OLIT)
936 if (lw_olit_widget_p (instance->widget))
937 xol_destroy_instance (instance);
938 else
939 #endif
940 #if defined (USE_XAW)
941 if (lw_xaw_widget_p (instance->widget))
942 xaw_destroy_instance (instance);
943 else
944 #endif
945 /* do not remove the empty statement */
949 free_widget_instance (instance);
952 void
953 lw_destroy_widget (w)
954 Widget w;
956 widget_instance* instance = get_widget_instance (w, True);
958 if (instance)
960 widget_info *info = instance->info;
961 /* instance has already been removed from the list; free it */
962 destroy_one_instance (instance);
963 /* if there are no instances left, free the info too */
964 if (!info->instances)
965 lw_destroy_all_widgets (info->id);
969 void
970 lw_destroy_all_widgets (id)
971 LWLIB_ID id;
973 widget_info* info = get_widget_info (id, True);
974 widget_instance* instance;
975 widget_instance* next;
977 if (info)
979 for (instance = info->instances; instance; )
981 next = instance->next;
982 destroy_one_instance (instance);
983 instance = next;
985 free_widget_info (info);
989 void
990 lw_destroy_everything ()
992 while (all_widget_info)
993 lw_destroy_all_widgets (all_widget_info->id);
996 void
997 lw_destroy_all_pop_ups ()
999 widget_info* info;
1000 widget_info* next;
1001 widget_instance* instance;
1003 for (info = all_widget_info; info; info = next)
1005 next = info->next;
1006 instance = info->instances;
1007 if (instance && instance->pop_up_p)
1008 lw_destroy_all_widgets (info->id);
1012 #ifdef USE_MOTIF
1013 extern Widget first_child (/* Widget */); /* garbage */
1014 #endif
1016 Widget
1017 lw_raise_all_pop_up_widgets ()
1019 widget_info* info;
1020 widget_instance* instance;
1021 Widget result = NULL;
1023 for (info = all_widget_info; info; info = info->next)
1024 for (instance = info->instances; instance; instance = instance->next)
1025 if (instance->pop_up_p)
1027 Widget widget = instance->widget;
1028 if (widget)
1030 if (XtIsManaged (widget)
1031 #ifdef USE_MOTIF
1032 /* What a complete load of crap!!!!
1033 When a dialogShell is on the screen, it is not managed!
1035 || (lw_motif_widget_p (instance->widget) &&
1036 XtIsManaged (first_child (widget)))
1037 #endif
1040 if (!result)
1041 result = widget;
1042 XMapRaised (XtDisplay (widget), XtWindow (widget));
1046 return result;
1049 static void
1050 lw_pop_all_widgets (id, up)
1051 LWLIB_ID id;
1052 Boolean up;
1054 widget_info* info = get_widget_info (id, False);
1055 widget_instance* instance;
1057 if (info)
1058 for (instance = info->instances; instance; instance = instance->next)
1059 if (instance->pop_up_p && instance->widget)
1061 #if defined (USE_LUCID)
1062 if (lw_lucid_widget_p (instance->widget))
1064 XtRealizeWidget (instance->widget);
1065 xlw_pop_instance (instance, up);
1067 #endif
1068 #if defined (USE_MOTIF)
1069 if (lw_motif_widget_p (instance->widget))
1071 XtRealizeWidget (instance->widget);
1072 xm_pop_instance (instance, up);
1074 #endif
1075 #if defined (USE_OLIT)
1076 if (lw_olit_widget_p (instance->widget))
1078 XtRealizeWidget (instance->widget);
1079 xol_pop_instance (instance, up);
1081 #endif
1082 #if defined (USE_XAW)
1083 if (lw_xaw_widget_p (instance->widget))
1085 XtRealizeWidget (XtParent (instance->widget));
1086 XtRealizeWidget (instance->widget);
1087 xaw_pop_instance (instance, up);
1089 #endif
1093 void
1094 lw_pop_up_all_widgets (id)
1095 LWLIB_ID id;
1097 lw_pop_all_widgets (id, True);
1100 void
1101 lw_pop_down_all_widgets (id)
1102 LWLIB_ID id;
1104 lw_pop_all_widgets (id, False);
1107 void
1108 lw_popup_menu (widget, event)
1109 Widget widget;
1110 XEvent *event;
1112 #if defined (USE_LUCID)
1113 if (lw_lucid_widget_p (widget))
1114 xlw_popup_menu (widget, event);
1115 #endif
1116 #if defined (USE_MOTIF)
1117 if (lw_motif_widget_p (widget))
1118 xm_popup_menu (widget, event);
1119 #endif
1120 #if defined (USE_OLIT)
1121 if (lw_olit_widget_p (widget))
1122 xol_popup_menu (widget, event);
1123 #endif
1124 #if defined (USE_XAW)
1125 if (lw_xaw_widget_p (widget))
1126 xaw_popup_menu (widget, event);
1127 #endif
1130 \f/* get the values back */
1131 static Boolean
1132 get_one_value (instance, val)
1133 widget_instance* instance;
1134 widget_value* val;
1136 Widget widget = name_to_widget (instance, val->name);
1138 if (widget)
1140 #if defined (USE_LUCID)
1141 if (lw_lucid_widget_p (instance->widget))
1142 xlw_update_one_value (instance, widget, val);
1143 #endif
1144 #if defined (USE_MOTIF)
1145 if (lw_motif_widget_p (instance->widget))
1146 xm_update_one_value (instance, widget, val);
1147 #endif
1148 #if defined (USE_OLIT)
1149 if (lw_olit_widget_p (instance->widget))
1150 xol_update_one_value (instance, widget, val);
1151 #endif
1152 #if defined (USE_XAW)
1153 if (lw_xaw_widget_p (instance->widget))
1154 xaw_update_one_value (instance, widget, val);
1155 #endif
1156 return True;
1158 else
1159 return False;
1162 Boolean
1163 lw_get_some_values (id, val_out)
1164 LWLIB_ID id;
1165 widget_value* val_out;
1167 widget_info* info = get_widget_info (id, False);
1168 widget_instance* instance;
1169 widget_value* val;
1170 Boolean result = False;
1172 if (!info)
1173 return False;
1175 instance = info->instances;
1176 if (!instance)
1177 return False;
1179 for (val = val_out; val; val = val->next)
1180 if (get_one_value (instance, val))
1181 result = True;
1183 return result;
1186 widget_value*
1187 lw_get_all_values (id)
1188 LWLIB_ID id;
1190 widget_info* info = get_widget_info (id, False);
1191 widget_value* val = info->val;
1192 if (lw_get_some_values (id, val))
1193 return val;
1194 else
1195 return NULL;
1198 /* internal function used by the library dependent implementation to get the
1199 widget_value for a given widget in an instance */
1200 widget_value*
1201 lw_get_widget_value_for_widget (instance, w)
1202 widget_instance* instance;
1203 Widget w;
1205 char* name = XtName (w);
1206 widget_value* cur;
1207 for (cur = instance->info->val; cur; cur = cur->next)
1208 if (!strcmp (cur->name, name))
1209 return cur;
1210 return NULL;
1213 \f/* update other instances value when one thing changed */
1215 /* To forbid recursive calls */
1216 static Boolean lwlib_updating;
1218 /* This function can be used as a an XtCallback for the widgets that get
1219 modified to update other instances of the widgets. Closure should be the
1220 widget_instance. */
1221 void
1222 lw_internal_update_other_instances (widget, closure, call_data)
1223 Widget widget;
1224 XtPointer closure;
1225 XtPointer call_data;
1227 widget_instance* instance = (widget_instance*)closure;
1228 char* name = XtName (widget);
1229 widget_info* info;
1230 widget_instance* cur;
1231 widget_value* val;
1233 /* Avoid possibly infinite recursion. */
1234 if (lwlib_updating)
1235 return;
1237 /* protect against the widget being destroyed */
1238 if (XtWidgetBeingDestroyedP (widget))
1239 return;
1241 /* Return immediately if there are no other instances */
1242 info = instance->info;
1243 if (!info->instances->next)
1244 return;
1246 lwlib_updating = True;
1248 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1250 if (val && get_one_value (instance, val))
1251 for (cur = info->instances; cur; cur = cur->next)
1252 if (cur != instance)
1253 set_one_value (cur, val, True);
1255 lwlib_updating = False;
1259 \f/* get the id */
1261 LWLIB_ID
1262 lw_get_widget_id (w)
1263 Widget w;
1265 widget_instance* instance = get_widget_instance (w, False);
1267 return instance ? instance->info->id : 0;
1270 \f/* set the keyboard focus */
1271 void
1272 lw_set_keyboard_focus (parent, w)
1273 Widget parent;
1274 Widget w;
1276 #if defined (USE_MOTIF)
1277 xm_set_keyboard_focus (parent, w);
1278 #else
1279 XtSetKeyboardFocus (parent, w);
1280 #endif
1283 \f/* Show busy */
1284 static void
1285 show_one_widget_busy (w, flag)
1286 Widget w;
1287 Boolean flag;
1289 Pixel foreground = 0;
1290 Pixel background = 1;
1291 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1292 if (!widget_to_invert)
1293 widget_to_invert = w;
1295 XtVaGetValues (widget_to_invert,
1296 XtNforeground, &foreground,
1297 XtNbackground, &background,
1299 XtVaSetValues (widget_to_invert,
1300 XtNforeground, background,
1301 XtNbackground, foreground,
1305 void
1306 lw_show_busy (w, busy)
1307 Widget w;
1308 Boolean busy;
1310 widget_instance* instance = get_widget_instance (w, False);
1311 widget_info* info;
1312 widget_instance* next;
1314 if (instance)
1316 info = instance->info;
1317 if (info->busy != busy)
1319 for (next = info->instances; next; next = next->next)
1320 if (next->widget)
1321 show_one_widget_busy (next->widget, busy);
1322 info->busy = busy;
1327 /* This hack exists because Lucid/Athena need to execute the strange
1328 function below to support geometry management. */
1329 void
1330 lw_refigure_widget (w, doit)
1331 Widget w;
1332 Boolean doit;
1334 #if defined (USE_XAW)
1335 XawPanedSetRefigureMode (w, doit);
1336 #endif
1337 #if defined (USE_MOTIF)
1338 if (doit)
1339 XtManageChild (w);
1340 else
1341 XtUnmanageChild (w);
1342 #endif
1345 /* Toolkit independent way of determining if an event window is in the
1346 menubar. */
1347 Boolean
1348 lw_window_is_in_menubar (win, menubar_widget)
1349 Window win;
1350 Widget menubar_widget;
1352 return menubar_widget
1353 #if defined (USE_LUCID)
1354 && XtWindow (menubar_widget) == win;
1355 #endif
1356 #if defined (USE_MOTIF)
1357 && ((XtWindow (menubar_widget) == win)
1358 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1359 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1360 == menubar_widget)));
1361 #endif
1364 /* Motif hack to set the main window areas. */
1365 void
1366 lw_set_main_areas (parent, menubar, work_area)
1367 Widget parent;
1368 Widget menubar;
1369 Widget work_area;
1371 #if defined (USE_MOTIF)
1372 xm_set_main_areas (parent, menubar, work_area);
1373 #endif
1376 /* Manage resizing for Motif. This disables resizing when the menubar
1377 is about to be modified. */
1378 void
1379 lw_allow_resizing (w, flag)
1380 Widget w;
1381 Boolean flag;
1383 #if defined (USE_MOTIF)
1384 xm_manage_resizing (w, flag);
1385 #endif