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"
43 #ifdef LWLIB_WIDGETS_MOTIF
48 #include "lwlib-Xaw.h"
51 /* #### Does a check need to be put back in here to make sure we have
52 sufficient defines to function properly or are the checks in the
53 makefile sufficient? */
55 /* List of all widgets managed by the library. Note that each "widget"
56 listed here may actually be a tree of widgets; for example, a
57 single entry here might represent a single menubar or popup menu,
58 each of which might be implemented with a tree of widgets.
60 static widget_info *all_widget_info = NULL;
62 /* boolean flag indicating that the menubar is active */
63 int lw_menu_active = 0;
65 /* X11 menubar widget */
66 Widget lw_menubar_widget = NULL;
68 /* whether the last menu operation was a keyboard accelerator */
69 int lw_menu_accelerate = False;
72 /* Forward declarations */
73 static void instantiate_widget_instance (widget_instance *instance);
74 static void free_widget_value_args (widget_value* wv);
77 /* utility functions for widget_instance and widget_info */
79 safe_strdup (CONST char *s)
83 result = (char *) malloc (strlen (s) + 1);
91 safe_free_str (char *s)
96 static widget_value *widget_value_free_list = 0;
99 malloc_widget_value (void)
102 if (widget_value_free_list)
104 wv = widget_value_free_list;
105 widget_value_free_list = wv->free_list;
110 wv = (widget_value *) malloc (sizeof (widget_value));
114 memset (wv, 0, sizeof (widget_value));
119 /* this is analogous to free(). It frees only what was allocated
120 by malloc_widget_value(), and no substructures.
123 free_widget_value (widget_value *wv)
127 wv->free_list = widget_value_free_list;
128 widget_value_free_list = wv;
132 free_widget_value_contents (widget_value *wv)
134 if (wv->name) free (wv->name);
135 if (wv->value) free (wv->value);
136 if (wv->key) free (wv->key);
138 /* #### - all of this 0xDEADBEEF stuff should be unnecessary
139 in production code... it should be conditionalized. */
140 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
142 if (wv->toolkit_data && wv->free_toolkit_data)
144 XtFree ((char *) wv->toolkit_data);
145 wv->toolkit_data = (void *) 0xDEADBEEF;
147 #ifdef NEED_SCROLLBARS
148 if (wv->scrollbar_data)
150 free (wv->scrollbar_data);
151 wv->scrollbar_data = NULL;
154 if (wv->contents && (wv->contents != (widget_value*)1))
156 free_widget_value_tree (wv->contents);
157 wv->contents = (widget_value *) 0xDEADBEEF;
160 free_widget_value_args (wv);
164 free_widget_value_tree (wv->next);
165 wv->next = (widget_value *) 0xDEADBEEF;
170 free_widget_value_tree (widget_value *wv)
175 free_widget_value_contents (wv);
176 free_widget_value (wv);
179 #ifdef NEED_SCROLLBARS
182 copy_scrollbar_values (widget_value *val, widget_value *copy)
184 if (!copy->scrollbar_data)
185 copy->scrollbar_data =
186 (scrollbar_values *) malloc (sizeof (scrollbar_values));
188 if (val->scrollbar_data)
189 *copy->scrollbar_data = *val->scrollbar_data;
191 memset (copy->scrollbar_data, 0, sizeof (scrollbar_values));
195 * Return true if old->scrollbar_data were not equivalent
196 * to new->scrollbar_data.
199 merge_scrollbar_values (widget_value *old, widget_value *new)
201 Boolean changed = False;
203 if (new->scrollbar_data && !old->scrollbar_data)
205 copy_scrollbar_values (new, old);
208 else if (!new->scrollbar_data && old->scrollbar_data)
210 free (old->scrollbar_data);
211 old->scrollbar_data = NULL;
213 else if (new->scrollbar_data && old->scrollbar_data)
215 scrollbar_values *old_sb = old->scrollbar_data;
216 scrollbar_values *new_sb = new->scrollbar_data;
218 if ((old_sb->line_increment != new_sb->line_increment) ||
219 (old_sb->page_increment != new_sb->page_increment) ||
220 (old_sb->minimum != new_sb->minimum) ||
221 (old_sb->maximum != new_sb->maximum) ||
222 (old_sb->slider_size != new_sb->slider_size) ||
223 (old_sb->slider_position != new_sb->slider_position) ||
224 (old_sb->scrollbar_width != new_sb->scrollbar_width) ||
225 (old_sb->scrollbar_height != new_sb->scrollbar_height) ||
226 (old_sb->scrollbar_x != new_sb->scrollbar_x) ||
227 (old_sb->scrollbar_y != new_sb->scrollbar_y))
236 #endif /* NEED_SCROLLBARS */
240 * Return true if old->args was not equivalent
244 merge_widget_value_args (widget_value *old, widget_value *new)
246 Boolean changed = False;
248 if (new->args && !old->args)
250 lw_copy_widget_value_args (new, old);
253 /* Generally we don't want to lose values that are already in the
255 else if (!new->args && old->args)
257 lw_copy_widget_value_args (old, new);
260 else if (new->args && old->args)
262 /* #### Do something more sensible here than just copying the
263 new values (like actually merging the values). */
264 free_widget_value_args (old);
265 lw_copy_widget_value_args (new, old);
271 #endif /* HAVE_WIDGETS */
273 /* Make a complete copy of a widget_value tree. Store CHANGE into
274 the widget_value tree's `change' field. */
276 static widget_value *
277 copy_widget_value_tree (widget_value *val, change_type change)
283 if (val == (widget_value *) 1)
286 copy = malloc_widget_value ();
289 /* #### - don't seg fault *here* if out of memory. Menus will be
290 truncated inexplicably. */
291 copy->type = val->type;
292 copy->name = safe_strdup (val->name);
293 copy->value = safe_strdup (val->value);
294 copy->key = safe_strdup (val->key);
295 copy->accel = val->accel;
296 copy->enabled = val->enabled;
297 copy->selected = val->selected;
298 copy->edited = False;
299 copy->change = change;
300 copy->contents = copy_widget_value_tree (val->contents, change);
301 copy->call_data = val->call_data;
302 copy->next = copy_widget_value_tree (val->next, change);
303 copy->toolkit_data = NULL;
304 copy->free_toolkit_data = False;
306 lw_copy_widget_value_args (val, copy);
307 #ifdef NEED_SCROLLBARS
308 copy_scrollbar_values (val, copy);
314 /* This function is used to implement incremental menu construction. */
317 replace_widget_value_tree (widget_value *node, widget_value *newtree)
321 if (!node || !newtree)
324 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE);
326 free_widget_value_contents (node);
328 free_widget_value (copy); /* free the node, but not its contents. */
333 allocate_widget_info (CONST char *type, CONST char *name,
334 LWLIB_ID id, widget_value *val,
335 lw_callback pre_activate_cb, lw_callback selection_cb,
336 lw_callback post_activate_cb)
338 widget_info *info = (widget_info *) malloc (sizeof (widget_info));
339 info->type = safe_strdup (type);
340 info->name = safe_strdup (name);
342 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
344 info->pre_activate_cb = pre_activate_cb;
345 info->selection_cb = selection_cb;
346 info->post_activate_cb = post_activate_cb;
347 info->instances = NULL;
349 info->next = all_widget_info;
350 all_widget_info = info;
356 free_widget_info (widget_info *info)
358 safe_free_str (info->type);
359 safe_free_str (info->name);
360 free_widget_value_tree (info->val);
361 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
366 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
368 widget_instance *instance = (widget_instance*)closure;
370 /* be very conservative */
371 if (instance->widget == widget)
372 instance->widget = NULL;
375 static widget_instance *
376 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
378 widget_instance *instance =
379 (widget_instance *) malloc (sizeof (widget_instance));
380 instance->parent = parent;
381 instance->pop_up_p = pop_up_p;
382 instance->info = info;
383 instance->next = info->instances;
384 info->instances = instance;
386 instantiate_widget_instance (instance);
388 XtAddCallback (instance->widget, XtNdestroyCallback,
389 mark_widget_destroyed, (XtPointer)instance);
394 free_widget_instance (widget_instance *instance)
396 memset ((void *) instance, 0xDEADBEEF, sizeof (widget_instance));
401 get_widget_info (LWLIB_ID id, Boolean remove_p)
405 for (prev = NULL, info = all_widget_info;
407 prev = info, info = info->next)
413 prev->next = info->next;
415 all_widget_info = info->next;
422 /* Internal function used by the library dependent implementation to get the
423 widget_value for a given widget in an instance */
425 lw_get_widget_info (LWLIB_ID id)
427 return get_widget_info (id, 0);
431 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value,
438 retval = map_widget_values (value->contents, mapfunc, closure);
443 retval = map_widget_values (value->next, mapfunc, closure);
447 return (mapfunc) (value, closure);
451 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value,
455 widget_info *info = get_widget_info (id, 0);
461 return map_widget_values (info->val, mapfunc, closure);
465 static widget_instance *
466 get_widget_instance (Widget widget, Boolean remove_p)
469 widget_instance *instance;
470 widget_instance *prev;
471 for (info = all_widget_info; info; info = info->next)
472 for (prev = NULL, instance = info->instances;
474 prev = instance, instance = instance->next)
475 if (instance->widget == widget)
480 prev->next = instance->next;
482 info->instances = instance->next;
486 return (widget_instance *) 0;
489 static widget_instance*
490 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
492 widget_info *info = get_widget_info (id, False);
493 widget_instance *instance;
496 for (instance = info->instances; instance; instance = instance->next)
497 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
504 /* utility function for widget_value */
506 safe_strcmp (CONST char *s1, CONST char *s2)
508 if (!!s1 ^ !!s2) return True;
509 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
514 max (change_type i1, change_type i2)
516 return (int)i1 > (int)i2 ? i1 : i2;
522 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
523 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
525 (oc == NO_CHANGE ? "none" : \
526 (oc == INVISIBLE_CHANGE ? "invisible" : \
527 (oc == VISIBLE_CHANGE ? "visible" : \
528 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
530 (nc == NO_CHANGE ? "none" : \
531 (nc == INVISIBLE_CHANGE ? "invisible" : \
532 (nc == VISIBLE_CHANGE ? "visible" : \
533 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
536 # define EXPLAIN(name, oc, nc, desc, a1, a2)
540 static widget_value *
541 merge_widget_value (widget_value *val1, widget_value *val2, int level)
544 widget_value *merged_next;
545 widget_value *merged_contents;
550 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
556 free_widget_value_tree (val1);
562 if (val1->type != val2->type)
564 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change",
565 val1->type, val2->type);
566 change = max (change, STRUCTURAL_CHANGE);
567 val1->type = val2->type;
569 if (safe_strcmp (val1->name, val2->name))
571 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
572 val1->name, val2->name);
573 change = max (change, STRUCTURAL_CHANGE);
574 safe_free_str (val1->name);
575 val1->name = safe_strdup (val2->name);
577 if (safe_strcmp (val1->value, val2->value))
579 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
580 val1->value, val2->value);
581 change = max (change, VISIBLE_CHANGE);
582 safe_free_str (val1->value);
583 val1->value = safe_strdup (val2->value);
585 if (safe_strcmp (val1->key, val2->key))
587 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
588 val1->key, val2->key);
589 change = max (change, VISIBLE_CHANGE);
590 safe_free_str (val1->key);
591 val1->key = safe_strdup (val2->key);
593 if (val1->accel != val2->accel)
595 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change",
596 val1->accel, val2->accel);
597 change = max (change, VISIBLE_CHANGE);
598 val1->accel = val2->accel;
600 if (val1->enabled != val2->enabled)
602 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
603 val1->enabled, val2->enabled);
604 change = max (change, VISIBLE_CHANGE);
605 val1->enabled = val2->enabled;
607 if (val1->selected != val2->selected)
609 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
610 val1->selected, val2->selected);
611 change = max (change, VISIBLE_CHANGE);
612 val1->selected = val2->selected;
614 if (val1->call_data != val2->call_data)
616 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
617 val1->call_data, val2->call_data);
618 change = max (change, INVISIBLE_CHANGE);
619 val1->call_data = val2->call_data;
622 if (merge_widget_value_args (val1, val2))
624 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "widget change", 0, 0);
625 change = max (change, VISIBLE_CHANGE);
629 #ifdef NEED_SCROLLBARS
630 if (merge_scrollbar_values (val1, val2))
632 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0);
633 change = max (change, VISIBLE_CHANGE);
640 merge_widget_value (val1->contents, val2->contents, level - 1);
642 if (val1->contents && !merged_contents)
644 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
646 change = max (change, INVISIBLE_CHANGE);
648 else if (merged_contents && merged_contents->change != NO_CHANGE)
650 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
652 change = max (change, INVISIBLE_CHANGE);
655 val1->contents = merged_contents;
658 merged_next = merge_widget_value (val1->next, val2->next, level);
660 if (val1->next && !merged_next)
662 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
664 change = max (change, STRUCTURAL_CHANGE);
666 else if (merged_next)
668 if (merged_next->change)
670 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
673 change = max (change, merged_next->change);
676 val1->next = merged_next;
678 val1->change = change;
680 if (change > NO_CHANGE && val1->toolkit_data)
682 if (val1->free_toolkit_data)
683 XtFree ((char *) val1->toolkit_data);
684 val1->toolkit_data = NULL;
691 /* modifying the widgets */
693 name_to_widget (widget_instance *instance, CONST char *name)
695 Widget widget = NULL;
697 if (!instance->widget)
700 if (!strcmp (XtName (instance->widget), name))
701 widget = instance->widget;
704 int length = strlen (name) + 2;
705 char *real_name = (char *) alloca (length);
707 strcpy (real_name + 1, name);
709 widget = XtNameToWidget (instance->widget, real_name);
715 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p)
717 Widget widget = name_to_widget (instance, val->name);
722 if (lw_lucid_widget_p (instance->widget))
723 xlw_update_one_widget (instance, widget, val, deep_p);
726 if (lw_motif_widget_p (instance->widget))
727 xm_update_one_widget (instance, widget, val, deep_p);
730 if (lw_xaw_widget_p (instance->widget))
731 xaw_update_one_widget (instance, widget, val, deep_p);
737 update_one_widget_instance (widget_instance *instance, Boolean deep_p)
741 if (!instance->widget)
742 /* the widget was destroyed */
745 for (val = instance->info->val; val; val = val->next)
746 if (val->change != NO_CHANGE)
747 set_one_value (instance, val, deep_p);
751 update_all_widget_values (widget_info *info, Boolean deep_p)
753 widget_instance *instance;
756 for (instance = info->instances; instance; instance = instance->next)
757 update_one_widget_instance (instance, deep_p);
759 for (val = info->val; val; val = val->next)
760 val->change = NO_CHANGE;
764 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p)
766 widget_info *info = get_widget_info (id, False);
767 widget_value *new_val;
768 widget_value *next_new_val;
777 for (new_val = val; new_val; new_val = new_val->next)
779 next_new_val = new_val->next;
780 new_val->next = NULL;
782 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
783 if (!strcmp (cur->name, new_val->name))
788 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
790 prev->next = cur ? cur : next;
792 info->val = cur ? cur : next;
799 /* Could not find it, add it */
801 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
803 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
805 new_val->next = next_new_val;
808 update_all_widget_values (info, deep_p);
812 /* creating the widgets */
815 initialize_widget_instance (widget_instance *instance)
819 for (val = instance->info->val; val; val = val->next)
820 val->change = STRUCTURAL_CHANGE;
822 update_one_widget_instance (instance, True);
824 for (val = instance->info->val; val; val = val->next)
825 val->change = NO_CHANGE;
829 static widget_creation_function
830 find_in_table (CONST char *type, widget_creation_entry *table)
832 widget_creation_entry *cur;
833 for (cur = table; cur->type; cur++)
834 if (!strcasecmp (type, cur->type))
835 return cur->function;
840 dialog_spec_p (CONST char *name)
842 /* return True if name matches [EILPQeilpq][1-9][Bb] or
843 [EILPQeilpq][1-9][Bb][Rr][1-9] */
849 case 'E': case 'I': case 'L': case 'P': case 'Q':
850 case 'e': case 'i': case 'l': case 'p': case 'q':
851 if (name [1] >= '0' && name [1] <= '9')
853 if (name [2] != 'B' && name [2] != 'b')
857 if ((name [3] == 'T' || name [3] == 't') && !name [4])
859 if ((name [3] == 'R' || name [3] == 'r')
860 && name [4] >= '0' && name [4] <= '9' && !name [5])
873 instantiate_widget_instance (widget_instance *instance)
875 widget_creation_function function = NULL;
879 function = find_in_table (instance->info->type, xlw_creation_table);
883 function = find_in_table (instance->info->type, xm_creation_table);
887 function = find_in_table (instance->info->type, xaw_creation_table);
892 if (dialog_spec_p (instance->info->type))
894 #ifdef LWLIB_DIALOGS_MOTIF
896 function = xm_create_dialog;
898 #ifdef LWLIB_DIALOGS_ATHENA
900 function = xaw_create_dialog;
902 #ifdef LWLIB_DIALOGS_LUCID
903 /* not yet (not ever?) */
910 fprintf (stderr, "No creation function for widget type %s\n",
911 instance->info->type);
915 instance->widget = (*function) (instance);
917 if (!instance->widget)
920 /* XtRealizeWidget (instance->widget);*/
924 lw_register_widget (CONST char *type, CONST char *name,
925 LWLIB_ID id, widget_value *val,
926 lw_callback pre_activate_cb, lw_callback selection_cb,
927 lw_callback post_activate_cb)
929 if (!get_widget_info (id, False))
930 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
935 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
937 widget_instance *instance = find_instance (id, parent, pop_up_p);
938 return instance ? instance->widget : NULL;
942 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
944 widget_instance *instance = find_instance (id, parent, pop_up_p);
948 widget_info *info = get_widget_info (id, False);
951 instance = allocate_widget_instance (info, parent, pop_up_p);
952 initialize_widget_instance (instance);
954 if (!instance->widget)
956 return instance->widget;
960 lw_create_widget (CONST char *type, CONST char *name,
961 LWLIB_ID id, widget_value *val,
962 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
963 lw_callback selection_cb, lw_callback post_activate_cb)
965 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
967 return lw_make_widget (id, parent, pop_up_p);
971 /* destroying the widgets */
973 destroy_one_instance (widget_instance *instance)
975 /* Remove the destroy callback on the widget; that callback will try to
976 dereference the instance object (to set its widget slot to 0, since the
977 widget is dead.) Since the instance is now dead, we don't have to worry
978 about the fact that its widget is dead too.
980 This happens in the Phase2Destroy of the widget, so this callback would
981 not have been run until arbitrarily long after the instance was freed.
983 if (instance->widget)
984 XtRemoveCallback (instance->widget, XtNdestroyCallback,
985 mark_widget_destroyed, (XtPointer)instance);
987 if (instance->widget)
989 /* The else are pretty tricky here, including the empty statement
990 at the end because it would be very bad to destroy a widget
993 if (lw_lucid_widget_p (instance->widget))
994 xlw_destroy_instance (instance);
998 if (lw_motif_widget_p (instance->widget))
999 xm_destroy_instance (instance);
1003 if (lw_xaw_widget_p (instance->widget))
1004 xaw_destroy_instance (instance);
1008 /* do not remove the empty statement */
1013 free_widget_instance (instance);
1017 lw_destroy_widget (Widget w)
1019 widget_instance *instance = get_widget_instance (w, True);
1023 widget_info *info = instance->info;
1024 /* instance has already been removed from the list; free it */
1025 destroy_one_instance (instance);
1026 /* if there are no instances left, free the info too */
1027 if (!info->instances)
1028 lw_destroy_all_widgets (info->id);
1033 lw_destroy_all_widgets (LWLIB_ID id)
1035 widget_info *info = get_widget_info (id, True);
1036 widget_instance *instance;
1037 widget_instance *next;
1041 for (instance = info->instances; instance; )
1043 next = instance->next;
1044 destroy_one_instance (instance);
1047 free_widget_info (info);
1052 lw_destroy_everything ()
1054 while (all_widget_info)
1055 lw_destroy_all_widgets (all_widget_info->id);
1059 lw_destroy_all_pop_ups ()
1063 widget_instance *instance;
1065 for (info = all_widget_info; info; info = next)
1068 instance = info->instances;
1069 if (instance && instance->pop_up_p)
1070 lw_destroy_all_widgets (info->id);
1075 lw_raise_all_pop_up_widgets (void)
1078 widget_instance *instance;
1079 Widget result = NULL;
1081 for (info = all_widget_info; info; info = info->next)
1082 for (instance = info->instances; instance; instance = instance->next)
1083 if (instance->pop_up_p)
1085 Widget widget = instance->widget;
1088 if (XtIsManaged (widget)
1090 /* What a complete load of crap!!!!
1091 When a dialogShell is on the screen, it is not managed!
1093 || (lw_motif_widget_p (instance->widget) &&
1094 XtIsManaged (first_child (widget)))
1100 XMapRaised (XtDisplay (widget), XtWindow (widget));
1108 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1110 widget_info *info = get_widget_info (id, False);
1111 widget_instance *instance;
1114 for (instance = info->instances; instance; instance = instance->next)
1115 if (instance->pop_up_p && instance->widget)
1118 if (lw_lucid_widget_p (instance->widget))
1120 XtRealizeWidget (instance->widget);
1121 xlw_pop_instance (instance, up);
1125 if (lw_motif_widget_p (instance->widget))
1127 XtRealizeWidget (instance->widget);
1128 xm_pop_instance (instance, up);
1132 if (lw_xaw_widget_p (instance->widget))
1134 XtRealizeWidget (XtParent (instance->widget));
1135 XtRealizeWidget (instance->widget);
1136 xaw_pop_instance (instance, up);
1143 lw_pop_up_all_widgets (LWLIB_ID id)
1145 lw_pop_all_widgets (id, True);
1149 lw_pop_down_all_widgets (LWLIB_ID id)
1151 lw_pop_all_widgets (id, False);
1155 lw_popup_menu (Widget widget, XEvent *event)
1157 #ifdef LWLIB_MENUBARS_LUCID
1158 if (lw_lucid_widget_p (widget))
1159 xlw_popup_menu (widget, event);
1161 #ifdef LWLIB_MENUBARS_MOTIF
1162 if (lw_motif_widget_p (widget))
1163 xm_popup_menu (widget, event);
1165 #ifdef LWLIB_MENUBARS_ATHENA
1166 if (lw_xaw_widget_p (widget))
1167 xaw_popup_menu (widget, event); /* not implemented */
1171 \f/* get the values back */
1173 get_one_value (widget_instance *instance, widget_value *val)
1175 Widget widget = name_to_widget (instance, val->name);
1180 if (lw_lucid_widget_p (instance->widget))
1181 xlw_update_one_value (instance, widget, val);
1184 if (lw_motif_widget_p (instance->widget))
1185 xm_update_one_value (instance, widget, val);
1188 if (lw_xaw_widget_p (instance->widget))
1189 xaw_update_one_value (instance, widget, val);
1198 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
1200 widget_info *info = get_widget_info (id, False);
1201 widget_instance *instance;
1203 Boolean result = False;
1208 instance = info->instances;
1212 for (val = val_out; val; val = val->next)
1213 if (get_one_value (instance, val))
1220 lw_get_all_values (LWLIB_ID id)
1222 widget_info *info = get_widget_info (id, False);
1223 widget_value *val = info->val;
1224 if (lw_get_some_values (id, val))
1230 /* internal function used by the library dependent implementation to get the
1231 widget_value for a given widget in an instance */
1233 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
1235 char *name = XtName (w);
1237 for (cur = instance->info->val; cur; cur = cur->next)
1238 if (!strcmp (cur->name, name))
1244 /* update other instances value when one thing changed */
1245 /* This function can be used as a an XtCallback for the widgets that get
1246 modified to update other instances of the widgets. Closure should be the
1249 lw_internal_update_other_instances (Widget widget, XtPointer closure,
1250 XtPointer call_data)
1252 /* To forbid recursive calls */
1253 static Boolean updating;
1255 widget_instance *instance = (widget_instance*)closure;
1256 char *name = XtName (widget);
1258 widget_instance *cur;
1261 /* never recurse as this could cause infinite recursions. */
1265 /* protect against the widget being destroyed */
1266 if (XtWidgetBeingDestroyedP (widget))
1269 /* Return immediately if there are no other instances */
1270 info = instance->info;
1271 if (!info->instances->next)
1276 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1278 if (val && get_one_value (instance, val))
1279 for (cur = info->instances; cur; cur = cur->next)
1280 if (cur != instance)
1281 set_one_value (cur, val, True);
1291 lw_get_widget_id (Widget w)
1293 widget_instance *instance = get_widget_instance (w, False);
1295 return instance ? instance->info->id : 0;
1299 /* set the keyboard focus */
1301 lw_set_keyboard_focus (Widget parent, Widget w)
1303 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION)
1304 /* This loses with Lesstif v0.75a */
1305 xm_set_keyboard_focus (parent, w);
1307 XtSetKeyboardFocus (parent, w);
1314 show_one_widget_busy (Widget w, Boolean flag)
1316 Pixel foreground = 0;
1317 Pixel background = 1;
1318 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1321 if (!widget_to_invert)
1322 widget_to_invert = w;
1324 XtSetArg (al [0], XtNforeground, &foreground);
1325 XtSetArg (al [1], XtNbackground, &background);
1326 XtGetValues (widget_to_invert, al, 2);
1328 XtSetArg (al [0], XtNforeground, background);
1329 XtSetArg (al [1], XtNbackground, foreground);
1330 XtSetValues (widget_to_invert, al, 2);
1334 lw_show_busy (Widget w, Boolean busy)
1336 widget_instance *instance = get_widget_instance (w, False);
1338 widget_instance *next;
1342 info = instance->info;
1343 if (info->busy != busy)
1345 for (next = info->instances; next; next = next->next)
1347 show_one_widget_busy (next->widget, busy);
1353 void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
1356 if (wv->args && wv->args->nargs)
1358 for (i = 0; i<wv->args->nargs; i++)
1360 addto[i + *offset] = wv->args->args[i];
1362 *offset += wv->args->nargs;
1366 void lw_add_widget_value_arg (widget_value* wv, String name, XtArgVal value)
1370 wv->args = (widget_args *) malloc (sizeof (widget_args));
1371 memset (wv->args, 0, sizeof (widget_args));
1372 wv->args->ref_count = 1;
1373 wv->args->nargs = 0;
1374 wv->args->args = (ArgList) malloc (sizeof (Arg) * 10);
1375 memset (wv->args->args, 0, sizeof (Arg) * 10);
1378 if (wv->args->nargs > 10)
1381 XtSetArg (wv->args->args [wv->args->nargs], name, value); wv->args->nargs++;
1384 static void free_widget_value_args (widget_value* wv)
1388 if (--wv->args->ref_count <= 0)
1390 #ifdef LWLIB_WIDGETS_MOTIF
1392 for (i = 0; i < wv->args->nargs; i++)
1394 if (!strcmp (wv->args->args[i].name, XmNfontList))
1395 XmFontListFree ((XmFontList)wv->args->args[i].value);
1398 free (wv->args->args);
1400 wv->args = (widget_args*)0xDEADBEEF;
1405 void lw_copy_widget_value_args (widget_value* val, widget_value* copy)
1410 free_widget_value_args (copy);
1415 copy->args = val->args;
1416 copy->args->ref_count++;