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);
270 #endif /* HAVE_WIDGETS */
272 /* Make a complete copy of a widget_value tree. Store CHANGE into
273 the widget_value tree's `change' field. */
275 static widget_value *
276 copy_widget_value_tree (widget_value *val, change_type change)
282 if (val == (widget_value *) 1)
285 copy = malloc_widget_value ();
288 /* #### - don't seg fault *here* if out of memory. Menus will be
289 truncated inexplicably. */
290 copy->type = val->type;
291 copy->name = safe_strdup (val->name);
292 copy->value = safe_strdup (val->value);
293 copy->key = safe_strdup (val->key);
294 copy->accel = val->accel;
295 copy->enabled = val->enabled;
296 copy->selected = val->selected;
297 copy->edited = False;
298 copy->change = change;
299 copy->contents = copy_widget_value_tree (val->contents, change);
300 copy->call_data = val->call_data;
301 copy->next = copy_widget_value_tree (val->next, change);
302 copy->toolkit_data = NULL;
303 copy->free_toolkit_data = False;
305 lw_copy_widget_value_args (val, copy);
306 #ifdef NEED_SCROLLBARS
307 copy_scrollbar_values (val, copy);
313 /* This function is used to implement incremental menu construction. */
316 replace_widget_value_tree (widget_value *node, widget_value *newtree)
320 if (!node || !newtree)
323 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE);
325 free_widget_value_contents (node);
327 free_widget_value (copy); /* free the node, but not its contents. */
332 allocate_widget_info (const char *type, const char *name,
333 LWLIB_ID id, widget_value *val,
334 lw_callback pre_activate_cb, lw_callback selection_cb,
335 lw_callback post_activate_cb)
337 widget_info *info = (widget_info *) malloc (sizeof (widget_info));
338 info->type = safe_strdup (type);
339 info->name = safe_strdup (name);
341 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
343 info->pre_activate_cb = pre_activate_cb;
344 info->selection_cb = selection_cb;
345 info->post_activate_cb = post_activate_cb;
346 info->instances = NULL;
348 info->next = all_widget_info;
349 all_widget_info = info;
355 free_widget_info (widget_info *info)
357 safe_free_str (info->type);
358 safe_free_str (info->name);
359 free_widget_value_tree (info->val);
360 memset (info, '\0', sizeof (widget_info));
365 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
367 widget_instance *instance = (widget_instance*)closure;
369 /* be very conservative */
370 if (instance->widget == widget)
371 instance->widget = NULL;
374 static widget_instance *
375 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
377 widget_instance *instance =
378 (widget_instance *) malloc (sizeof (widget_instance));
379 instance->parent = parent;
380 instance->pop_up_p = pop_up_p;
381 instance->info = info;
382 instance->next = info->instances;
383 info->instances = instance;
385 instantiate_widget_instance (instance);
387 XtAddCallback (instance->widget, XtNdestroyCallback,
388 mark_widget_destroyed, (XtPointer)instance);
393 free_widget_instance (widget_instance *instance)
395 memset (instance, '\0', sizeof (widget_instance));
400 get_widget_info (LWLIB_ID id, Boolean remove_p)
404 for (prev = NULL, info = all_widget_info;
406 prev = info, info = info->next)
412 prev->next = info->next;
414 all_widget_info = info->next;
421 /* Internal function used by the library dependent implementation to get the
422 widget_value for a given widget in an instance */
424 lw_get_widget_info (LWLIB_ID id)
426 return get_widget_info (id, 0);
430 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value,
437 retval = map_widget_values (value->contents, mapfunc, closure);
442 retval = map_widget_values (value->next, mapfunc, closure);
446 return (mapfunc) (value, closure);
450 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value,
454 widget_info *info = get_widget_info (id, 0);
460 return map_widget_values (info->val, mapfunc, closure);
464 static widget_instance *
465 get_widget_instance (Widget widget, Boolean remove_p)
468 widget_instance *instance;
469 widget_instance *prev;
470 for (info = all_widget_info; info; info = info->next)
471 for (prev = NULL, instance = info->instances;
473 prev = instance, instance = instance->next)
474 if (instance->widget == widget)
479 prev->next = instance->next;
481 info->instances = instance->next;
485 return (widget_instance *) 0;
488 static widget_instance*
489 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
491 widget_info *info = get_widget_info (id, False);
492 widget_instance *instance;
495 for (instance = info->instances; instance; instance = instance->next)
496 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
503 /* utility function for widget_value */
505 safe_strcmp (const char *s1, const char *s2)
507 if (!!s1 ^ !!s2) return True;
508 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
513 max (change_type i1, change_type i2)
515 return (int)i1 > (int)i2 ? i1 : i2;
521 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
522 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
524 (oc == NO_CHANGE ? "none" : \
525 (oc == INVISIBLE_CHANGE ? "invisible" : \
526 (oc == VISIBLE_CHANGE ? "visible" : \
527 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
529 (nc == NO_CHANGE ? "none" : \
530 (nc == INVISIBLE_CHANGE ? "invisible" : \
531 (nc == VISIBLE_CHANGE ? "visible" : \
532 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
535 # define EXPLAIN(name, oc, nc, desc, a1, a2)
539 static widget_value *
540 merge_widget_value (widget_value *val1, widget_value *val2, int level)
543 widget_value *merged_next;
544 widget_value *merged_contents;
549 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
555 free_widget_value_tree (val1);
561 if (val1->type != val2->type)
563 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change",
564 val1->type, val2->type);
565 change = max (change, STRUCTURAL_CHANGE);
566 val1->type = val2->type;
568 if (safe_strcmp (val1->name, val2->name))
570 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
571 val1->name, val2->name);
572 change = max (change, STRUCTURAL_CHANGE);
573 safe_free_str (val1->name);
574 val1->name = safe_strdup (val2->name);
576 if (safe_strcmp (val1->value, val2->value))
578 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
579 val1->value, val2->value);
580 change = max (change, VISIBLE_CHANGE);
581 safe_free_str (val1->value);
582 val1->value = safe_strdup (val2->value);
584 if (safe_strcmp (val1->key, val2->key))
586 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
587 val1->key, val2->key);
588 change = max (change, VISIBLE_CHANGE);
589 safe_free_str (val1->key);
590 val1->key = safe_strdup (val2->key);
592 if (val1->accel != val2->accel)
594 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change",
595 val1->accel, val2->accel);
596 change = max (change, VISIBLE_CHANGE);
597 val1->accel = val2->accel;
599 if (val1->enabled != val2->enabled)
601 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
602 val1->enabled, val2->enabled);
603 change = max (change, VISIBLE_CHANGE);
604 val1->enabled = val2->enabled;
606 if (val1->selected != val2->selected)
608 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
609 val1->selected, val2->selected);
610 change = max (change, VISIBLE_CHANGE);
611 val1->selected = val2->selected;
613 if (val1->call_data != val2->call_data)
615 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
616 val1->call_data, val2->call_data);
617 change = max (change, INVISIBLE_CHANGE);
618 val1->call_data = val2->call_data;
621 if (merge_widget_value_args (val1, val2))
623 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "widget change", 0, 0);
624 change = max (change, VISIBLE_CHANGE);
628 #ifdef NEED_SCROLLBARS
629 if (merge_scrollbar_values (val1, val2))
631 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0);
632 change = max (change, VISIBLE_CHANGE);
639 merge_widget_value (val1->contents, val2->contents, level - 1);
641 if (val1->contents && !merged_contents)
643 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
645 change = max (change, INVISIBLE_CHANGE);
647 else if (merged_contents && merged_contents->change != NO_CHANGE)
649 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
651 change = max (change, INVISIBLE_CHANGE);
654 val1->contents = merged_contents;
657 merged_next = merge_widget_value (val1->next, val2->next, level);
659 if (val1->next && !merged_next)
661 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
663 change = max (change, STRUCTURAL_CHANGE);
665 else if (merged_next)
667 if (merged_next->change)
669 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
672 change = max (change, merged_next->change);
675 val1->next = merged_next;
677 val1->change = change;
679 if (change > NO_CHANGE && val1->toolkit_data)
681 if (val1->free_toolkit_data)
682 XtFree ((char *) val1->toolkit_data);
683 val1->toolkit_data = NULL;
690 /* modifying the widgets */
692 name_to_widget (widget_instance *instance, const char *name)
694 Widget widget = NULL;
696 if (!instance->widget)
699 if (!strcmp (XtName (instance->widget), name))
700 widget = instance->widget;
703 int length = strlen (name) + 2;
704 char *real_name = (char *) alloca (length);
706 strcpy (real_name + 1, name);
708 widget = XtNameToWidget (instance->widget, real_name);
714 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p)
716 Widget widget = name_to_widget (instance, val->name);
721 if (lw_lucid_widget_p (instance->widget))
722 xlw_update_one_widget (instance, widget, val, deep_p);
725 if (lw_motif_widget_p (instance->widget))
726 xm_update_one_widget (instance, widget, val, deep_p);
729 if (lw_xaw_widget_p (instance->widget))
730 xaw_update_one_widget (instance, widget, val, deep_p);
736 update_one_widget_instance (widget_instance *instance, Boolean deep_p)
740 if (!instance->widget)
741 /* the widget was destroyed */
744 for (val = instance->info->val; val; val = val->next)
745 if (val->change != NO_CHANGE)
746 set_one_value (instance, val, deep_p);
750 update_all_widget_values (widget_info *info, Boolean deep_p)
752 widget_instance *instance;
755 for (instance = info->instances; instance; instance = instance->next)
756 update_one_widget_instance (instance, deep_p);
758 for (val = info->val; val; val = val->next)
759 val->change = NO_CHANGE;
763 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p)
765 widget_info *info = get_widget_info (id, False);
766 widget_value *new_val;
767 widget_value *next_new_val;
776 for (new_val = val; new_val; new_val = new_val->next)
778 next_new_val = new_val->next;
779 new_val->next = NULL;
781 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
782 if (!strcmp (cur->name, new_val->name))
787 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
789 prev->next = cur ? cur : next;
791 info->val = cur ? cur : next;
798 /* Could not find it, add it */
800 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
802 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
804 new_val->next = next_new_val;
807 update_all_widget_values (info, deep_p);
811 /* creating the widgets */
814 initialize_widget_instance (widget_instance *instance)
818 for (val = instance->info->val; val; val = val->next)
819 val->change = STRUCTURAL_CHANGE;
821 update_one_widget_instance (instance, True);
823 for (val = instance->info->val; val; val = val->next)
824 val->change = NO_CHANGE;
828 static widget_creation_function
829 find_in_table (const char *type, widget_creation_entry *table)
831 widget_creation_entry *cur;
832 for (cur = table; cur->type; cur++)
833 if (!strcasecmp (type, cur->type))
834 return cur->function;
839 dialog_spec_p (const char *name)
841 /* return True if name matches [EILPQeilpq][1-9][Bb] or
842 [EILPQeilpq][1-9][Bb][Rr][1-9] */
848 case 'E': case 'I': case 'L': case 'P': case 'Q':
849 case 'e': case 'i': case 'l': case 'p': case 'q':
850 if (name [1] >= '0' && name [1] <= '9')
852 if (name [2] != 'B' && name [2] != 'b')
856 if ((name [3] == 'T' || name [3] == 't') && !name [4])
858 if ((name [3] == 'R' || name [3] == 'r')
859 && name [4] >= '0' && name [4] <= '9' && !name [5])
872 instantiate_widget_instance (widget_instance *instance)
874 widget_creation_function function = NULL;
878 function = find_in_table (instance->info->type, xlw_creation_table);
882 function = find_in_table (instance->info->type, xm_creation_table);
886 function = find_in_table (instance->info->type, xaw_creation_table);
891 if (dialog_spec_p (instance->info->type))
893 #ifdef LWLIB_DIALOGS_MOTIF
895 function = xm_create_dialog;
897 #ifdef LWLIB_DIALOGS_ATHENA
899 function = xaw_create_dialog;
901 #ifdef LWLIB_DIALOGS_LUCID
902 /* not yet (not ever?) */
909 fprintf (stderr, "No creation function for widget type %s\n",
910 instance->info->type);
914 instance->widget = (*function) (instance);
916 if (!instance->widget)
919 /* XtRealizeWidget (instance->widget);*/
923 lw_register_widget (const char *type, const char *name,
924 LWLIB_ID id, widget_value *val,
925 lw_callback pre_activate_cb, lw_callback selection_cb,
926 lw_callback post_activate_cb)
928 if (!get_widget_info (id, False))
929 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
934 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
936 widget_instance *instance = find_instance (id, parent, pop_up_p);
937 return instance ? instance->widget : NULL;
941 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
943 widget_instance *instance = find_instance (id, parent, pop_up_p);
947 widget_info *info = get_widget_info (id, False);
950 instance = allocate_widget_instance (info, parent, pop_up_p);
951 initialize_widget_instance (instance);
953 if (!instance->widget)
955 return instance->widget;
959 lw_create_widget (const char *type, const char *name,
960 LWLIB_ID id, widget_value *val,
961 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
962 lw_callback selection_cb, lw_callback post_activate_cb)
964 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
966 return lw_make_widget (id, parent, pop_up_p);
970 /* destroying the widgets */
972 destroy_one_instance (widget_instance *instance)
974 /* Remove the destroy callback on the widget; that callback will try to
975 dereference the instance object (to set its widget slot to 0, since the
976 widget is dead.) Since the instance is now dead, we don't have to worry
977 about the fact that its widget is dead too.
979 This happens in the Phase2Destroy of the widget, so this callback would
980 not have been run until arbitrarily long after the instance was freed.
982 if (instance->widget)
983 XtRemoveCallback (instance->widget, XtNdestroyCallback,
984 mark_widget_destroyed, (XtPointer)instance);
986 if (instance->widget)
988 /* The else are pretty tricky here, including the empty statement
989 at the end because it would be very bad to destroy a widget
992 if (lw_lucid_widget_p (instance->widget))
993 xlw_destroy_instance (instance);
997 if (lw_motif_widget_p (instance->widget))
998 xm_destroy_instance (instance);
1002 if (lw_xaw_widget_p (instance->widget))
1003 xaw_destroy_instance (instance);
1007 /* do not remove the empty statement */
1012 free_widget_instance (instance);
1016 lw_destroy_widget (Widget w)
1018 widget_instance *instance = get_widget_instance (w, True);
1022 widget_info *info = instance->info;
1023 /* instance has already been removed from the list; free it */
1024 destroy_one_instance (instance);
1025 /* if there are no instances left, free the info too */
1026 if (!info->instances)
1027 lw_destroy_all_widgets (info->id);
1032 lw_destroy_all_widgets (LWLIB_ID id)
1034 widget_info *info = get_widget_info (id, True);
1035 widget_instance *instance;
1036 widget_instance *next;
1040 for (instance = info->instances; instance; )
1042 next = instance->next;
1043 destroy_one_instance (instance);
1046 free_widget_info (info);
1051 lw_destroy_everything (void)
1053 while (all_widget_info)
1054 lw_destroy_all_widgets (all_widget_info->id);
1058 lw_destroy_all_pop_ups (void)
1062 widget_instance *instance;
1064 for (info = all_widget_info; info; info = next)
1067 instance = info->instances;
1068 if (instance && instance->pop_up_p)
1069 lw_destroy_all_widgets (info->id);
1074 lw_raise_all_pop_up_widgets (void)
1077 widget_instance *instance;
1078 Widget result = NULL;
1080 for (info = all_widget_info; info; info = info->next)
1081 for (instance = info->instances; instance; instance = instance->next)
1082 if (instance->pop_up_p)
1084 Widget widget = instance->widget;
1087 if (XtIsManaged (widget)
1089 /* What a complete load of crap!!!!
1090 When a dialogShell is on the screen, it is not managed!
1092 || (lw_motif_widget_p (instance->widget) &&
1093 XtIsManaged (first_child (widget)))
1099 XMapRaised (XtDisplay (widget), XtWindow (widget));
1107 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1109 widget_info *info = get_widget_info (id, False);
1110 widget_instance *instance;
1113 for (instance = info->instances; instance; instance = instance->next)
1114 if (instance->pop_up_p && instance->widget)
1117 if (lw_lucid_widget_p (instance->widget))
1119 XtRealizeWidget (instance->widget);
1120 xlw_pop_instance (instance, up);
1124 if (lw_motif_widget_p (instance->widget))
1126 XtRealizeWidget (instance->widget);
1127 xm_pop_instance (instance, up);
1131 if (lw_xaw_widget_p (instance->widget))
1133 XtRealizeWidget (XtParent (instance->widget));
1134 XtRealizeWidget (instance->widget);
1135 xaw_pop_instance (instance, up);
1142 lw_pop_up_all_widgets (LWLIB_ID id)
1144 lw_pop_all_widgets (id, True);
1148 lw_pop_down_all_widgets (LWLIB_ID id)
1150 lw_pop_all_widgets (id, False);
1154 lw_popup_menu (Widget widget, XEvent *event)
1156 #ifdef LWLIB_MENUBARS_LUCID
1157 if (lw_lucid_widget_p (widget))
1158 xlw_popup_menu (widget, event);
1160 #ifdef LWLIB_MENUBARS_MOTIF
1161 if (lw_motif_widget_p (widget))
1162 xm_popup_menu (widget, event);
1164 #ifdef LWLIB_MENUBARS_ATHENA
1165 if (lw_xaw_widget_p (widget))
1166 xaw_popup_menu (widget, event); /* not implemented */
1170 \f/* get the values back */
1172 get_one_value (widget_instance *instance, widget_value *val)
1174 Widget widget = name_to_widget (instance, val->name);
1179 if (lw_lucid_widget_p (instance->widget))
1180 xlw_update_one_value (instance, widget, val);
1183 if (lw_motif_widget_p (instance->widget))
1184 xm_update_one_value (instance, widget, val);
1187 if (lw_xaw_widget_p (instance->widget))
1188 xaw_update_one_value (instance, widget, val);
1197 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
1199 widget_info *info = get_widget_info (id, False);
1200 widget_instance *instance;
1202 Boolean result = False;
1207 instance = info->instances;
1211 for (val = val_out; val; val = val->next)
1212 if (get_one_value (instance, val))
1219 lw_get_all_values (LWLIB_ID id)
1221 widget_info *info = get_widget_info (id, False);
1222 widget_value *val = info->val;
1223 if (lw_get_some_values (id, val))
1229 /* internal function used by the library dependent implementation to get the
1230 widget_value for a given widget in an instance */
1232 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
1234 char *name = XtName (w);
1236 for (cur = instance->info->val; cur; cur = cur->next)
1237 if (!strcmp (cur->name, name))
1243 /* update other instances value when one thing changed */
1244 /* This function can be used as a an XtCallback for the widgets that get
1245 modified to update other instances of the widgets. Closure should be the
1248 lw_internal_update_other_instances (Widget widget, XtPointer closure,
1249 XtPointer call_data)
1251 /* To forbid recursive calls */
1252 static Boolean updating;
1254 widget_instance *instance = (widget_instance*)closure;
1255 char *name = XtName (widget);
1257 widget_instance *cur;
1260 /* never recurse as this could cause infinite recursions. */
1264 /* protect against the widget being destroyed */
1265 if (XtWidgetBeingDestroyedP (widget))
1268 /* Return immediately if there are no other instances */
1269 info = instance->info;
1270 if (!info->instances->next)
1275 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1277 if (val && get_one_value (instance, val))
1278 for (cur = info->instances; cur; cur = cur->next)
1279 if (cur != instance)
1280 set_one_value (cur, val, True);
1290 lw_get_widget_id (Widget w)
1292 widget_instance *instance = get_widget_instance (w, False);
1294 return instance ? instance->info->id : 0;
1298 /* set the keyboard focus */
1300 lw_set_keyboard_focus (Widget parent, Widget w)
1302 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION)
1303 /* This loses with Lesstif v0.75a */
1304 xm_set_keyboard_focus (parent, w);
1306 XtSetKeyboardFocus (parent, w);
1313 show_one_widget_busy (Widget w, Boolean flag)
1315 Pixel foreground = 0;
1316 Pixel background = 1;
1317 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1320 if (!widget_to_invert)
1321 widget_to_invert = w;
1323 XtSetArg (al [0], XtNforeground, &foreground);
1324 XtSetArg (al [1], XtNbackground, &background);
1325 XtGetValues (widget_to_invert, al, 2);
1327 XtSetArg (al [0], XtNforeground, background);
1328 XtSetArg (al [1], XtNbackground, foreground);
1329 XtSetValues (widget_to_invert, al, 2);
1333 lw_show_busy (Widget w, Boolean busy)
1335 widget_instance *instance = get_widget_instance (w, False);
1337 widget_instance *next;
1341 info = instance->info;
1342 if (info->busy != busy)
1344 for (next = info->instances; next; next = next->next)
1346 show_one_widget_busy (next->widget, busy);
1352 void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
1355 if (wv->args && wv->args->nargs)
1357 for (i = 0; i<wv->args->nargs; i++)
1359 addto[i + *offset] = wv->args->args[i];
1361 *offset += wv->args->nargs;
1365 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 /* If the arg is already there then we must replace it. */
1382 for (i = 0; i < wv->args->nargs; i++)
1384 if (!strcmp (wv->args->args[i].name, name))
1386 XtSetArg (wv->args->args [i], name, value);
1390 if (i >= wv->args->nargs)
1392 XtSetArg (wv->args->args [wv->args->nargs], name, value); wv->args->nargs++;
1396 static void free_widget_value_args (widget_value* wv)
1400 if (--wv->args->ref_count <= 0)
1402 #ifdef LWLIB_WIDGETS_MOTIF
1404 for (i = 0; i < wv->args->nargs; i++)
1406 if (!strcmp (wv->args->args[i].name, XmNfontList))
1407 XmFontListFree ((XmFontList)wv->args->args[i].value);
1410 free (wv->args->args);
1417 void lw_copy_widget_value_args (widget_value* val, widget_value* copy)
1419 if (val == copy || val->args == copy->args)
1424 free_widget_value_args (copy);
1429 copy->args = val->args;
1430 copy->args->ref_count++;