X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/42de618f8f4c2908a710b059f582e5808cd046b2..8f924df7df019cce90537647de2627581043b5c4:/lwlib/lwlib-Xm.c diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c index c5da97f85e..b22c59a7a1 100644 --- a/lwlib/lwlib-Xm.c +++ b/lwlib/lwlib-Xm.c @@ -3,13 +3,13 @@ This file is part of the Lucid Widget Library. -The Lucid Widget Library is free software; you can redistribute it and/or +The Lucid Widget Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. The Lucid Widget Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of +but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -18,9 +18,11 @@ along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#ifdef HAVE_CONFIG_H +#include +#endif + #include -#include #include #include @@ -29,6 +31,8 @@ Boston, MA 02111-1307, USA. */ #include #include +#include "../src/lisp.h" + #include "lwlib-Xm.h" #include "lwlib-utils.h" @@ -57,19 +61,18 @@ Boston, MA 02111-1307, USA. */ #include #include -static void xm_pull_down_callback (/* Widget, XtPointer, XtPointer */); -static void xm_internal_update_other_instances (/* Widget, XtPointer, - XtPointer */); -static void xm_generic_callback (/* Widget, XtPointer, XtPointer */); -static void xm_nosel_callback (/* Widget, XtPointer, XtPointer */); -static void xm_pop_down_callback (/* Widget, XtPointer, XtPointer */); +#undef P_ +#if defined __STDC__ || defined PROTOTYPES +#define P_(X) X +#else +#define P_(X) () +#endif -static void xm_update_menu (/* widget_instance*, Widget, widget_value*, - Boolean) */); +enum do_call_type { pre_activate, selection, no_selection, post_activate }; /* Structures to keep destroyed instances */ -typedef struct _destroyed_instance +typedef struct _destroyed_instance { char* name; char* type; @@ -79,8 +82,93 @@ typedef struct _destroyed_instance struct _destroyed_instance* next; } destroyed_instance; -static destroyed_instance* -all_destroyed_instances = NULL; +static destroyed_instance *make_destroyed_instance P_ ((char *, char *, + Widget, Widget, + Boolean)); +static void free_destroyed_instance P_ ((destroyed_instance*)); +Widget first_child P_ ((Widget)); +Boolean lw_motif_widget_p P_ ((Widget)); +static XmString resource_motif_string P_ ((Widget, char *)); +static void destroy_all_children P_ ((Widget, int)); +static void xm_update_label P_ ((widget_instance *, Widget, widget_value *)); +static void xm_update_list P_ ((widget_instance *, Widget, widget_value *)); +static void xm_update_pushbutton P_ ((widget_instance *, Widget, + widget_value *)); +static void xm_update_cascadebutton P_ ((widget_instance *, Widget, + widget_value *)); +static void xm_update_toggle P_ ((widget_instance *, Widget, widget_value *)); +static void xm_update_radiobox P_ ((widget_instance *, Widget, widget_value *)); +static void make_menu_in_widget P_ ((widget_instance *, Widget, + widget_value *, int)); +static void update_one_menu_entry P_ ((widget_instance *, Widget, + widget_value *, Boolean)); +static void xm_update_menu P_ ((widget_instance *, Widget, widget_value *, + Boolean)); +static void xm_update_text P_ ((widget_instance *, Widget, widget_value *)); +static void xm_update_text_field P_ ((widget_instance *, Widget, + widget_value *)); +void xm_update_one_value P_ ((widget_instance *, Widget, widget_value *)); +static void activate_button P_ ((Widget, XtPointer, XtPointer)); +static Widget make_dialog P_ ((char *, Widget, Boolean, char *, char *, + Boolean, Boolean, Boolean, int, int)); +static destroyed_instance* find_matching_instance P_ ((widget_instance*)); +static void mark_dead_instance_destroyed P_ ((Widget, XtPointer, XtPointer)); +static void recenter_widget P_ ((Widget)); +static Widget recycle_instance P_ ((destroyed_instance*)); +Widget xm_create_dialog P_ ((widget_instance*)); +static Widget make_menubar P_ ((widget_instance*)); +static void remove_grabs P_ ((Widget, XtPointer, XtPointer)); +static Widget make_popup_menu P_ ((widget_instance*)); +static Widget make_main P_ ((widget_instance*)); +void xm_destroy_instance P_ ((widget_instance*)); +void xm_popup_menu P_ ((Widget, XEvent *)); +static void set_min_dialog_size P_ ((Widget)); +static void do_call P_ ((Widget, XtPointer, enum do_call_type)); +static void xm_generic_callback P_ ((Widget, XtPointer, XtPointer)); +static void xm_nosel_callback P_ ((Widget, XtPointer, XtPointer)); +static void xm_pull_down_callback P_ ((Widget, XtPointer, XtPointer)); +static void xm_pop_down_callback P_ ((Widget, XtPointer, XtPointer)); +void xm_set_keyboard_focus P_ ((Widget, Widget)); +void xm_set_main_areas P_ ((Widget, Widget, Widget)); +static void xm_internal_update_other_instances P_ ((Widget, XtPointer, + XtPointer)); +static void xm_arm_callback P_ ((Widget, XtPointer, XtPointer)); + +#if 0 +void xm_update_one_widget P_ ((widget_instance *, Widget, widget_value *, + Boolean)); +void xm_pop_instance P_ ((widget_instance*, Boolean)); +void xm_manage_resizing P_ ((Widget, Boolean)); +#endif + + +#if 0 + +/* Print the complete X resource name of widget WIDGET to stderr. + This is sometimes handy to have available. */ + +void +x_print_complete_resource_name (widget) + Widget widget; +{ + int i; + String names[100]; + + for (i = 0; i < 100 && widget != NULL; ++i) + { + names[i] = XtName (widget); + widget = XtParent (widget); + } + + for (--i; i >= 1; --i) + fprintf (stderr, "%s.", names[i]); + fprintf (stderr, "%s\n", names[0]); +} + +#endif /* 0 */ + + +static destroyed_instance *all_destroyed_instances = NULL; static destroyed_instance* make_destroyed_instance (name, type, widget, parent, pop_up_p) @@ -100,7 +188,7 @@ make_destroyed_instance (name, type, widget, parent, pop_up_p) instance->next = NULL; return instance; } - + static void free_destroyed_instance (instance) destroyed_instance* instance; @@ -122,7 +210,7 @@ Boolean lw_motif_widget_p (widget) Widget widget; { - return + return XtClass (widget) == xmDialogShellWidgetClass || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget); } @@ -134,7 +222,7 @@ resource_motif_string (widget, name) { XtResource resource; XmString result = 0; - + resource.resource_name = name; resource.resource_class = XmCXmString; resource.resource_type = XmRXmString; @@ -166,7 +254,7 @@ destroy_all_children (widget, first_child_to_destroy) XtUnmanageChildren (children + first_child_to_destroy, number - first_child_to_destroy); - /* Unmanage all children and destroy them. They will only be + /* Unmanage all children and destroy them. They will only be really destroyed when we get out of DispatchEvent. */ for (i = first_child_to_destroy; i < number; i++) { @@ -177,10 +265,13 @@ destroy_all_children (widget, first_child_to_destroy) XtCompositeChildren. So get it out of the cascade button and free it. If this child is not a cascade button, then submenu should remain unchanged. */ - XtSetArg (al[0], XmNsubMenuId, &submenu); + XtSetArg (al[0], XmNsubMenuId, &submenu); XtGetValues (children[i], al, 1); if (submenu) - XtDestroyWidget (submenu); + { + destroy_all_children (submenu, 0); + XtDestroyWidget (submenu); + } XtDestroyWidget (children[i]); } @@ -188,7 +279,68 @@ destroy_all_children (widget, first_child_to_destroy) } } - /* update the label of anything subclass of a label */ + + +/* Callback XmNarmCallback and XmNdisarmCallback for buttons in a + menu. CLIENT_DATA contains a pointer to the widget_value + corresponding to widget W. CALL_DATA contains a + XmPushButtonCallbackStruct containing the reason why the callback + is called. */ + +static void +xm_arm_callback (w, client_data, call_data) + Widget w; + XtPointer client_data, call_data; +{ + XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *) call_data; + widget_value *wv = (widget_value *) client_data; + widget_instance *instance; + + /* Get the id of the menu bar or popup menu this widget is in. */ + while (w != NULL) + { + if (XmIsRowColumn (w)) + { + unsigned char type = 0xff; + + XtVaGetValues (w, XmNrowColumnType, &type, NULL); + if (type == XmMENU_BAR || type == XmMENU_POPUP) + break; + } + + w = XtParent (w); + } + + if (w != NULL) + { + instance = lw_get_widget_instance (w); + if (instance && instance->info->highlight_cb) + { + call_data = cbs->reason == XmCR_DISARM ? NULL : wv; + instance->info->highlight_cb (w, instance->info->id, call_data); + } + } +} + + + +/* Update the label of widget WIDGET. WIDGET must be a Label widget + or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains + the value to update. + + Menus: + + Emacs fills VAL->name with the text to display in the menu, and + sets VAL->value to null. Function make_menu_in_widget creates + widgets with VAL->name as resource name. This works because the + Label widget uses its resource name for display if no + XmNlabelString is set. + + Dialogs: + + VAL->name is again set to the resource name, but VAL->value is + not null, and contains the label string to display. */ + static void xm_update_label (instance, widget, val) widget_instance* instance; @@ -200,11 +352,13 @@ xm_update_label (instance, widget, val) XmString key_string = 0; Arg al [256]; int ac; - + ac = 0; if (val->value) { + /* A label string is specified, i.e. we are in a dialog. First + see if it is overridden by something from the resource file. */ res_string = resource_motif_string (widget, val->value); if (res_string) @@ -217,9 +371,10 @@ xm_update_label (instance, widget, val) XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET); XtSetArg (al [ac], XmNlabelString, built_string); ac++; } + XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++; } - + if (val->key) { key_string = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET); @@ -267,7 +422,7 @@ xm_update_pushbutton (instance, widget, val) Widget widget; widget_value* val; { - XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, 0); + XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, NULL); XtRemoveAllCallbacks (widget, XmNactivateCallback); XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance); } @@ -293,9 +448,9 @@ xm_update_toggle (instance, widget, val) { XtRemoveAllCallbacks (widget, XmNvalueChangedCallback); XtAddCallback (widget, XmNvalueChangedCallback, - xm_internal_update_other_instances, instance); + xm_generic_callback, instance); XtVaSetValues (widget, XmNset, val->selected, - XmNalignment, XmALIGNMENT_BEGINNING, 0); + XmNalignment, XmALIGNMENT_BEGINNING, NULL); } static void @@ -323,11 +478,11 @@ xm_update_radiobox (instance, widget, val) toggle = XtNameToWidget (widget, cur->value); if (toggle) { - XtVaSetValues (toggle, XmNsensitive, cur->enabled, 0); + XtSetSensitive (toggle, cur->enabled); if (!val->value && cur->selected) - XtVaSetValues (toggle, XmNset, cur->selected, 0); + XtVaSetValues (toggle, XmNset, cur->selected, NULL); if (val->value && strcmp (val->value, cur->value)) - XtVaSetValues (toggle, XmNset, False, 0); + XtVaSetValues (toggle, XmNset, False, NULL); } } @@ -336,21 +491,12 @@ xm_update_radiobox (instance, widget, val) { toggle = XtNameToWidget (widget, val->value); if (toggle) - XtVaSetValues (toggle, XmNset, True, 0); + XtVaSetValues (toggle, XmNset, True, NULL); } } - /* update a popup menu, pulldown menu or a menubar */ -static Boolean -all_dashes_p (s) - char* s; -{ - char* t; - for (t = s; *t; t++) - if (*t != '-') - return False; - return True; -} + +/* update a popup menu, pulldown menu or a menubar */ /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */ @@ -366,10 +512,12 @@ make_menu_in_widget (instance, widget, val, keep_first_children) int child_index; widget_value* cur; Widget button = 0; + Widget title = 0; Widget menu; Arg al [256]; int ac; Boolean menubar_p; + unsigned char type; Widget* old_children; unsigned int old_num_children; @@ -377,16 +525,24 @@ make_menu_in_widget (instance, widget, val, keep_first_children) old_children = XtCompositeChildren (widget, &old_num_children); /* Allocate the children array */ - for (num_children = 0, cur = val; cur; num_children++, cur = cur->next); + for (num_children = 0, cur = val; cur; num_children++, cur = cur->next) + ; children = (Widget*)XtMalloc (num_children * sizeof (Widget)); - /* tricky way to know if this RowColumn is a menubar or a pulldown... */ - menubar_p = False; - XtSetArg (al[0], XmNisHomogeneous, &menubar_p); + /* WIDGET should be a RowColumn. */ + if (!XmIsRowColumn (widget)) + abort (); + + /* Determine whether WIDGET is a menu bar. */ + type = -1; + XtSetArg (al[0], XmNrowColumnType, &type); XtGetValues (widget, al, 1); + if (type != XmMENU_BAR && type != XmMENU_PULLDOWN && type != XmMENU_POPUP) + abort (); + menubar_p = type == XmMENU_BAR; - /* add the unmap callback for popups and pulldowns */ - /*** this sounds bogus ***/ + /* Add a callback to popups and pulldowns that is called when + it is made invisible again. */ if (!menubar_p) XtAddCallback (XtParent (widget), XmNpopdownCallback, xm_pop_down_callback, (XtPointer)instance); @@ -403,22 +559,26 @@ make_menu_in_widget (instance, widget, val, keep_first_children) /* Create the rest. */ for (child_index = keep_first_children; cur; child_index++, cur = cur->next) - { + { + enum menu_separator separator; + ac = 0; - XtSetArg (al [ac], XmNsensitive, cur->enabled); ac++; - XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; - XtSetArg (al [ac], XmNuserData, cur->call_data); ac++; - + XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++; + XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + XtSetArg (al[ac], XmNuserData, cur->call_data); ac++; + if (instance->pop_up_p && !cur->contents && !cur->call_data - && !all_dashes_p (cur->name)) + && !lw_separator_p (cur->name, &separator, 1)) { ac = 0; XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++; - button = XmCreateLabel (widget, cur->name, al, ac); + title = button = XmCreateLabel (widget, cur->name, al, ac); } - else if (all_dashes_p (cur->name)) + else if (lw_separator_p (cur->name, &separator, 1)) { - button = XmCreateSeparator (widget, cur->name, NULL, 0); + ac = 0; + XtSetArg (al[ac], XmNseparatorType, separator); ++ac; + button = XmCreateSeparator (widget, cur->name, al, ac); } else if (!cur->contents) { @@ -426,25 +586,45 @@ make_menu_in_widget (instance, widget, val, keep_first_children) button = XmCreateCascadeButton (widget, cur->name, al, ac); else if (!cur->call_data) button = XmCreateLabel (widget, cur->name, al, ac); + else if (cur->button_type == BUTTON_TYPE_TOGGLE + || cur->button_type == BUTTON_TYPE_RADIO) + { + XtSetArg (al[ac], XmNset, cur->selected); ++ac; + XtSetArg (al[ac], XmNvisibleWhenOff, True); ++ac; + XtSetArg (al[ac], XmNindicatorType, + (cur->button_type == BUTTON_TYPE_TOGGLE + ? XmN_OF_MANY : XmONE_OF_MANY)); + ++ac; + button = XmCreateToggleButton (widget, cur->name, al, ac); + XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur); + XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur); + } else - button = XmCreatePushButtonGadget (widget, cur->name, al, ac); + { + button = XmCreatePushButton (widget, cur->name, al, ac); + XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur); + XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur); + } xm_update_label (instance, button, cur); - /* don't add a callback to a simple label */ - if (cur->call_data) + /* Add a callback that is called when the button is + selected. Toggle buttons don't support + XmNactivateCallback, we use XmNvalueChangedCallback in + that case. Don't add a callback to a simple label. */ + if (cur->button_type) + xm_update_toggle (instance, button, cur); + else if (cur->call_data) XtAddCallback (button, XmNactivateCallback, xm_generic_callback, (XtPointer)instance); } else { menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0); + make_menu_in_widget (instance, menu, cur->contents, 0); - XtSetArg (al [ac], XmNsubMenuId, menu); ac++; - /* non-zero values don't work reliably in - conjunction with Emacs' event loop */ - XtSetArg (al [ac], XmNmappingDelay, 0); ac++; - button = XmCreateCascadeButtonGadget (widget, cur->name, al, ac); + XtSetArg (al[ac], XmNsubMenuId, menu); ac++; + button = XmCreateCascadeButton (widget, cur->name, al, ac); xm_update_label (instance, button, cur); @@ -452,19 +632,19 @@ make_menu_in_widget (instance, widget, val, keep_first_children) (XtPointer)instance); } - children [child_index] = button; + children[child_index] = button; } - XtManageChildren (children, num_children); - - /* Last entry is the help button. Has to be done after managing - * the buttons otherwise the menubar is only 4 pixels high... */ + /* Last entry is the help button. The original comment read "Has to + be done after managing the buttons otherwise the menubar is only + 4 pixels high." This is no longer true, and to make + XmNmenuHelpWidget work, we need to set it before managing the + children.. --gerd. */ if (button) - { - ac = 0; - XtSetArg (al [ac], XmNmenuHelpWidget, button); ac++; - XtSetValues (widget, al, ac); - } + XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL); + + if (num_children) + XtManageChildren (children, num_children); XtFree ((char *) children); if (old_children) @@ -488,32 +668,78 @@ update_one_menu_entry (instance, widget, val, deep_p) /* update the sensitivity and userdata */ /* Common to all widget types */ - XtVaSetValues (widget, - XmNsensitive, val->enabled, - XmNuserData, val->call_data, - 0); + XtSetSensitive (widget, val->enabled); + XtVaSetValues (widget, XmNuserData, val->call_data, NULL); /* update the menu button as a label. */ if (val->this_one_change >= VISIBLE_CHANGE) - xm_update_label (instance, widget, val); + { + xm_update_label (instance, widget, val); + if (val->button_type) + xm_update_toggle (instance, widget, val); + } /* update the pulldown/pullaside as needed */ ac = 0; menu = NULL; XtSetArg (al [ac], XmNsubMenuId, &menu); ac++; XtGetValues (widget, al, ac); - + contents = val->contents; if (!menu) { if (contents) { - menu = XmCreatePulldownMenu (XtParent (widget), XtName (widget), NULL, 0); - make_menu_in_widget (instance, menu, contents, 0); - ac = 0; - XtSetArg (al [ac], XmNsubMenuId, menu); ac++; - XtSetValues (widget, al, ac); + unsigned int old_num_children, i; + Widget parent; + Widget *widget_list; + + parent = XtParent (widget); + widget_list = XtCompositeChildren (parent, &old_num_children); + + /* Find the widget position within the parent's widget list. */ + for (i = 0; i < old_num_children; i++) + if (strcmp (XtName (widget_list[i]), XtName (widget)) == 0) + break; + if (i == old_num_children) + abort (); + if (XmIsCascadeButton (widget_list[i])) + { + menu = XmCreatePulldownMenu (parent, XtName(widget), NULL, 0); + make_menu_in_widget (instance, menu, contents, 0); + ac = 0; + XtSetArg (al [ac], XmNsubMenuId, menu); ac++; + XtSetValues (widget, al, ac); + } + else + { + Widget button; + + /* The current menuitem is a XmPushButtonGadget, it + needs to be replaced by a CascadeButtonGadget */ + XtDestroyWidget (widget_list[i]); + menu = XmCreatePulldownMenu (parent, val->name, NULL, 0); + make_menu_in_widget (instance, menu, contents, 0); + ac = 0; + XtSetArg (al [ac], XmNsubMenuId, menu); ac++; + /* Non-zero values don't work reliably in + conjunction with Emacs' event loop */ + XtSetArg (al [ac], XmNmappingDelay, 0); ac++; +#ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */ + /* Tell Motif to put it in the right place */ + XtSetArg (al [ac], XmNpositionIndex , i); ac++; +#endif + button = XmCreateCascadeButton (parent, val->name, al, ac); + xm_update_label (instance, button, val); + + XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback, + (XtPointer)instance); + XtManageChild (button); + } + + if (widget_list) + XtFree ((char*) widget_list); } } else if (!contents) @@ -553,7 +779,7 @@ xm_update_menu (instance, widget, val, deep_p) { if (children) { - for (i = 0, cur = val->contents; + for (i = 0, cur = val->contents; (i < num_children && cur); /* how else to ditch unwanted children ?? - mgd */ i++, cur = cur->next) @@ -575,7 +801,10 @@ xm_update_menu (instance, widget, val, deep_p) for (i = 0, cur = val->contents; i < num_children_to_keep; i++) { if (!cur) - abort (); + { + num_children_to_keep = i; + break; + } if (children [i]->core.being_destroyed || strcmp (XtName (children [i]), cur->name)) continue; @@ -590,7 +819,7 @@ xm_update_menu (instance, widget, val, deep_p) { destroy_all_children (widget, num_children_to_keep); make_menu_in_widget (instance, widget, val->contents, - num_children_to_keep); + num_children_to_keep); } XtFree ((char *) children); @@ -638,20 +867,18 @@ xm_update_one_widget (instance, widget, val, deep_p) Boolean deep_p; { WidgetClass class; - + /* Mark as not edited */ val->edited = False; /* Common to all widget types */ - XtVaSetValues (widget, - XmNsensitive, val->enabled, - XmNuserData, val->call_data, - 0); - + XtSetSensitive (widget, val->enabled); + XtVaSetValues (widget, XmNuserData, val->call_data, NULL); + /* Common to all label like widgets */ if (XtIsSubclass (widget, xmLabelWidgetClass)) xm_update_label (instance, widget, val); - + class = XtClass (widget); /* Class specific things */ if (class == xmPushButtonWidgetClass || @@ -673,10 +900,10 @@ xm_update_one_widget (instance, widget, val, deep_p) Boolean radiobox = 0; int ac = 0; Arg al [1]; - + XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++; XtGetValues (widget, al, ac); - + if (radiobox) xm_update_radiobox (instance, widget, val); else @@ -713,10 +940,10 @@ xm_update_one_value (instance, widget, val) val->call_data = old_wv->call_data; break; } - + if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass) { - XtVaGetValues (widget, XmNset, &val->selected, 0); + XtVaGetValues (widget, XmNset, &val->selected, NULL); val->edited = True; } else if (class == xmTextWidgetClass) @@ -738,10 +965,10 @@ xm_update_one_value (instance, widget, val) Boolean radiobox = 0; int ac = 0; Arg al [1]; - + XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++; XtGetValues (widget, al, ac); - + if (radiobox) { CompositeWidget radio = (CompositeWidget)widget; @@ -750,8 +977,8 @@ xm_update_one_value (instance, widget, val) { int set = False; Widget toggle = radio->composite.children [i]; - - XtVaGetValues (toggle, XmNset, &set, 0); + + XtVaGetValues (toggle, XmNset, &set, NULL); if (set) { if (val->value) @@ -793,7 +1020,7 @@ xm_update_one_value (instance, widget, val) /* This function is for activating a button from a program. It's wrong because we pass a NULL argument in the call_data which is not Motif compatible. This is used from the XmNdefaultAction callback of the List widgets to - have a double-click put down a dialog box like the button would do. + have a double-click put down a dialog box like the button would do. I could not find a way to do that with accelerators. */ static void @@ -837,7 +1064,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, Arg al[64]; /* Arg List */ int ac; /* Arg Count */ int i; - + if (pop_up_p) { ac = 0; @@ -862,9 +1089,9 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, n_children = left_buttons + right_buttons + 1; ac = 0; - XtSetArg(al[ac], XmNpacking, n_children == 3? + XtSetArg(al[ac], XmNpacking, n_children == 3? XmPACK_COLUMN: XmPACK_TIGHT); ac++; - XtSetArg(al[ac], XmNorientation, n_children == 3? + XtSetArg(al[ac], XmNorientation, n_children == 3? XmVERTICAL: XmHORIZONTAL); ac++; XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++; XtSetArg(al[ac], XmNmarginWidth, 0); ac++; @@ -881,7 +1108,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; XtSetArg(al[ac], XmNrightOffset, 13); ac++; row = XmCreateRowColumn (form, "row", al, ac); - + n_children = 0; for (i = 0; i < left_buttons; i++) { @@ -913,7 +1140,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++; children [n_children] = XmCreateLabel (row, "separator_button", al, ac); n_children++; - + for (i = 0; i < right_buttons; i++) { char button_name [16]; @@ -925,9 +1152,9 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, if (! button) button = children [n_children]; n_children++; } - + XtManageChildren (children, n_children); - + ac = 0; XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++; XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++; @@ -1023,7 +1250,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, list activate the default button */ XtAddCallback (value, XmNdefaultActionCallback, activate_button, button); } - + ac = 0; XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++; @@ -1038,7 +1265,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; XtSetArg(al[ac], XmNrightOffset, 13); ac++; message = XmCreateLabel (form, "message", al, ac); - + if (list) XtManageChild (value); @@ -1053,7 +1280,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, children [i] = icon; i++; children [i] = icon_separator; i++; XtManageChildren (children, i); - + if (text_input_slot || list) { XtInstallAccelerators (value, button); @@ -1064,7 +1291,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, XtInstallAccelerators (form, button); XtSetKeyboardFocus (result, button); } - + return result; } @@ -1131,13 +1358,13 @@ recenter_widget (widget) Position x; Position y; - XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, 0); + XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, NULL); XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height, - 0); + NULL); x = (((Position)parent_width) - ((Position)child_width)) / 2; y = (((Position)parent_height) - ((Position)child_height)) / 2; - + XtTranslateCoords (parent, x, y, &x, &y); if (x + child_width > screen_width) @@ -1150,7 +1377,7 @@ recenter_widget (widget) if (y < 0) y = 0; - XtVaSetValues (widget, XtNx, x, XtNy, y, 0); + XtVaSetValues (widget, XtNx, x, XtNy, y, NULL); } static Widget @@ -1177,11 +1404,11 @@ recycle_instance (instance) focus = XtNameToWidget (widget, "*button1"); if (focus) XtSetKeyboardFocus (widget, focus); - + /* shrink the separator label back to their original size */ separator = XtNameToWidget (widget, "*separator_button"); if (separator) - XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, 0); + XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, NULL); /* Center the dialog in its parent */ recenter_widget (widget); @@ -1199,7 +1426,7 @@ xm_create_dialog (instance) Widget widget; Boolean pop_up_p = instance->pop_up_p; char* shell_name = 0; - char* icon_name; + char* icon_name = 0; Boolean text_input_slot = False; Boolean radio_box = False; Boolean list = False; @@ -1245,7 +1472,7 @@ xm_create_dialog (instance) shell_name = "Question"; break; } - + total_buttons = name [1] - '0'; if (name [3] == 'T' || name [3] == 't') @@ -1255,9 +1482,9 @@ xm_create_dialog (instance) } else if (name [3]) right_buttons = name [4] - '0'; - + left_buttons = total_buttons - right_buttons; - + widget = make_dialog (name, parent, pop_up_p, shell_name, icon_name, text_input_slot, radio_box, list, left_buttons, right_buttons); @@ -1274,12 +1501,12 @@ static Widget make_menubar (instance) widget_instance* instance; { - Arg al[1]; + Arg al[3]; int ac; ac = 0; - XtSetArg(al[0], XmNmenuAccelerator, 0); - return XmCreateMenuBar (instance->parent, instance->info->name, al, 1); + XtSetArg(al[ac], XmNmenuAccelerator, 0); ++ac; + return XmCreateMenuBar (instance->parent, instance->info->name, al, ac); } static void @@ -1308,6 +1535,7 @@ make_popup_menu (instance) parent->core.window = parent_window; return result; } + static Widget make_main (instance) widget_instance* instance; @@ -1427,7 +1655,7 @@ make_project_display_dialog (widget_instance* instance) #endif /* ENERGIZE */ widget_creation_entry -xm_creation_table [] = +xm_creation_table [] = { {"menubar", make_menubar}, {"popup", make_popup_menu}, @@ -1507,19 +1735,29 @@ xm_popup_menu (widget, event) if (event->type == ButtonPress || event->type == ButtonRelease) { - /* This is so totally ridiculous: there's NO WAY to tell Motif - that *any* button can select a menu item. Only one button - can have that honor. - */ - char *trans = 0; - if (event->xbutton.state & Button5Mask) trans = ""; - else if (event->xbutton.state & Button4Mask) trans = ""; - else if (event->xbutton.state & Button3Mask) trans = ""; - else if (event->xbutton.state & Button2Mask) trans = ""; - else if (event->xbutton.state & Button1Mask) trans = ""; - if (trans) XtVaSetValues (widget, XmNmenuPost, trans, 0); + /* Setting the menuPost resource only required by Motif 1.1 and + LessTif 0.84 and earlier. With later versions of LessTif, + setting menuPost is unnecessary and may cause problems, so + don't do it. */ +#if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84) + { + /* This is so totally ridiculous: there's NO WAY to tell Motif + that *any* button can select a menu item. Only one button + can have that honor. */ + + char *trans = 0; + if (event->xbutton.state & Button5Mask) trans = ""; + else if (event->xbutton.state & Button4Mask) trans = ""; + else if (event->xbutton.state & Button3Mask) trans = ""; + else if (event->xbutton.state & Button2Mask) trans = ""; + else if (event->xbutton.state & Button1Mask) trans = ""; + if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL); + } +#endif + XmMenuPosition (widget, (XButtonPressedEvent *) event); } + XtManageChild (widget); } @@ -1529,8 +1767,8 @@ set_min_dialog_size (w) { short width; short height; - XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, 0); - XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, 0); + XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, NULL); + XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, NULL); } void @@ -1557,14 +1795,12 @@ xm_pop_instance (instance, up) if (up) XtManageChild (widget); else - XtUnmanageChild (widget); + XtUnmanageChild (widget); } } -/* motif callback */ - -enum do_call_type { pre_activate, selection, no_selection, post_activate }; +/* motif callback */ static void do_call (widget, closure, type) @@ -1593,31 +1829,36 @@ do_call (widget, closure, type) user_data = NULL; XtSetArg (al [ac], XmNuserData, &user_data); ac++; XtGetValues (widget, al, ac); + switch (type) { case pre_activate: if (instance->info->pre_activate_cb) instance->info->pre_activate_cb (widget, id, user_data); break; + case selection: if (instance->info->selection_cb) instance->info->selection_cb (widget, id, user_data); break; + case no_selection: if (instance->info->selection_cb) instance->info->selection_cb (widget, id, (XtPointer) -1); break; + case post_activate: if (instance->info->post_activate_cb) instance->info->post_activate_cb (widget, id, user_data); break; + default: abort (); } } /* Like lw_internal_update_other_instances except that it does not do - anything if its shell parent is not managed. This is to protect + anything if its shell parent is not managed. This is to protect lw_internal_update_other_instances to dereference freed memory if the widget was ``destroyed'' by caching it in the all_destroyed_instances list */ @@ -1652,14 +1893,14 @@ xm_nosel_callback (widget, closure, call_data) XtPointer closure; XtPointer call_data; { - /* This callback is only called when a dialog box is dismissed with the wm's - destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed - in that case, not just unmapped, so that it releases its keyboard grabs. - But there are problems with running our callbacks while the widget is in - the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP - instead of XmDESTROY and then destroy it ourself after having run the - callback. - */ + /* This callback is only called when a dialog box is dismissed with + the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog + box to be destroyed in that case, not just unmapped, so that it + releases its keyboard grabs. But there are problems with running + our callbacks while the widget is in the process of being + destroyed, so we set XmNdeleteResponse to XmUNMAP instead of + XmDESTROY and then destroy it ourself after having run the + callback. */ do_call (widget, closure, no_selection); XtDestroyWidget (widget); } @@ -1670,9 +1911,24 @@ xm_pull_down_callback (widget, closure, call_data) XtPointer closure; XtPointer call_data; { - do_call (widget, closure, pre_activate); + Widget parent = XtParent (widget); + + if (XmIsRowColumn (parent)) + { + unsigned char type = 0xff; + XtVaGetValues (parent, XmNrowColumnType, &type, NULL); + if (type == XmMENU_BAR) + do_call (widget, closure, pre_activate); + } } + +/* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell, + CLOSURE is a pointer to the widget_instance of the shell, + + Note that this callback is called for each cascade button in a + menu, whether or not its submenu is visible. */ + static void xm_pop_down_callback (widget, closure, call_data) Widget widget; @@ -1681,8 +1937,8 @@ xm_pop_down_callback (widget, closure, call_data) { widget_instance *instance = (widget_instance *) closure; - if ((!instance->pop_up_p && (XtParent (widget) == instance->widget)) - || (XtParent (widget) == instance->parent)) + if ((!instance->pop_up_p && XtParent (widget) == instance->widget) + || XtParent (widget) == instance->parent) do_call (widget, closure, post_activate); } @@ -1718,20 +1974,5 @@ xm_manage_resizing (w, flag) Widget w; Boolean flag; { - if (flag) - { - /* Enable the edit widget for resizing. */ - Arg al[1]; - - XtSetArg (al[0], XtNallowShellResize, 0); - XtSetValues (w, al, 1); - } - else - { - /* Disable the edit widget from resizing. */ - Arg al[1]; - - XtSetArg (al[0], XtNallowShellResize, 0); - XtSetValues (w, al, 1); - } + XtVaSetValues (w, XtNallowShellResize, flag, NULL); }