/* The lwlib interface to Motif widgets.
+ Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 1992 Lucid, Inc.
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.
You should have received a copy of the GNU General Public License
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. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
\f/* Structures to keep destroyed instances */
-typedef struct _destroyed_instance
+typedef struct _destroyed_instance
{
char* name;
char* type;
instance->next = NULL;
return instance;
}
-
+
static void
free_destroyed_instance (instance)
destroyed_instance* instance;
lw_motif_widget_p (widget)
Widget widget;
{
- return
+ return
XtClass (widget) == xmDialogShellWidgetClass
|| XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
}
{
XtResource resource;
XmString result = 0;
-
+
resource.resource_name = name;
resource.resource_class = XmCXmString;
resource.resource_type = XmRXmString;
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++)
{
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]);
}
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
else
{
built_string =
- XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET);
+ XmStringCreateLocalized (val->value);
XtSetArg (al [ac], XmNlabelString, built_string); ac++;
}
-
+
XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
}
-
+
if (val->key)
{
- key_string = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET);
+ key_string = XmStringCreateLocalized (val->key);
XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
}
for (cur = val->contents, i = 0; cur; cur = cur->next)
if (cur->value)
{
- XmString xmstr = XmStringCreate (cur->value, XmSTRING_DEFAULT_CHARSET);
+ XmString xmstr = XmStringCreateLocalized (cur->value);
i += 1;
XmListAddItem (widget, xmstr, 0);
if (cur->selected)
Widget* old_children;
unsigned int old_num_children;
+ /* Disable drag and drop for labels in menu bar. */
+ static char overrideTrans[] = "<Btn2Down>: Noop()";
+ XtTranslations override = XtParseTranslationTable (overrideTrans);
+
old_children = XtCompositeChildren (widget, &old_num_children);
/* Allocate the children array */
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
&& !lw_separator_p (cur->name, &separator, 1))
{
XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
}
-
+
xm_update_label (instance, button, cur);
-
+
/* Add a callback that is called when the button is
selected. Toggle buttons don't support
XmNactivateCallback, we use XmNvalueChangedCallback in
XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
(XtPointer)instance);
+ XtOverrideTranslations (button, override);
+
}
children[child_index] = button;
menu = NULL;
XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
XtGetValues (widget, al, ac);
-
+
contents = val->contents;
if (!menu)
else
{
Widget button;
-
- /* The current menuitem is a XmPushButtonGadget, it
+
+ /* 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);
#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)
{
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)
{
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);
Boolean deep_p;
{
WidgetClass class;
-
+
/* Mark as not edited */
val->edited = False;
/* Common to all widget types */
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 ||
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
val->call_data = old_wv->call_data;
break;
}
-
+
if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
{
XtVaGetValues (widget, XmNset, &val->selected, NULL);
}
else if (class == xmTextWidgetClass)
{
- if (val->value)
- free (val->value);
+ free (val->value);
val->value = XmTextGetString (widget);
val->edited = True;
}
else if (class == xmTextFieldWidgetClass)
{
- if (val->value)
- free (val->value);
+ free (val->value);
val->value = XmTextFieldGetString (widget);
val->edited = True;
}
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;
{
int set = False;
Widget toggle = radio->composite.children [i];
-
+
XtVaGetValues (toggle, XmNset, &set, NULL);
if (set)
{
- if (val->value)
- free (val->value);
+ free (val->value);
val->value = safe_strdup (XtName (toggle));
}
}
/* 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
/* creation functions */
+/* Called for key press in dialogs. Used to pop down dialog on ESC. */
+static void
+dialog_key_cb (widget, closure, event, continue_to_dispatch)
+ Widget widget;
+ XtPointer closure;
+ XEvent *event;
+ Boolean *continue_to_dispatch;
+{
+ KeySym sym = 0;
+ Modifiers modif_ret;
+
+ XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0,
+ &modif_ret, &sym);
+
+ if (sym == osfXK_Cancel)
+ {
+ Widget w = *((Widget *) closure);
+
+ while (w && ! XtIsShell (w))
+ w = XtParent (w);
+
+ if (XtIsShell (w)) XtPopdown (w);
+ }
+
+ *continue_to_dispatch = TRUE;
+}
+
/* dialogs */
static Widget
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;
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++;
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++)
{
XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
children [n_children] = XmCreatePushButton (row, button_name, al, ac);
+ XtAddEventHandler (children [n_children],
+ KeyPressMask, False, dialog_key_cb, result);
if (i == 0)
{
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];
XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
children [n_children] = XmCreatePushButton (row, button_name, al, ac);
+ XtAddEventHandler (children [n_children],
+ KeyPressMask, False, dialog_key_cb, result);
+
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++;
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++;
XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNrightOffset, 13); ac++;
message = XmCreateLabel (form, "message", al, ac);
-
+
if (list)
XtManageChild (value);
children [i] = icon; i++;
children [i] = icon_separator; i++;
XtManageChildren (children, i);
-
+
if (text_input_slot || list)
{
XtInstallAccelerators (value, button);
XtInstallAccelerators (form, button);
XtSetKeyboardFocus (result, button);
}
-
+
return result;
}
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)
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)
shell_name = "Question";
break;
}
-
+
total_buttons = name [1] - '0';
if (name [3] == 'T' || name [3] == 't')
}
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);
XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
(XtPointer) instance);
+
return widget;
}
#endif /* ENERGIZE */
widget_creation_entry
-xm_creation_table [] =
+xm_creation_table [] =
{
{"menubar", make_menubar},
{"popup", make_popup_menu},
/* 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 = "<Btn5Down>";
else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL);
}
#endif
-
+
XmMenuPosition (widget, (XButtonPressedEvent *) event);
}
-
+
XtManageChild (widget);
}
if (up)
XtManageChild (widget);
else
- XtUnmanageChild (widget);
+ XtUnmanageChild (widget);
}
}
\f
-/* motif callback */
+/* motif callback */
static void
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 */
/* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
- CLOSURE is a pointer to the widget_instance of the shell,
+ 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. */
{
XtVaSetValues (w, XtNallowShellResize, flag, NULL);
}
+
+/* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
+ (do not change this comment) */