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;
158 if (wv->args && wv->free_args)
161 wv->args = (void *) 0xDEADBEEF;
166 free_widget_value_tree (wv->next);
167 wv->next = (widget_value *) 0xDEADBEEF;
172 free_widget_value_tree (widget_value *wv)
177 free_widget_value_contents (wv);
178 free_widget_value (wv);
181 #ifdef NEED_SCROLLBARS
184 copy_scrollbar_values (widget_value *val, widget_value *copy)
186 if (!copy->scrollbar_data)
187 copy->scrollbar_data =
188 (scrollbar_values *) malloc (sizeof (scrollbar_values));
190 if (val->scrollbar_data)
191 *copy->scrollbar_data = *val->scrollbar_data;
193 memset (copy->scrollbar_data, 0, sizeof (scrollbar_values));
197 * Return true if old->scrollbar_data were not equivalent
198 * to new->scrollbar_data.
201 merge_scrollbar_values (widget_value *old, widget_value *new)
203 Boolean changed = False;
205 if (new->scrollbar_data && !old->scrollbar_data)
207 copy_scrollbar_values (new, old);
210 else if (!new->scrollbar_data && old->scrollbar_data)
212 free (old->scrollbar_data);
213 old->scrollbar_data = NULL;
215 else if (new->scrollbar_data && old->scrollbar_data)
217 scrollbar_values *old_sb = old->scrollbar_data;
218 scrollbar_values *new_sb = new->scrollbar_data;
220 if ((old_sb->line_increment != new_sb->line_increment) ||
221 (old_sb->page_increment != new_sb->page_increment) ||
222 (old_sb->minimum != new_sb->minimum) ||
223 (old_sb->maximum != new_sb->maximum) ||
224 (old_sb->slider_size != new_sb->slider_size) ||
225 (old_sb->slider_position != new_sb->slider_position) ||
226 (old_sb->scrollbar_width != new_sb->scrollbar_width) ||
227 (old_sb->scrollbar_height != new_sb->scrollbar_height) ||
228 (old_sb->scrollbar_x != new_sb->scrollbar_x) ||
229 (old_sb->scrollbar_y != new_sb->scrollbar_y))
238 #endif /* NEED_SCROLLBARS */
240 /* Make a complete copy of a widget_value tree. Store CHANGE into
241 the widget_value tree's `change' field. */
243 static widget_value *
244 copy_widget_value_tree (widget_value *val, change_type change)
250 if (val == (widget_value *) 1)
253 copy = malloc_widget_value ();
256 /* #### - don't seg fault *here* if out of memory. Menus will be
257 truncated inexplicably. */
258 copy->type = val->type;
259 copy->name = safe_strdup (val->name);
260 copy->value = safe_strdup (val->value);
261 copy->key = safe_strdup (val->key);
262 copy->accel = val->accel;
263 copy->enabled = val->enabled;
264 copy->selected = val->selected;
265 copy->edited = False;
266 copy->change = change;
267 copy->contents = copy_widget_value_tree (val->contents, change);
268 copy->call_data = val->call_data;
269 copy->next = copy_widget_value_tree (val->next, change);
270 copy->toolkit_data = NULL;
271 copy->free_toolkit_data = False;
274 copy->args = (ArgList)malloc (sizeof (Arg) * val->nargs);
275 memcpy (copy->args, val->args, sizeof(Arg) * val->nargs);
276 copy->nargs = val->nargs;
277 copy->free_args = True;
279 #ifdef NEED_SCROLLBARS
280 copy_scrollbar_values (val, copy);
286 /* This function is used to implement incremental menu construction. */
289 replace_widget_value_tree (widget_value *node, widget_value *newtree)
293 if (!node || !newtree)
296 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE);
298 free_widget_value_contents (node);
300 free_widget_value (copy); /* free the node, but not its contents. */
305 allocate_widget_info (CONST char *type, CONST char *name,
306 LWLIB_ID id, widget_value *val,
307 lw_callback pre_activate_cb, lw_callback selection_cb,
308 lw_callback post_activate_cb)
310 widget_info *info = (widget_info *) malloc (sizeof (widget_info));
311 info->type = safe_strdup (type);
312 info->name = safe_strdup (name);
314 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
316 info->pre_activate_cb = pre_activate_cb;
317 info->selection_cb = selection_cb;
318 info->post_activate_cb = post_activate_cb;
319 info->instances = NULL;
321 info->next = all_widget_info;
322 all_widget_info = info;
328 free_widget_info (widget_info *info)
330 safe_free_str (info->type);
331 safe_free_str (info->name);
332 free_widget_value_tree (info->val);
333 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
338 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
340 widget_instance *instance = (widget_instance*)closure;
342 /* be very conservative */
343 if (instance->widget == widget)
344 instance->widget = NULL;
347 static widget_instance *
348 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
350 widget_instance *instance =
351 (widget_instance *) malloc (sizeof (widget_instance));
352 instance->parent = parent;
353 instance->pop_up_p = pop_up_p;
354 instance->info = info;
355 instance->next = info->instances;
356 info->instances = instance;
358 instantiate_widget_instance (instance);
360 XtAddCallback (instance->widget, XtNdestroyCallback,
361 mark_widget_destroyed, (XtPointer)instance);
366 free_widget_instance (widget_instance *instance)
368 memset ((void *) instance, 0xDEADBEEF, sizeof (widget_instance));
373 get_widget_info (LWLIB_ID id, Boolean remove_p)
377 for (prev = NULL, info = all_widget_info;
379 prev = info, info = info->next)
385 prev->next = info->next;
387 all_widget_info = info->next;
394 /* Internal function used by the library dependent implementation to get the
395 widget_value for a given widget in an instance */
397 lw_get_widget_info (LWLIB_ID id)
399 return get_widget_info (id, 0);
403 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value,
410 retval = map_widget_values (value->contents, mapfunc, closure);
415 retval = map_widget_values (value->next, mapfunc, closure);
419 return (mapfunc) (value, closure);
423 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value,
427 widget_info *info = get_widget_info (id, 0);
433 return map_widget_values (info->val, mapfunc, closure);
437 static widget_instance *
438 get_widget_instance (Widget widget, Boolean remove_p)
441 widget_instance *instance;
442 widget_instance *prev;
443 for (info = all_widget_info; info; info = info->next)
444 for (prev = NULL, instance = info->instances;
446 prev = instance, instance = instance->next)
447 if (instance->widget == widget)
452 prev->next = instance->next;
454 info->instances = instance->next;
458 return (widget_instance *) 0;
461 static widget_instance*
462 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
464 widget_info *info = get_widget_info (id, False);
465 widget_instance *instance;
468 for (instance = info->instances; instance; instance = instance->next)
469 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
476 /* utility function for widget_value */
478 safe_strcmp (CONST char *s1, CONST char *s2)
480 if (!!s1 ^ !!s2) return True;
481 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
486 max (change_type i1, change_type i2)
488 return (int)i1 > (int)i2 ? i1 : i2;
494 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
495 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
497 (oc == NO_CHANGE ? "none" : \
498 (oc == INVISIBLE_CHANGE ? "invisible" : \
499 (oc == VISIBLE_CHANGE ? "visible" : \
500 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
502 (nc == NO_CHANGE ? "none" : \
503 (nc == INVISIBLE_CHANGE ? "invisible" : \
504 (nc == VISIBLE_CHANGE ? "visible" : \
505 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
508 # define EXPLAIN(name, oc, nc, desc, a1, a2)
512 static widget_value *
513 merge_widget_value (widget_value *val1, widget_value *val2, int level)
516 widget_value *merged_next;
517 widget_value *merged_contents;
522 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
528 free_widget_value_tree (val1);
534 if (val1->type != val2->type)
536 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change",
537 val1->type, val2->type);
538 change = max (change, STRUCTURAL_CHANGE);
539 val1->type = val2->type;
541 if (safe_strcmp (val1->name, val2->name))
543 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
544 val1->name, val2->name);
545 change = max (change, STRUCTURAL_CHANGE);
546 safe_free_str (val1->name);
547 val1->name = safe_strdup (val2->name);
549 if (safe_strcmp (val1->value, val2->value))
551 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
552 val1->value, val2->value);
553 change = max (change, VISIBLE_CHANGE);
554 safe_free_str (val1->value);
555 val1->value = safe_strdup (val2->value);
557 if (safe_strcmp (val1->key, val2->key))
559 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
560 val1->key, val2->key);
561 change = max (change, VISIBLE_CHANGE);
562 safe_free_str (val1->key);
563 val1->key = safe_strdup (val2->key);
565 if (val1->accel != val2->accel)
567 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change",
568 val1->accel, val2->accel);
569 change = max (change, VISIBLE_CHANGE);
570 val1->accel = val2->accel;
572 if (val1->enabled != val2->enabled)
574 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
575 val1->enabled, val2->enabled);
576 change = max (change, VISIBLE_CHANGE);
577 val1->enabled = val2->enabled;
579 if (val1->selected != val2->selected)
581 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
582 val1->selected, val2->selected);
583 change = max (change, VISIBLE_CHANGE);
584 val1->selected = val2->selected;
586 if (val1->call_data != val2->call_data)
588 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
589 val1->call_data, val2->call_data);
590 change = max (change, INVISIBLE_CHANGE);
591 val1->call_data = val2->call_data;
593 #ifdef NEED_SCROLLBARS
594 if (merge_scrollbar_values (val1, val2))
596 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0);
597 change = max (change, VISIBLE_CHANGE);
604 merge_widget_value (val1->contents, val2->contents, level - 1);
606 if (val1->contents && !merged_contents)
608 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
610 change = max (change, INVISIBLE_CHANGE);
612 else if (merged_contents && merged_contents->change != NO_CHANGE)
614 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
616 change = max (change, INVISIBLE_CHANGE);
619 val1->contents = merged_contents;
622 merged_next = merge_widget_value (val1->next, val2->next, level);
624 if (val1->next && !merged_next)
626 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
628 change = max (change, STRUCTURAL_CHANGE);
630 else if (merged_next)
632 if (merged_next->change)
634 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
637 change = max (change, merged_next->change);
640 val1->next = merged_next;
642 val1->change = change;
644 if (change > NO_CHANGE && val1->toolkit_data)
646 if (val1->free_toolkit_data)
647 XtFree ((char *) val1->toolkit_data);
648 val1->toolkit_data = NULL;
655 /* modifying the widgets */
657 name_to_widget (widget_instance *instance, CONST char *name)
659 Widget widget = NULL;
661 if (!instance->widget)
664 if (!strcmp (XtName (instance->widget), name))
665 widget = instance->widget;
668 int length = strlen (name) + 2;
669 char *real_name = (char *) alloca (length);
671 strcpy (real_name + 1, name);
673 widget = XtNameToWidget (instance->widget, real_name);
679 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p)
681 Widget widget = name_to_widget (instance, val->name);
686 if (lw_lucid_widget_p (instance->widget))
687 xlw_update_one_widget (instance, widget, val, deep_p);
690 if (lw_motif_widget_p (instance->widget))
691 xm_update_one_widget (instance, widget, val, deep_p);
694 if (lw_xaw_widget_p (instance->widget))
695 xaw_update_one_widget (instance, widget, val, deep_p);
701 update_one_widget_instance (widget_instance *instance, Boolean deep_p)
705 if (!instance->widget)
706 /* the widget was destroyed */
709 for (val = instance->info->val; val; val = val->next)
710 if (val->change != NO_CHANGE)
711 set_one_value (instance, val, deep_p);
715 update_all_widget_values (widget_info *info, Boolean deep_p)
717 widget_instance *instance;
720 for (instance = info->instances; instance; instance = instance->next)
721 update_one_widget_instance (instance, deep_p);
723 for (val = info->val; val; val = val->next)
724 val->change = NO_CHANGE;
728 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p)
730 widget_info *info = get_widget_info (id, False);
731 widget_value *new_val;
732 widget_value *next_new_val;
741 for (new_val = val; new_val; new_val = new_val->next)
743 next_new_val = new_val->next;
744 new_val->next = NULL;
746 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
747 if (!strcmp (cur->name, new_val->name))
752 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
754 prev->next = cur ? cur : next;
756 info->val = cur ? cur : next;
763 /* Could not find it, add it */
765 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
767 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
769 new_val->next = next_new_val;
772 update_all_widget_values (info, deep_p);
776 /* creating the widgets */
779 initialize_widget_instance (widget_instance *instance)
783 for (val = instance->info->val; val; val = val->next)
784 val->change = STRUCTURAL_CHANGE;
786 update_one_widget_instance (instance, True);
788 for (val = instance->info->val; val; val = val->next)
789 val->change = NO_CHANGE;
793 static widget_creation_function
794 find_in_table (CONST char *type, widget_creation_entry *table)
796 widget_creation_entry *cur;
797 for (cur = table; cur->type; cur++)
798 if (!strcasecmp (type, cur->type))
799 return cur->function;
804 dialog_spec_p (CONST char *name)
806 /* return True if name matches [EILPQeilpq][1-9][Bb] or
807 [EILPQeilpq][1-9][Bb][Rr][1-9] */
813 case 'E': case 'I': case 'L': case 'P': case 'Q':
814 case 'e': case 'i': case 'l': case 'p': case 'q':
815 if (name [1] >= '0' && name [1] <= '9')
817 if (name [2] != 'B' && name [2] != 'b')
821 if ((name [3] == 'T' || name [3] == 't') && !name [4])
823 if ((name [3] == 'R' || name [3] == 'r')
824 && name [4] >= '0' && name [4] <= '9' && !name [5])
837 instantiate_widget_instance (widget_instance *instance)
839 widget_creation_function function = NULL;
843 function = find_in_table (instance->info->type, xlw_creation_table);
847 function = find_in_table (instance->info->type, xm_creation_table);
851 function = find_in_table (instance->info->type, xaw_creation_table);
856 if (dialog_spec_p (instance->info->type))
858 #ifdef LWLIB_DIALOGS_MOTIF
860 function = xm_create_dialog;
862 #ifdef LWLIB_DIALOGS_ATHENA
864 function = xaw_create_dialog;
866 #ifdef LWLIB_DIALOGS_LUCID
867 /* not yet (not ever?) */
874 fprintf (stderr, "No creation function for widget type %s\n",
875 instance->info->type);
879 instance->widget = (*function) (instance);
881 if (!instance->widget)
884 /* XtRealizeWidget (instance->widget);*/
888 lw_register_widget (CONST char *type, CONST char *name,
889 LWLIB_ID id, widget_value *val,
890 lw_callback pre_activate_cb, lw_callback selection_cb,
891 lw_callback post_activate_cb)
893 if (!get_widget_info (id, False))
894 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
899 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
901 widget_instance *instance = find_instance (id, parent, pop_up_p);
902 return instance ? instance->widget : NULL;
906 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
908 widget_instance *instance = find_instance (id, parent, pop_up_p);
912 widget_info *info = get_widget_info (id, False);
915 instance = allocate_widget_instance (info, parent, pop_up_p);
916 initialize_widget_instance (instance);
918 if (!instance->widget)
920 return instance->widget;
924 lw_create_widget (CONST char *type, CONST char *name,
925 LWLIB_ID id, widget_value *val,
926 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
927 lw_callback selection_cb, lw_callback post_activate_cb)
929 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
931 return lw_make_widget (id, parent, pop_up_p);
935 /* destroying the widgets */
937 destroy_one_instance (widget_instance *instance)
939 /* Remove the destroy callback on the widget; that callback will try to
940 dereference the instance object (to set its widget slot to 0, since the
941 widget is dead.) Since the instance is now dead, we don't have to worry
942 about the fact that its widget is dead too.
944 This happens in the Phase2Destroy of the widget, so this callback would
945 not have been run until arbitrarily long after the instance was freed.
947 if (instance->widget)
948 XtRemoveCallback (instance->widget, XtNdestroyCallback,
949 mark_widget_destroyed, (XtPointer)instance);
951 if (instance->widget)
953 /* The else are pretty tricky here, including the empty statement
954 at the end because it would be very bad to destroy a widget
957 if (lw_lucid_widget_p (instance->widget))
958 xlw_destroy_instance (instance);
962 if (lw_motif_widget_p (instance->widget))
963 xm_destroy_instance (instance);
967 if (lw_xaw_widget_p (instance->widget))
968 xaw_destroy_instance (instance);
972 /* do not remove the empty statement */
977 free_widget_instance (instance);
981 lw_destroy_widget (Widget w)
983 widget_instance *instance = get_widget_instance (w, True);
987 widget_info *info = instance->info;
988 /* instance has already been removed from the list; free it */
989 destroy_one_instance (instance);
990 /* if there are no instances left, free the info too */
991 if (!info->instances)
992 lw_destroy_all_widgets (info->id);
997 lw_destroy_all_widgets (LWLIB_ID id)
999 widget_info *info = get_widget_info (id, True);
1000 widget_instance *instance;
1001 widget_instance *next;
1005 for (instance = info->instances; instance; )
1007 next = instance->next;
1008 destroy_one_instance (instance);
1011 free_widget_info (info);
1016 lw_destroy_everything ()
1018 while (all_widget_info)
1019 lw_destroy_all_widgets (all_widget_info->id);
1023 lw_destroy_all_pop_ups ()
1027 widget_instance *instance;
1029 for (info = all_widget_info; info; info = next)
1032 instance = info->instances;
1033 if (instance && instance->pop_up_p)
1034 lw_destroy_all_widgets (info->id);
1039 lw_raise_all_pop_up_widgets (void)
1042 widget_instance *instance;
1043 Widget result = NULL;
1045 for (info = all_widget_info; info; info = info->next)
1046 for (instance = info->instances; instance; instance = instance->next)
1047 if (instance->pop_up_p)
1049 Widget widget = instance->widget;
1052 if (XtIsManaged (widget)
1054 /* What a complete load of crap!!!!
1055 When a dialogShell is on the screen, it is not managed!
1057 || (lw_motif_widget_p (instance->widget) &&
1058 XtIsManaged (first_child (widget)))
1064 XMapRaised (XtDisplay (widget), XtWindow (widget));
1072 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1074 widget_info *info = get_widget_info (id, False);
1075 widget_instance *instance;
1078 for (instance = info->instances; instance; instance = instance->next)
1079 if (instance->pop_up_p && instance->widget)
1082 if (lw_lucid_widget_p (instance->widget))
1084 XtRealizeWidget (instance->widget);
1085 xlw_pop_instance (instance, up);
1089 if (lw_motif_widget_p (instance->widget))
1091 XtRealizeWidget (instance->widget);
1092 xm_pop_instance (instance, up);
1096 if (lw_xaw_widget_p (instance->widget))
1098 XtRealizeWidget (XtParent (instance->widget));
1099 XtRealizeWidget (instance->widget);
1100 xaw_pop_instance (instance, up);
1107 lw_pop_up_all_widgets (LWLIB_ID id)
1109 lw_pop_all_widgets (id, True);
1113 lw_pop_down_all_widgets (LWLIB_ID id)
1115 lw_pop_all_widgets (id, False);
1119 lw_popup_menu (Widget widget, XEvent *event)
1121 #ifdef LWLIB_MENUBARS_LUCID
1122 if (lw_lucid_widget_p (widget))
1123 xlw_popup_menu (widget, event);
1125 #ifdef LWLIB_MENUBARS_MOTIF
1126 if (lw_motif_widget_p (widget))
1127 xm_popup_menu (widget, event);
1129 #ifdef LWLIB_MENUBARS_ATHENA
1130 if (lw_xaw_widget_p (widget))
1131 xaw_popup_menu (widget, event); /* not implemented */
1135 \f/* get the values back */
1137 get_one_value (widget_instance *instance, widget_value *val)
1139 Widget widget = name_to_widget (instance, val->name);
1144 if (lw_lucid_widget_p (instance->widget))
1145 xlw_update_one_value (instance, widget, val);
1148 if (lw_motif_widget_p (instance->widget))
1149 xm_update_one_value (instance, widget, val);
1152 if (lw_xaw_widget_p (instance->widget))
1153 xaw_update_one_value (instance, widget, val);
1162 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
1164 widget_info *info = get_widget_info (id, False);
1165 widget_instance *instance;
1167 Boolean result = False;
1172 instance = info->instances;
1176 for (val = val_out; val; val = val->next)
1177 if (get_one_value (instance, val))
1184 lw_get_all_values (LWLIB_ID id)
1186 widget_info *info = get_widget_info (id, False);
1187 widget_value *val = info->val;
1188 if (lw_get_some_values (id, val))
1194 /* internal function used by the library dependent implementation to get the
1195 widget_value for a given widget in an instance */
1197 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
1199 char *name = XtName (w);
1201 for (cur = instance->info->val; cur; cur = cur->next)
1202 if (!strcmp (cur->name, name))
1208 /* update other instances value when one thing changed */
1209 /* This function can be used as a an XtCallback for the widgets that get
1210 modified to update other instances of the widgets. Closure should be the
1213 lw_internal_update_other_instances (Widget widget, XtPointer closure,
1214 XtPointer call_data)
1216 /* To forbid recursive calls */
1217 static Boolean updating;
1219 widget_instance *instance = (widget_instance*)closure;
1220 char *name = XtName (widget);
1222 widget_instance *cur;
1225 /* never recurse as this could cause infinite recursions. */
1229 /* protect against the widget being destroyed */
1230 if (XtWidgetBeingDestroyedP (widget))
1233 /* Return immediately if there are no other instances */
1234 info = instance->info;
1235 if (!info->instances->next)
1240 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1242 if (val && get_one_value (instance, val))
1243 for (cur = info->instances; cur; cur = cur->next)
1244 if (cur != instance)
1245 set_one_value (cur, val, True);
1255 lw_get_widget_id (Widget w)
1257 widget_instance *instance = get_widget_instance (w, False);
1259 return instance ? instance->info->id : 0;
1263 /* set the keyboard focus */
1265 lw_set_keyboard_focus (Widget parent, Widget w)
1267 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION)
1268 /* This loses with Lesstif v0.75a */
1269 xm_set_keyboard_focus (parent, w);
1271 XtSetKeyboardFocus (parent, w);
1278 show_one_widget_busy (Widget w, Boolean flag)
1280 Pixel foreground = 0;
1281 Pixel background = 1;
1282 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1285 if (!widget_to_invert)
1286 widget_to_invert = w;
1288 XtSetArg (al [0], XtNforeground, &foreground);
1289 XtSetArg (al [1], XtNbackground, &background);
1290 XtGetValues (widget_to_invert, al, 2);
1292 XtSetArg (al [0], XtNforeground, background);
1293 XtSetArg (al [1], XtNbackground, foreground);
1294 XtSetValues (widget_to_invert, al, 2);
1298 lw_show_busy (Widget w, Boolean busy)
1300 widget_instance *instance = get_widget_instance (w, False);
1302 widget_instance *next;
1306 info = instance->info;
1307 if (info->busy != busy)
1309 for (next = info->instances; next; next = next->next)
1311 show_one_widget_busy (next->widget, busy);
1317 void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
1320 if (wv->nargs && wv->args)
1322 for (i = 0; i<wv->nargs; i++)
1324 addto[i + *offset] = wv->args[i];
1326 *offset += wv->nargs;