1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993, 1994 Lucid, Inc.
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
5 This file is part of the Lucid Widget Library.
7 The Lucid Widget Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 The Lucid Widget Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 #undef __STRICT_BSD__ /* ick */
30 #include <sys/types.h>
34 #include <X11/StringDefs.h>
35 #include "lwlib-internal.h"
36 #include "lwlib-utils.h"
39 #include "lwlib-Xlw.h"
45 #include "lwlib-Xaw.h"
48 /* #### Does a check need to be put back in here to make sure we have
49 sufficient defines to function properly or are the checks in the
50 makefile sufficient? */
52 /* List of all widgets managed by the library. Note that each "widget"
53 listed here may actually be a tree of widgets; for example, a
54 single entry here might represent a single menubar or popup menu,
55 each of which might be implemented with a tree of widgets.
57 static widget_info *all_widget_info = NULL;
59 /* boolean flag indicating that the menubar is active */
60 int lw_menu_active = 0;
62 /* X11 menubar widget */
63 Widget lw_menubar_widget = NULL;
65 /* whether the last menu operation was a keyboard accelerator */
66 int lw_menu_accelerate = False;
69 /* Forward declarations */
71 instantiate_widget_instance (widget_instance *instance);
74 /* utility functions for widget_instance and widget_info */
76 safe_strdup (CONST char *s)
80 result = (char *) malloc (strlen (s) + 1);
88 safe_free_str (char *s)
93 static widget_value *widget_value_free_list = 0;
96 malloc_widget_value (void)
99 if (widget_value_free_list)
101 wv = widget_value_free_list;
102 widget_value_free_list = wv->free_list;
107 wv = (widget_value *) malloc (sizeof (widget_value));
111 memset (wv, 0, sizeof (widget_value));
116 /* this is analogous to free(). It frees only what was allocated
117 by malloc_widget_value(), and no substructures.
120 free_widget_value (widget_value *wv)
124 wv->free_list = widget_value_free_list;
125 widget_value_free_list = wv;
128 static void free_widget_value_tree (widget_value *wv);
131 free_widget_value_contents (widget_value *wv)
133 if (wv->name) free (wv->name);
134 if (wv->value) free (wv->value);
135 if (wv->key) free (wv->key);
137 /* #### - all of this 0xDEADBEEF stuff should be unnecessary
138 in production code... it should be conditionalized. */
139 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
141 if (wv->toolkit_data && wv->free_toolkit_data)
143 XtFree ((char *) wv->toolkit_data);
144 wv->toolkit_data = (void *) 0xDEADBEEF;
146 #ifdef NEED_SCROLLBARS
147 if (wv->scrollbar_data)
149 free (wv->scrollbar_data);
150 wv->scrollbar_data = NULL;
153 if (wv->contents && (wv->contents != (widget_value*)1))
155 free_widget_value_tree (wv->contents);
156 wv->contents = (widget_value *) 0xDEADBEEF;
160 free_widget_value_tree (wv->next);
161 wv->next = (widget_value *) 0xDEADBEEF;
166 free_widget_value_tree (widget_value *wv)
171 free_widget_value_contents (wv);
172 free_widget_value (wv);
175 #ifdef NEED_SCROLLBARS
178 copy_scrollbar_values (widget_value *val, widget_value *copy)
180 if (!copy->scrollbar_data)
181 copy->scrollbar_data =
182 (scrollbar_values *) malloc (sizeof (scrollbar_values));
184 if (val->scrollbar_data)
185 *copy->scrollbar_data = *val->scrollbar_data;
187 memset (copy->scrollbar_data, 0, sizeof (scrollbar_values));
191 * Return true if old->scrollbar_data were not equivalent
192 * to new->scrollbar_data.
195 merge_scrollbar_values (widget_value *old, widget_value *new)
197 Boolean changed = False;
199 if (new->scrollbar_data && !old->scrollbar_data)
201 copy_scrollbar_values (new, old);
204 else if (!new->scrollbar_data && old->scrollbar_data)
206 free (old->scrollbar_data);
207 old->scrollbar_data = NULL;
209 else if (new->scrollbar_data && old->scrollbar_data)
211 scrollbar_values *old_sb = old->scrollbar_data;
212 scrollbar_values *new_sb = new->scrollbar_data;
214 if ((old_sb->line_increment != new_sb->line_increment) ||
215 (old_sb->page_increment != new_sb->page_increment) ||
216 (old_sb->minimum != new_sb->minimum) ||
217 (old_sb->maximum != new_sb->maximum) ||
218 (old_sb->slider_size != new_sb->slider_size) ||
219 (old_sb->slider_position != new_sb->slider_position) ||
220 (old_sb->scrollbar_width != new_sb->scrollbar_width) ||
221 (old_sb->scrollbar_height != new_sb->scrollbar_height) ||
222 (old_sb->scrollbar_x != new_sb->scrollbar_x) ||
223 (old_sb->scrollbar_y != new_sb->scrollbar_y))
232 #endif /* NEED_SCROLLBARS */
234 /* Make a complete copy of a widget_value tree. Store CHANGE into
235 the widget_value tree's `change' field. */
237 static widget_value *
238 copy_widget_value_tree (widget_value *val, change_type change)
244 if (val == (widget_value *) 1)
247 copy = malloc_widget_value ();
250 /* #### - don't seg fault *here* if out of memory. Menus will be
251 truncated inexplicably. */
252 copy->type = val->type;
253 copy->name = safe_strdup (val->name);
254 copy->value = safe_strdup (val->value);
255 copy->key = safe_strdup (val->key);
256 copy->accel = val->accel;
257 copy->enabled = val->enabled;
258 copy->selected = val->selected;
259 copy->edited = False;
260 copy->change = change;
261 copy->contents = copy_widget_value_tree (val->contents, change);
262 copy->call_data = val->call_data;
263 copy->next = copy_widget_value_tree (val->next, change);
264 copy->toolkit_data = NULL;
265 copy->free_toolkit_data = False;
266 #ifdef NEED_SCROLLBARS
267 copy_scrollbar_values (val, copy);
273 /* This function is used to implement incremental menu construction. */
276 replace_widget_value_tree (widget_value *node, widget_value *newtree)
280 if (!node || !newtree)
283 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE);
285 free_widget_value_contents (node);
287 free_widget_value (copy); /* free the node, but not its contents. */
292 allocate_widget_info (CONST char *type, CONST char *name,
293 LWLIB_ID id, widget_value *val,
294 lw_callback pre_activate_cb, lw_callback selection_cb,
295 lw_callback post_activate_cb)
297 widget_info *info = (widget_info *) malloc (sizeof (widget_info));
298 info->type = safe_strdup (type);
299 info->name = safe_strdup (name);
301 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
303 info->pre_activate_cb = pre_activate_cb;
304 info->selection_cb = selection_cb;
305 info->post_activate_cb = post_activate_cb;
306 info->instances = NULL;
308 info->next = all_widget_info;
309 all_widget_info = info;
315 free_widget_info (widget_info *info)
317 safe_free_str (info->type);
318 safe_free_str (info->name);
319 free_widget_value_tree (info->val);
320 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
325 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
327 widget_instance *instance = (widget_instance*)closure;
329 /* be very conservative */
330 if (instance->widget == widget)
331 instance->widget = NULL;
334 static widget_instance *
335 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
337 widget_instance *instance =
338 (widget_instance *) malloc (sizeof (widget_instance));
339 instance->parent = parent;
340 instance->pop_up_p = pop_up_p;
341 instance->info = info;
342 instance->next = info->instances;
343 info->instances = instance;
345 instantiate_widget_instance (instance);
347 XtAddCallback (instance->widget, XtNdestroyCallback,
348 mark_widget_destroyed, (XtPointer)instance);
353 free_widget_instance (widget_instance *instance)
355 memset ((void *) instance, 0xDEADBEEF, sizeof (widget_instance));
360 get_widget_info (LWLIB_ID id, Boolean remove_p)
364 for (prev = NULL, info = all_widget_info;
366 prev = info, info = info->next)
372 prev->next = info->next;
374 all_widget_info = info->next;
381 /* Internal function used by the library dependent implementation to get the
382 widget_value for a given widget in an instance */
384 lw_get_widget_info (LWLIB_ID id)
386 return get_widget_info (id, 0);
390 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value,
397 retval = map_widget_values (value->contents, mapfunc, closure);
402 retval = map_widget_values (value->next, mapfunc, closure);
406 return (mapfunc) (value, closure);
410 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value,
414 widget_info *info = get_widget_info (id, 0);
420 return map_widget_values (info->val, mapfunc, closure);
424 static widget_instance *
425 get_widget_instance (Widget widget, Boolean remove_p)
428 widget_instance *instance;
429 widget_instance *prev;
430 for (info = all_widget_info; info; info = info->next)
431 for (prev = NULL, instance = info->instances;
433 prev = instance, instance = instance->next)
434 if (instance->widget == widget)
439 prev->next = instance->next;
441 info->instances = instance->next;
445 return (widget_instance *) 0;
448 static widget_instance*
449 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
451 widget_info *info = get_widget_info (id, False);
452 widget_instance *instance;
455 for (instance = info->instances; instance; instance = instance->next)
456 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
463 /* utility function for widget_value */
465 safe_strcmp (CONST char *s1, CONST char *s2)
467 if (!!s1 ^ !!s2) return True;
468 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
473 max (change_type i1, change_type i2)
475 return (int)i1 > (int)i2 ? i1 : i2;
481 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
482 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
484 (oc == NO_CHANGE ? "none" : \
485 (oc == INVISIBLE_CHANGE ? "invisible" : \
486 (oc == VISIBLE_CHANGE ? "visible" : \
487 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
489 (nc == NO_CHANGE ? "none" : \
490 (nc == INVISIBLE_CHANGE ? "invisible" : \
491 (nc == VISIBLE_CHANGE ? "visible" : \
492 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
495 # define EXPLAIN(name, oc, nc, desc, a1, a2)
499 static widget_value *
500 merge_widget_value (widget_value *val1, widget_value *val2, int level)
503 widget_value *merged_next;
504 widget_value *merged_contents;
509 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
515 free_widget_value_tree (val1);
521 if (val1->type != val2->type)
523 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change",
524 val1->type, val2->type);
525 change = max (change, STRUCTURAL_CHANGE);
526 val1->type = val2->type;
528 if (safe_strcmp (val1->name, val2->name))
530 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
531 val1->name, val2->name);
532 change = max (change, STRUCTURAL_CHANGE);
533 safe_free_str (val1->name);
534 val1->name = safe_strdup (val2->name);
536 if (safe_strcmp (val1->value, val2->value))
538 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
539 val1->value, val2->value);
540 change = max (change, VISIBLE_CHANGE);
541 safe_free_str (val1->value);
542 val1->value = safe_strdup (val2->value);
544 if (safe_strcmp (val1->key, val2->key))
546 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
547 val1->key, val2->key);
548 change = max (change, VISIBLE_CHANGE);
549 safe_free_str (val1->key);
550 val1->key = safe_strdup (val2->key);
552 if (val1->accel != val2->accel)
554 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change",
555 val1->accel, val2->accel);
556 change = max (change, VISIBLE_CHANGE);
557 val1->accel = val2->accel;
559 if (val1->enabled != val2->enabled)
561 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
562 val1->enabled, val2->enabled);
563 change = max (change, VISIBLE_CHANGE);
564 val1->enabled = val2->enabled;
566 if (val1->selected != val2->selected)
568 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
569 val1->selected, val2->selected);
570 change = max (change, VISIBLE_CHANGE);
571 val1->selected = val2->selected;
573 if (val1->call_data != val2->call_data)
575 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
576 val1->call_data, val2->call_data);
577 change = max (change, INVISIBLE_CHANGE);
578 val1->call_data = val2->call_data;
580 #ifdef NEED_SCROLLBARS
581 if (merge_scrollbar_values (val1, val2))
583 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0);
584 change = max (change, VISIBLE_CHANGE);
591 merge_widget_value (val1->contents, val2->contents, level - 1);
593 if (val1->contents && !merged_contents)
595 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
597 change = max (change, INVISIBLE_CHANGE);
599 else if (merged_contents && merged_contents->change != NO_CHANGE)
601 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
603 change = max (change, INVISIBLE_CHANGE);
606 val1->contents = merged_contents;
609 merged_next = merge_widget_value (val1->next, val2->next, level);
611 if (val1->next && !merged_next)
613 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
615 change = max (change, STRUCTURAL_CHANGE);
617 else if (merged_next)
619 if (merged_next->change)
621 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
624 change = max (change, merged_next->change);
627 val1->next = merged_next;
629 val1->change = change;
631 if (change > NO_CHANGE && val1->toolkit_data)
633 if (val1->free_toolkit_data)
634 XtFree ((char *) val1->toolkit_data);
635 val1->toolkit_data = NULL;
642 /* modifying the widgets */
644 name_to_widget (widget_instance *instance, CONST char *name)
646 Widget widget = NULL;
648 if (!instance->widget)
651 if (!strcmp (XtName (instance->widget), name))
652 widget = instance->widget;
655 int length = strlen (name) + 2;
656 char *real_name = (char *) alloca (length);
658 strcpy (real_name + 1, name);
660 widget = XtNameToWidget (instance->widget, real_name);
666 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p)
668 Widget widget = name_to_widget (instance, val->name);
673 if (lw_lucid_widget_p (instance->widget))
674 xlw_update_one_widget (instance, widget, val, deep_p);
677 if (lw_motif_widget_p (instance->widget))
678 xm_update_one_widget (instance, widget, val, deep_p);
681 if (lw_xaw_widget_p (instance->widget))
682 xaw_update_one_widget (instance, widget, val, deep_p);
688 update_one_widget_instance (widget_instance *instance, Boolean deep_p)
692 if (!instance->widget)
693 /* the widget was destroyed */
696 for (val = instance->info->val; val; val = val->next)
697 if (val->change != NO_CHANGE)
698 set_one_value (instance, val, deep_p);
702 update_all_widget_values (widget_info *info, Boolean deep_p)
704 widget_instance *instance;
707 for (instance = info->instances; instance; instance = instance->next)
708 update_one_widget_instance (instance, deep_p);
710 for (val = info->val; val; val = val->next)
711 val->change = NO_CHANGE;
715 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p)
717 widget_info *info = get_widget_info (id, False);
718 widget_value *new_val;
719 widget_value *next_new_val;
728 for (new_val = val; new_val; new_val = new_val->next)
730 next_new_val = new_val->next;
731 new_val->next = NULL;
733 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
734 if (!strcmp (cur->name, new_val->name))
739 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
741 prev->next = cur ? cur : next;
743 info->val = cur ? cur : next;
750 /* Could not find it, add it */
752 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
754 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
756 new_val->next = next_new_val;
759 update_all_widget_values (info, deep_p);
763 /* creating the widgets */
766 initialize_widget_instance (widget_instance *instance)
770 for (val = instance->info->val; val; val = val->next)
771 val->change = STRUCTURAL_CHANGE;
773 update_one_widget_instance (instance, True);
775 for (val = instance->info->val; val; val = val->next)
776 val->change = NO_CHANGE;
780 static widget_creation_function
781 find_in_table (CONST char *type, widget_creation_entry *table)
783 widget_creation_entry *cur;
784 for (cur = table; cur->type; cur++)
785 if (!strcasecmp (type, cur->type))
786 return cur->function;
791 dialog_spec_p (CONST char *name)
793 /* return True if name matches [EILPQeilpq][1-9][Bb] or
794 [EILPQeilpq][1-9][Bb][Rr][1-9] */
800 case 'E': case 'I': case 'L': case 'P': case 'Q':
801 case 'e': case 'i': case 'l': case 'p': case 'q':
802 if (name [1] >= '0' && name [1] <= '9')
804 if (name [2] != 'B' && name [2] != 'b')
808 if ((name [3] == 'T' || name [3] == 't') && !name [4])
810 if ((name [3] == 'R' || name [3] == 'r')
811 && name [4] >= '0' && name [4] <= '9' && !name [5])
824 instantiate_widget_instance (widget_instance *instance)
826 widget_creation_function function = NULL;
830 function = find_in_table (instance->info->type, xlw_creation_table);
834 function = find_in_table (instance->info->type, xm_creation_table);
838 function = find_in_table (instance->info->type, xaw_creation_table);
843 if (dialog_spec_p (instance->info->type))
845 #ifdef LWLIB_DIALOGS_MOTIF
847 function = xm_create_dialog;
849 #ifdef LWLIB_DIALOGS_ATHENA
851 function = xaw_create_dialog;
853 #ifdef LWLIB_DIALOGS_LUCID
854 /* not yet (not ever?) */
861 fprintf (stderr, "No creation function for widget type %s\n",
862 instance->info->type);
866 instance->widget = (*function) (instance);
868 if (!instance->widget)
871 /* XtRealizeWidget (instance->widget);*/
875 lw_register_widget (CONST char *type, CONST char *name,
876 LWLIB_ID id, widget_value *val,
877 lw_callback pre_activate_cb, lw_callback selection_cb,
878 lw_callback post_activate_cb)
880 if (!get_widget_info (id, False))
881 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
886 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
888 widget_instance *instance = find_instance (id, parent, pop_up_p);
889 return instance ? instance->widget : NULL;
893 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
895 widget_instance *instance = find_instance (id, parent, pop_up_p);
899 widget_info *info = get_widget_info (id, False);
902 instance = allocate_widget_instance (info, parent, pop_up_p);
903 initialize_widget_instance (instance);
905 if (!instance->widget)
907 return instance->widget;
911 lw_create_widget (CONST char *type, CONST char *name,
912 LWLIB_ID id, widget_value *val,
913 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
914 lw_callback selection_cb, lw_callback post_activate_cb)
916 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
918 return lw_make_widget (id, parent, pop_up_p);
922 /* destroying the widgets */
924 destroy_one_instance (widget_instance *instance)
926 /* Remove the destroy callback on the widget; that callback will try to
927 dereference the instance object (to set its widget slot to 0, since the
928 widget is dead.) Since the instance is now dead, we don't have to worry
929 about the fact that its widget is dead too.
931 This happens in the Phase2Destroy of the widget, so this callback would
932 not have been run until arbitrarily long after the instance was freed.
934 if (instance->widget)
935 XtRemoveCallback (instance->widget, XtNdestroyCallback,
936 mark_widget_destroyed, (XtPointer)instance);
938 if (instance->widget)
940 /* The else are pretty tricky here, including the empty statement
941 at the end because it would be very bad to destroy a widget
944 if (lw_lucid_widget_p (instance->widget))
945 xlw_destroy_instance (instance);
949 if (lw_motif_widget_p (instance->widget))
950 xm_destroy_instance (instance);
954 if (lw_xaw_widget_p (instance->widget))
955 xaw_destroy_instance (instance);
959 /* do not remove the empty statement */
964 free_widget_instance (instance);
968 lw_destroy_widget (Widget w)
970 widget_instance *instance = get_widget_instance (w, True);
974 widget_info *info = instance->info;
975 /* instance has already been removed from the list; free it */
976 destroy_one_instance (instance);
977 /* if there are no instances left, free the info too */
978 if (!info->instances)
979 lw_destroy_all_widgets (info->id);
984 lw_destroy_all_widgets (LWLIB_ID id)
986 widget_info *info = get_widget_info (id, True);
987 widget_instance *instance;
988 widget_instance *next;
992 for (instance = info->instances; instance; )
994 next = instance->next;
995 destroy_one_instance (instance);
998 free_widget_info (info);
1003 lw_destroy_everything ()
1005 while (all_widget_info)
1006 lw_destroy_all_widgets (all_widget_info->id);
1010 lw_destroy_all_pop_ups ()
1014 widget_instance *instance;
1016 for (info = all_widget_info; info; info = next)
1019 instance = info->instances;
1020 if (instance && instance->pop_up_p)
1021 lw_destroy_all_widgets (info->id);
1026 lw_raise_all_pop_up_widgets (void)
1029 widget_instance *instance;
1030 Widget result = NULL;
1032 for (info = all_widget_info; info; info = info->next)
1033 for (instance = info->instances; instance; instance = instance->next)
1034 if (instance->pop_up_p)
1036 Widget widget = instance->widget;
1039 if (XtIsManaged (widget)
1041 /* What a complete load of crap!!!!
1042 When a dialogShell is on the screen, it is not managed!
1044 || (lw_motif_widget_p (instance->widget) &&
1045 XtIsManaged (first_child (widget)))
1051 XMapRaised (XtDisplay (widget), XtWindow (widget));
1059 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1061 widget_info *info = get_widget_info (id, False);
1062 widget_instance *instance;
1065 for (instance = info->instances; instance; instance = instance->next)
1066 if (instance->pop_up_p && instance->widget)
1069 if (lw_lucid_widget_p (instance->widget))
1071 XtRealizeWidget (instance->widget);
1072 xlw_pop_instance (instance, up);
1076 if (lw_motif_widget_p (instance->widget))
1078 XtRealizeWidget (instance->widget);
1079 xm_pop_instance (instance, up);
1083 if (lw_xaw_widget_p (instance->widget))
1085 XtRealizeWidget (XtParent (instance->widget));
1086 XtRealizeWidget (instance->widget);
1087 xaw_pop_instance (instance, up);
1094 lw_pop_up_all_widgets (LWLIB_ID id)
1096 lw_pop_all_widgets (id, True);
1100 lw_pop_down_all_widgets (LWLIB_ID id)
1102 lw_pop_all_widgets (id, False);
1106 lw_popup_menu (Widget widget, XEvent *event)
1108 #ifdef LWLIB_MENUBARS_LUCID
1109 if (lw_lucid_widget_p (widget))
1110 xlw_popup_menu (widget, event);
1112 #ifdef LWLIB_MENUBARS_MOTIF
1113 if (lw_motif_widget_p (widget))
1114 xm_popup_menu (widget, event);
1116 #ifdef LWLIB_MENUBARS_ATHENA
1117 if (lw_xaw_widget_p (widget))
1118 xaw_popup_menu (widget, event); /* not implemented */
1122 \f/* get the values back */
1124 get_one_value (widget_instance *instance, widget_value *val)
1126 Widget widget = name_to_widget (instance, val->name);
1131 if (lw_lucid_widget_p (instance->widget))
1132 xlw_update_one_value (instance, widget, val);
1135 if (lw_motif_widget_p (instance->widget))
1136 xm_update_one_value (instance, widget, val);
1139 if (lw_xaw_widget_p (instance->widget))
1140 xaw_update_one_value (instance, widget, val);
1149 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
1151 widget_info *info = get_widget_info (id, False);
1152 widget_instance *instance;
1154 Boolean result = False;
1159 instance = info->instances;
1163 for (val = val_out; val; val = val->next)
1164 if (get_one_value (instance, val))
1171 lw_get_all_values (LWLIB_ID id)
1173 widget_info *info = get_widget_info (id, False);
1174 widget_value *val = info->val;
1175 if (lw_get_some_values (id, val))
1181 /* internal function used by the library dependent implementation to get the
1182 widget_value for a given widget in an instance */
1184 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
1186 char *name = XtName (w);
1188 for (cur = instance->info->val; cur; cur = cur->next)
1189 if (!strcmp (cur->name, name))
1195 /* update other instances value when one thing changed */
1196 /* This function can be used as a an XtCallback for the widgets that get
1197 modified to update other instances of the widgets. Closure should be the
1200 lw_internal_update_other_instances (Widget widget, XtPointer closure,
1201 XtPointer call_data)
1203 /* To forbid recursive calls */
1204 static Boolean updating;
1206 widget_instance *instance = (widget_instance*)closure;
1207 char *name = XtName (widget);
1209 widget_instance *cur;
1212 /* never recurse as this could cause infinite recursions. */
1216 /* protect against the widget being destroyed */
1217 if (XtWidgetBeingDestroyedP (widget))
1220 /* Return immediately if there are no other instances */
1221 info = instance->info;
1222 if (!info->instances->next)
1227 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1229 if (val && get_one_value (instance, val))
1230 for (cur = info->instances; cur; cur = cur->next)
1231 if (cur != instance)
1232 set_one_value (cur, val, True);
1242 lw_get_widget_id (Widget w)
1244 widget_instance *instance = get_widget_instance (w, False);
1246 return instance ? instance->info->id : 0;
1250 /* set the keyboard focus */
1252 lw_set_keyboard_focus (Widget parent, Widget w)
1254 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION)
1255 /* This loses with Lesstif v0.75a */
1256 xm_set_keyboard_focus (parent, w);
1258 XtSetKeyboardFocus (parent, w);
1265 show_one_widget_busy (Widget w, Boolean flag)
1267 Pixel foreground = 0;
1268 Pixel background = 1;
1269 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1272 if (!widget_to_invert)
1273 widget_to_invert = w;
1275 XtSetArg (al [0], XtNforeground, &foreground);
1276 XtSetArg (al [1], XtNbackground, &background);
1277 XtGetValues (widget_to_invert, al, 2);
1279 XtSetArg (al [0], XtNforeground, background);
1280 XtSetArg (al [1], XtNbackground, foreground);
1281 XtSetValues (widget_to_invert, al, 2);
1285 lw_show_busy (Widget w, Boolean busy)
1287 widget_instance *instance = get_widget_instance (w, False);
1289 widget_instance *next;
1293 info = instance->info;
1294 if (info->busy != busy)
1296 for (next = info->instances; next; next = next->next)
1298 show_one_widget_busy (next->widget, busy);