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 && new->args != old->args)
262 /* #### Do something more sensible here than just copying the
263 new values (like actually merging the values). */
264 lw_copy_widget_value_args (new, old);
267 else if (new->args && new->args == old->args && new->args->args_changed == True)
274 #endif /* HAVE_WIDGETS */
276 /* Make a complete copy of a widget_value tree. Store CHANGE into
277 the widget_value tree's `change' field. */
280 copy_widget_value_tree (widget_value *val, change_type change)
286 if (val == (widget_value *) 1)
289 copy = malloc_widget_value ();
292 /* #### - don't seg fault *here* if out of memory. Menus will be
293 truncated inexplicably. */
294 copy->type = val->type;
295 copy->name = safe_strdup (val->name);
296 copy->value = safe_strdup (val->value);
297 copy->key = safe_strdup (val->key);
298 copy->accel = val->accel;
299 copy->enabled = val->enabled;
300 copy->selected = val->selected;
301 copy->edited = False;
302 copy->change = change;
303 copy->contents = copy_widget_value_tree (val->contents, change);
304 copy->call_data = val->call_data;
305 copy->next = copy_widget_value_tree (val->next, change);
306 copy->toolkit_data = NULL;
307 copy->free_toolkit_data = False;
309 lw_copy_widget_value_args (val, copy);
310 #ifdef NEED_SCROLLBARS
311 copy_scrollbar_values (val, copy);
317 /* This function is used to implement incremental menu construction. */
320 replace_widget_value_tree (widget_value *node, widget_value *newtree)
324 if (!node || !newtree)
327 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE);
329 free_widget_value_contents (node);
331 free_widget_value (copy); /* free the node, but not its contents. */
336 allocate_widget_info (const char *type, const char *name,
337 LWLIB_ID id, widget_value *val,
338 lw_callback pre_activate_cb, lw_callback selection_cb,
339 lw_callback post_activate_cb)
341 widget_info *info = (widget_info *) malloc (sizeof (widget_info));
342 info->type = safe_strdup (type);
343 info->name = safe_strdup (name);
345 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
347 info->pre_activate_cb = pre_activate_cb;
348 info->selection_cb = selection_cb;
349 info->post_activate_cb = post_activate_cb;
350 info->instances = NULL;
352 info->next = all_widget_info;
353 all_widget_info = info;
359 free_widget_info (widget_info *info)
361 safe_free_str (info->type);
362 safe_free_str (info->name);
363 free_widget_value_tree (info->val);
364 memset (info, '\0', sizeof (widget_info));
369 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
371 widget_instance *instance = (widget_instance*)closure;
373 /* be very conservative */
374 if (instance->widget == widget)
375 instance->widget = NULL;
378 static widget_instance *
379 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
381 widget_instance *instance =
382 (widget_instance *) malloc (sizeof (widget_instance));
383 instance->parent = parent;
384 instance->pop_up_p = pop_up_p;
385 instance->info = info;
386 instance->next = info->instances;
387 info->instances = instance;
389 instantiate_widget_instance (instance);
391 XtAddCallback (instance->widget, XtNdestroyCallback,
392 mark_widget_destroyed, (XtPointer)instance);
397 free_widget_instance (widget_instance *instance)
399 memset (instance, '\0', sizeof (widget_instance));
404 get_widget_info (LWLIB_ID id, Boolean remove_p)
408 for (prev = NULL, info = all_widget_info;
410 prev = info, info = info->next)
416 prev->next = info->next;
418 all_widget_info = info->next;
425 /* Internal function used by the library dependent implementation to get the
426 widget_value for a given widget in an instance */
428 lw_get_widget_info (LWLIB_ID id)
430 return get_widget_info (id, 0);
434 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value,
441 retval = map_widget_values (value->contents, mapfunc, closure);
446 retval = map_widget_values (value->next, mapfunc, closure);
450 return (mapfunc) (value, closure);
454 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value,
458 widget_info *info = get_widget_info (id, 0);
464 return map_widget_values (info->val, mapfunc, closure);
468 static widget_instance *
469 get_widget_instance (Widget widget, Boolean remove_p)
472 widget_instance *instance;
473 widget_instance *prev;
474 for (info = all_widget_info; info; info = info->next)
475 for (prev = NULL, instance = info->instances;
477 prev = instance, instance = instance->next)
478 if (instance->widget == widget)
483 prev->next = instance->next;
485 info->instances = instance->next;
489 return (widget_instance *) 0;
492 static widget_instance*
493 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
495 widget_info *info = get_widget_info (id, False);
496 widget_instance *instance;
499 for (instance = info->instances; instance; instance = instance->next)
500 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
507 /* utility function for widget_value */
509 safe_strcmp (const char *s1, const char *s2)
511 if (!!s1 ^ !!s2) return True;
512 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
517 max (change_type i1, change_type i2)
519 return (int)i1 > (int)i2 ? i1 : i2;
525 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
526 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
528 (oc == NO_CHANGE ? "none" : \
529 (oc == INVISIBLE_CHANGE ? "invisible" : \
530 (oc == VISIBLE_CHANGE ? "visible" : \
531 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
533 (nc == NO_CHANGE ? "none" : \
534 (nc == INVISIBLE_CHANGE ? "invisible" : \
535 (nc == VISIBLE_CHANGE ? "visible" : \
536 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
539 # define EXPLAIN(name, oc, nc, desc, a1, a2)
543 static widget_value *
544 merge_widget_value (widget_value *val1, widget_value *val2, int level)
547 widget_value *merged_next;
548 widget_value *merged_contents;
553 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
559 free_widget_value_tree (val1);
565 if (val1->type != val2->type)
567 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change",
568 val1->type, val2->type);
569 change = max (change, STRUCTURAL_CHANGE);
570 val1->type = val2->type;
572 if (safe_strcmp (val1->name, val2->name))
574 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
575 val1->name, val2->name);
576 change = max (change, STRUCTURAL_CHANGE);
577 safe_free_str (val1->name);
578 val1->name = safe_strdup (val2->name);
580 if (safe_strcmp (val1->value, val2->value))
582 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
583 val1->value, val2->value);
584 change = max (change, VISIBLE_CHANGE);
585 safe_free_str (val1->value);
586 val1->value = safe_strdup (val2->value);
588 if (safe_strcmp (val1->key, val2->key))
590 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
591 val1->key, val2->key);
592 change = max (change, VISIBLE_CHANGE);
593 safe_free_str (val1->key);
594 val1->key = safe_strdup (val2->key);
596 if (val1->accel != val2->accel)
598 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change",
599 val1->accel, val2->accel);
600 change = max (change, VISIBLE_CHANGE);
601 val1->accel = val2->accel;
603 if (val1->enabled != val2->enabled)
605 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
606 val1->enabled, val2->enabled);
607 change = max (change, VISIBLE_CHANGE);
608 val1->enabled = val2->enabled;
610 if (val1->selected != val2->selected)
612 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
613 val1->selected, val2->selected);
614 change = max (change, VISIBLE_CHANGE);
615 val1->selected = val2->selected;
617 if (val1->call_data != val2->call_data)
619 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
620 val1->call_data, val2->call_data);
621 change = max (change, INVISIBLE_CHANGE);
622 val1->call_data = val2->call_data;
625 if (merge_widget_value_args (val1, val2))
627 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "widget change", 0, 0);
628 change = max (change, VISIBLE_CHANGE);
632 #ifdef NEED_SCROLLBARS
633 if (merge_scrollbar_values (val1, val2))
635 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0);
636 change = max (change, VISIBLE_CHANGE);
643 merge_widget_value (val1->contents, val2->contents, level - 1);
645 if (val1->contents && !merged_contents)
647 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
649 change = max (change, INVISIBLE_CHANGE);
651 else if (merged_contents && merged_contents->change != NO_CHANGE)
653 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
655 change = max (change, INVISIBLE_CHANGE);
658 val1->contents = merged_contents;
661 merged_next = merge_widget_value (val1->next, val2->next, level);
663 if (val1->next && !merged_next)
665 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
667 change = max (change, STRUCTURAL_CHANGE);
669 else if (merged_next)
671 if (merged_next->change)
673 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
676 change = max (change, merged_next->change);
679 val1->next = merged_next;
681 val1->change = change;
683 if (change > NO_CHANGE && val1->toolkit_data)
685 if (val1->free_toolkit_data)
686 XtFree ((char *) val1->toolkit_data);
687 val1->toolkit_data = NULL;
694 /* modifying the widgets */
696 name_to_widget (widget_instance *instance, const char *name)
698 Widget widget = NULL;
700 if (!instance->widget)
703 if (!strcmp (XtName (instance->widget), name))
704 widget = instance->widget;
707 int length = strlen (name) + 2;
708 char *real_name = (char *) alloca (length);
710 strcpy (real_name + 1, name);
712 widget = XtNameToWidget (instance->widget, real_name);
718 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p)
720 Widget widget = name_to_widget (instance, val->name);
725 if (lw_lucid_widget_p (instance->widget))
726 xlw_update_one_widget (instance, widget, val, deep_p);
729 if (lw_motif_widget_p (instance->widget))
730 xm_update_one_widget (instance, widget, val, deep_p);
733 if (lw_xaw_widget_p (instance->widget))
734 xaw_update_one_widget (instance, widget, val, deep_p);
740 update_one_widget_instance (widget_instance *instance, Boolean deep_p)
744 if (!instance->widget)
745 /* the widget was destroyed */
748 for (val = instance->info->val; val; val = val->next)
749 if (val->change != NO_CHANGE)
750 set_one_value (instance, val, deep_p);
754 update_all_widget_values (widget_info *info, Boolean deep_p)
756 widget_instance *instance;
759 for (instance = info->instances; instance; instance = instance->next)
760 update_one_widget_instance (instance, deep_p);
762 for (val = info->val; val; val = val->next)
764 val->change = NO_CHANGE;
766 val->args->args_changed = False;
771 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p)
773 widget_info *info = get_widget_info (id, False);
774 widget_value *new_val;
775 widget_value *next_new_val;
784 for (new_val = val; new_val; new_val = new_val->next)
786 next_new_val = new_val->next;
787 new_val->next = NULL;
789 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
790 if (!strcmp (cur->name, new_val->name))
795 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
797 prev->next = cur ? cur : next;
799 info->val = cur ? cur : next;
806 /* Could not find it, add it */
808 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
810 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
812 new_val->next = next_new_val;
815 update_all_widget_values (info, deep_p);
819 /* creating the widgets */
822 initialize_widget_instance (widget_instance *instance)
826 for (val = instance->info->val; val; val = val->next)
827 val->change = STRUCTURAL_CHANGE;
829 update_one_widget_instance (instance, True);
831 for (val = instance->info->val; val; val = val->next)
833 val->change = NO_CHANGE;
835 val->args->args_changed = False;
839 /* strcasecmp() is not sufficiently portable or standard,
840 and it's easier just to write our own. */
842 ascii_strcasecmp (const char *s1, const char *s2)
848 if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
849 if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
850 if (c1 != c2) return c1 - c2;
851 if (c1 == '\0') return 0;
855 static widget_creation_function
856 find_in_table (const char *type, const widget_creation_entry table[])
858 const widget_creation_entry *cur;
859 for (cur = table; cur->type; cur++)
860 if (!ascii_strcasecmp (type, cur->type))
861 return cur->function;
866 dialog_spec_p (const char *name)
868 /* return True if name matches [EILPQeilpq][1-9][Bb] or
869 [EILPQeilpq][1-9][Bb][Rr][1-9] */
875 case 'E': case 'I': case 'L': case 'P': case 'Q':
876 case 'e': case 'i': case 'l': case 'p': case 'q':
877 if (name [1] >= '0' && name [1] <= '9')
879 if (name [2] != 'B' && name [2] != 'b')
883 if ((name [3] == 'T' || name [3] == 't') && !name [4])
885 if ((name [3] == 'R' || name [3] == 'r')
886 && name [4] >= '0' && name [4] <= '9' && !name [5])
899 instantiate_widget_instance (widget_instance *instance)
901 widget_creation_function function = NULL;
905 function = find_in_table (instance->info->type, xlw_creation_table);
909 function = find_in_table (instance->info->type, xm_creation_table);
913 function = find_in_table (instance->info->type, xaw_creation_table);
918 if (dialog_spec_p (instance->info->type))
920 #ifdef LWLIB_DIALOGS_MOTIF
922 function = xm_create_dialog;
924 #ifdef LWLIB_DIALOGS_ATHENA
926 function = xaw_create_dialog;
928 #ifdef LWLIB_DIALOGS_LUCID
929 /* not yet (not ever?) */
936 fprintf (stderr, "No creation function for widget type %s\n",
937 instance->info->type);
941 instance->widget = (*function) (instance);
943 if (!instance->widget)
946 /* XtRealizeWidget (instance->widget);*/
950 lw_register_widget (const char *type, const char *name,
951 LWLIB_ID id, widget_value *val,
952 lw_callback pre_activate_cb, lw_callback selection_cb,
953 lw_callback post_activate_cb)
955 if (!get_widget_info (id, False))
956 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
961 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
963 widget_instance *instance = find_instance (id, parent, pop_up_p);
964 return instance ? instance->widget : NULL;
968 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
970 widget_instance *instance = find_instance (id, parent, pop_up_p);
974 widget_info *info = get_widget_info (id, False);
977 instance = allocate_widget_instance (info, parent, pop_up_p);
978 initialize_widget_instance (instance);
980 if (!instance->widget)
982 return instance->widget;
986 lw_create_widget (const char *type, const char *name,
987 LWLIB_ID id, widget_value *val,
988 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
989 lw_callback selection_cb, lw_callback post_activate_cb)
991 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
993 return lw_make_widget (id, parent, pop_up_p);
997 /* destroying the widgets */
999 destroy_one_instance (widget_instance *instance)
1001 /* Remove the destroy callback on the widget; that callback will try to
1002 dereference the instance object (to set its widget slot to 0, since the
1003 widget is dead.) Since the instance is now dead, we don't have to worry
1004 about the fact that its widget is dead too.
1006 This happens in the Phase2Destroy of the widget, so this callback would
1007 not have been run until arbitrarily long after the instance was freed.
1009 if (instance->widget)
1010 XtRemoveCallback (instance->widget, XtNdestroyCallback,
1011 mark_widget_destroyed, (XtPointer)instance);
1013 if (instance->widget)
1015 /* The else are pretty tricky here, including the empty statement
1016 at the end because it would be very bad to destroy a widget
1019 if (lw_lucid_widget_p (instance->widget))
1020 xlw_destroy_instance (instance);
1024 if (lw_motif_widget_p (instance->widget))
1025 xm_destroy_instance (instance);
1029 if (lw_xaw_widget_p (instance->widget))
1030 xaw_destroy_instance (instance);
1034 /* do not remove the empty statement */
1039 free_widget_instance (instance);
1043 lw_destroy_widget (Widget w)
1045 widget_instance *instance = get_widget_instance (w, True);
1049 widget_info *info = instance->info;
1050 /* instance has already been removed from the list; free it */
1051 destroy_one_instance (instance);
1052 /* if there are no instances left, free the info too */
1053 if (!info->instances)
1054 lw_destroy_all_widgets (info->id);
1059 lw_destroy_all_widgets (LWLIB_ID id)
1061 widget_info *info = get_widget_info (id, True);
1062 widget_instance *instance;
1063 widget_instance *next;
1067 for (instance = info->instances; instance; )
1069 next = instance->next;
1070 destroy_one_instance (instance);
1073 free_widget_info (info);
1078 lw_destroy_everything (void)
1080 while (all_widget_info)
1081 lw_destroy_all_widgets (all_widget_info->id);
1085 lw_destroy_all_pop_ups (void)
1089 widget_instance *instance;
1091 for (info = all_widget_info; info; info = next)
1094 instance = info->instances;
1095 if (instance && instance->pop_up_p)
1096 lw_destroy_all_widgets (info->id);
1101 lw_raise_all_pop_up_widgets (void)
1104 widget_instance *instance;
1105 Widget result = NULL;
1107 for (info = all_widget_info; info; info = info->next)
1108 for (instance = info->instances; instance; instance = instance->next)
1109 if (instance->pop_up_p)
1111 Widget widget = instance->widget;
1114 if (XtIsManaged (widget)
1116 /* What a complete load of crap!!!!
1117 When a dialogShell is on the screen, it is not managed!
1119 || (lw_motif_widget_p (instance->widget) &&
1120 XtIsManaged (first_child (widget)))
1126 XMapRaised (XtDisplay (widget), XtWindow (widget));
1134 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1136 widget_info *info = get_widget_info (id, False);
1137 widget_instance *instance;
1140 for (instance = info->instances; instance; instance = instance->next)
1141 if (instance->pop_up_p && instance->widget)
1144 if (lw_lucid_widget_p (instance->widget))
1146 XtRealizeWidget (instance->widget);
1147 xlw_pop_instance (instance, up);
1151 if (lw_motif_widget_p (instance->widget))
1153 XtRealizeWidget (instance->widget);
1154 xm_pop_instance (instance, up);
1158 if (lw_xaw_widget_p (instance->widget))
1160 XtRealizeWidget (XtParent (instance->widget));
1161 XtRealizeWidget (instance->widget);
1162 xaw_pop_instance (instance, up);
1169 lw_pop_up_all_widgets (LWLIB_ID id)
1171 lw_pop_all_widgets (id, True);
1175 lw_pop_down_all_widgets (LWLIB_ID id)
1177 lw_pop_all_widgets (id, False);
1181 lw_popup_menu (Widget widget, XEvent *event)
1183 #ifdef LWLIB_MENUBARS_LUCID
1184 if (lw_lucid_widget_p (widget))
1185 xlw_popup_menu (widget, event);
1187 #ifdef LWLIB_MENUBARS_MOTIF
1188 if (lw_motif_widget_p (widget))
1189 xm_popup_menu (widget, event);
1191 #ifdef LWLIB_MENUBARS_ATHENA
1192 if (lw_xaw_widget_p (widget))
1193 xaw_popup_menu (widget, event); /* not implemented */
1197 \f/* get the values back */
1199 get_one_value (widget_instance *instance, widget_value *val)
1201 Widget widget = name_to_widget (instance, val->name);
1206 if (lw_lucid_widget_p (instance->widget))
1207 xlw_update_one_value (instance, widget, val);
1210 if (lw_motif_widget_p (instance->widget))
1211 xm_update_one_value (instance, widget, val);
1214 if (lw_xaw_widget_p (instance->widget))
1215 xaw_update_one_value (instance, widget, val);
1224 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
1226 widget_info *info = get_widget_info (id, False);
1227 widget_instance *instance;
1229 Boolean result = False;
1234 instance = info->instances;
1238 for (val = val_out; val; val = val->next)
1239 if (get_one_value (instance, val))
1246 lw_get_all_values (LWLIB_ID id)
1248 widget_info *info = get_widget_info (id, False);
1249 widget_value *val = info->val;
1250 if (lw_get_some_values (id, val))
1256 /* internal function used by the library dependent implementation to get the
1257 widget_value for a given widget in an instance */
1259 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
1261 char *name = XtName (w);
1263 for (cur = instance->info->val; cur; cur = cur->next)
1264 if (!strcmp (cur->name, name))
1270 /* update other instances value when one thing changed */
1271 /* This function can be used as a an XtCallback for the widgets that get
1272 modified to update other instances of the widgets. Closure should be the
1275 lw_internal_update_other_instances (Widget widget, XtPointer closure,
1276 XtPointer call_data)
1278 /* To forbid recursive calls */
1279 static Boolean updating;
1281 widget_instance *instance = (widget_instance*)closure;
1282 char *name = XtName (widget);
1284 widget_instance *cur;
1287 /* never recurse as this could cause infinite recursions. */
1291 /* protect against the widget being destroyed */
1292 if (XtWidgetBeingDestroyedP (widget))
1295 /* Return immediately if there are no other instances */
1296 info = instance->info;
1297 if (!info->instances->next)
1302 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1304 if (val && get_one_value (instance, val))
1305 for (cur = info->instances; cur; cur = cur->next)
1306 if (cur != instance)
1307 set_one_value (cur, val, True);
1317 lw_get_widget_id (Widget w)
1319 widget_instance *instance = get_widget_instance (w, False);
1321 return instance ? instance->info->id : 0;
1325 /* set the keyboard focus */
1327 lw_set_keyboard_focus (Widget parent, Widget w)
1329 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION)
1330 /* This loses with Lesstif v0.75a */
1331 xm_set_keyboard_focus (parent, w);
1333 XtSetKeyboardFocus (parent, w);
1340 show_one_widget_busy (Widget w, Boolean flag)
1342 Pixel foreground = 0;
1343 Pixel background = 1;
1344 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1347 if (!widget_to_invert)
1348 widget_to_invert = w;
1350 XtSetArg (al [0], XtNforeground, &foreground);
1351 XtSetArg (al [1], XtNbackground, &background);
1352 XtGetValues (widget_to_invert, al, 2);
1354 XtSetArg (al [0], XtNforeground, background);
1355 XtSetArg (al [1], XtNbackground, foreground);
1356 XtSetValues (widget_to_invert, al, 2);
1360 lw_show_busy (Widget w, Boolean busy)
1362 widget_instance *instance = get_widget_instance (w, False);
1364 widget_instance *next;
1368 info = instance->info;
1369 if (info->busy != busy)
1371 for (next = info->instances; next; next = next->next)
1373 show_one_widget_busy (next->widget, busy);
1379 void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
1382 if (wv->args && wv->args->nargs)
1384 for (i = 0; i<wv->args->nargs; i++)
1386 addto[i + *offset] = wv->args->args[i];
1388 *offset += wv->args->nargs;
1392 XtArgVal lw_get_value_arg (widget_value* wv, String name)
1397 for (i = 0; i < wv->args->nargs; i++)
1399 if (!strcmp (wv->args->args[i].name, name))
1401 return wv->args->args[i].value;
1408 void lw_add_widget_value_arg (widget_value* wv, String name, XtArgVal value)
1413 wv->args = (widget_args *) malloc (sizeof (widget_args));
1414 memset (wv->args, '\0', sizeof (widget_args));
1415 wv->args->ref_count = 1;
1416 wv->args->nargs = 0;
1417 wv->args->args = (ArgList) malloc (sizeof (Arg) * 10);
1418 memset (wv->args->args, '\0', sizeof (Arg) * 10);
1421 if (wv->args->nargs > 10)
1424 /* Register the change. */
1425 wv->args->args_changed = True;
1426 /* If the arg is already there then we must replace it. */
1427 for (i = 0; i < wv->args->nargs; i++)
1429 if (!strcmp (wv->args->args[i].name, name))
1431 XtSetArg (wv->args->args [i], name, value);
1435 if (i >= wv->args->nargs)
1437 XtSetArg (wv->args->args [wv->args->nargs], name, value); wv->args->nargs++;
1441 static void free_widget_value_args (widget_value* wv)
1445 if (--wv->args->ref_count <= 0)
1447 #ifdef LWLIB_WIDGETS_MOTIF
1449 for (i = 0; i < wv->args->nargs; i++)
1451 if (!strcmp (wv->args->args[i].name, XmNfontList))
1452 XmFontListFree ((XmFontList)wv->args->args[i].value);
1455 free (wv->args->args);
1462 void lw_copy_widget_value_args (widget_value* val, widget_value* copy)
1464 if (val == copy || val->args == copy->args)
1469 free_widget_value_args (copy);
1474 copy->args = val->args;
1475 copy->args->ref_count++;
1479 /* Remove %_ and convert %% to %. We can do this in-place because we
1480 are always shortening, never lengthening, the string. */
1482 lw_remove_accelerator_spec (char *val)
1484 char *foo = val, *bar = val;
1488 if (*bar == '%' && *(bar+1) == '_')
1490 else if (*bar == '%' && *(bar+1) == '%')