summaryrefslogtreecommitdiff
path: root/src/xmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmenu.c')
-rw-r--r--src/xmenu.c309
1 files changed, 97 insertions, 212 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index 9b1ac540c21..0f69ee28e84 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -110,11 +110,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static Lisp_Object Qdebug_on_next_call;
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-static Lisp_Object xdialog_show (struct frame *, bool, Lisp_Object, Lisp_Object,
- const char **);
-#endif
-
/* Flag which when set indicates a dialog or menu has been posted by
Xt on behalf of one of the widget sets. */
static int popup_activated_flag;
@@ -122,7 +117,7 @@ static int popup_activated_flag;
#ifdef USE_X_TOOLKIT
-static int next_menubar_widget_id;
+static LWLIB_ID next_menubar_widget_id;
/* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
@@ -144,53 +139,6 @@ menubar_id_to_frame (LWLIB_ID id)
}
#endif
-
-#ifdef HAVE_X_WINDOWS
-/* Return the mouse position in *X and *Y. The coordinates are window
- relative for the edit window in frame F.
- This is for Fx_popup_menu. The mouse_position_hook can not
- be used for X, as it returns window relative coordinates
- for the window where the mouse is in. This could be the menu bar,
- the scroll bar or the edit window. Fx_popup_menu needs to be
- sure it is the edit window. */
-void
-mouse_position_for_popup (struct frame *f, int *x, int *y)
-{
- Window root, dummy_window;
- int dummy;
-
- eassert (FRAME_X_P (f));
-
- block_input ();
-
- XQueryPointer (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
-
- /* The root window which contains the pointer. */
- &root,
-
- /* Window pointer is on, not used */
- &dummy_window,
-
- /* The position on that root window. */
- x, y,
-
- /* x/y in dummy_window coordinates, not used. */
- &dummy, &dummy,
-
- /* Modifier keys and pointer buttons, about which
- we don't care. */
- (unsigned int *) &dummy);
-
- unblock_input ();
-
- /* xmenu_show expects window coordinates, not root window
- coordinates. Translate. */
- *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-}
-
-#endif /* HAVE_X_WINDOWS */
#ifndef MSDOS
@@ -213,9 +161,6 @@ x_menu_set_in_use (int in_use)
/* Wait for an X event to arrive or for a timer to expire. */
-#ifndef USE_MOTIF
-static
-#endif
void
x_menu_wait_for_event (void *data)
{
@@ -682,7 +627,6 @@ update_frame_menubar (struct frame *f)
xg_update_frame_menubar (f);
#else
struct x_output *x;
- int columns, rows;
eassert (FRAME_X_P (f));
@@ -692,10 +636,6 @@ update_frame_menubar (struct frame *f)
return;
block_input ();
- /* Save the size of the frame because the pane widget doesn't accept
- to resize itself. So force it. */
- columns = FRAME_COLS (f);
- rows = FRAME_LINES (f);
/* Do the voodoo which means "I'm changing lots of things, don't try
to refigure sizes until I'm done." */
@@ -716,10 +656,16 @@ update_frame_menubar (struct frame *f)
XtManageChild (x->edit_widget);
lw_refigure_widget (x->column_widget, True);
- /* Force the pane widget to resize itself with the right values. */
- EmacsFrameSetCharSize (x->edit_widget, columns, rows);
+ /* Force the pane widget to resize itself. */
+#ifdef USE_LUCID
+ /* For reasons I don't know Lucid wants to add one pixel to the frame
+ height when adding the menu bar. Compensate that here. */
+ adjust_frame_size (f, -1, FRAME_TEXT_HEIGHT (f) - 1, 2, 0, Qmenu_bar_lines);
+#else
+ adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
+#endif /* USE_LUCID */
unblock_input ();
-#endif
+#endif /* USE_GTK */
}
#ifdef USE_LUCID
@@ -760,7 +706,7 @@ apply_systemfont_to_menu (struct frame *f, Widget w)
void
set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
{
- xt_or_gtk_widget menubar_widget;
+ xt_or_gtk_widget menubar_widget, old_widget;
#ifdef USE_X_TOOLKIT
LWLIB_ID id;
#endif
@@ -773,7 +719,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
eassert (FRAME_X_P (f));
- menubar_widget = f->output_data.x->menubar_widget;
+ menubar_widget = old_widget = f->output_data.x->menubar_widget;
XSETFRAME (Vmenu_updating_frame, f);
@@ -793,12 +739,6 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
f->output_data.x->saved_menu_event->type = 0;
}
-#ifdef USE_GTK
- /* If we have detached menus, we must update deep so detached menus
- also gets updated. */
- deep_p = deep_p || xg_have_tear_offs (f);
-#endif
-
if (deep_p)
{
/* Make a widget-value tree representing the entire menu trees. */
@@ -887,12 +827,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
/* Convert menu_items into widget_value trees
to display the menu. This cannot evaluate Lisp code. */
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("menubar", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
first_wv = wv;
for (i = 0; submenu_start[i] >= 0; i++)
@@ -957,12 +893,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
/* Make a widget-value tree containing
just the top level menu bar strings. */
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("menubar", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
first_wv = wv;
items = FRAME_MENU_BAR_ITEMS (f);
@@ -974,12 +906,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
if (NILP (string))
break;
- wv = xmalloc_widget_value ();
- wv->name = SSDATA (string);
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
/* This prevents lwlib from assuming this
menu item is really supposed to be empty. */
/* The intptr_t cast avoids a warning.
@@ -1090,7 +1018,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
#endif /* USE_LUCID */
#endif /* 1 */
- f->output_data.x->menubar_height = menubar_size;
+ FRAME_MENUBAR_HEIGHT (f) = menubar_size;
}
#endif /* not USE_GTK */
@@ -1128,12 +1056,18 @@ void
free_frame_menubar (struct frame *f)
{
Widget menubar_widget;
+#ifdef USE_MOTIF
+ /* Motif automatically shrinks the frame in lw_destroy_all_widgets.
+ If we want to preserve the old height, calculate it now so we can
+ restore it below. */
+ int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
+#endif
eassert (FRAME_X_P (f));
menubar_widget = f->output_data.x->menubar_widget;
- f->output_data.x->menubar_height = 0;
+ FRAME_MENUBAR_HEIGHT (f) = 0;
if (menubar_widget)
{
@@ -1165,9 +1099,20 @@ free_frame_menubar (struct frame *f)
XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
if (x1 == 0 && y1 == 0)
XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
+ if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+ adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
+ else
+#endif /* USE_MOTIF */
+ adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
+ }
+ else
+ {
+#ifdef USE_MOTIF
+ if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+ adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
#endif
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
}
+
unblock_input ();
}
}
@@ -1175,16 +1120,17 @@ free_frame_menubar (struct frame *f)
#endif /* USE_X_TOOLKIT || USE_GTK */
-/* xmenu_show actually displays a menu using the panes and items in menu_items
+/* x_menu_show actually displays a menu using the panes and items in menu_items
and returns the value selected from it.
- There are two versions of xmenu_show, one for Xt and one for Xlib.
+ There are two versions of x_menu_show, one for Xt and one for Xlib.
Both assume input is blocked by the caller. */
/* F is the frame the menu is for.
X and Y are the frame-relative specified position,
relative to the inside upper left corner of the frame F.
- FOR_CLICK is true if this menu was invoked for a mouse click.
- KEYMAPS is true if this menu was specified with keymaps;
+ Bitfield MENUFLAGS bits are:
+ MENU_FOR_CLICK is set if this menu was invoked for a mouse click.
+ MENU_KEYMAPS is set if this menu was specified with keymaps;
in that case, we return a list containing the chosen item's value
and perhaps also the pane's prefix.
TITLE is the specified menu title.
@@ -1339,8 +1285,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
/* We need a unique id for each widget handled by the Lucid Widget
library.
- For the main windows, and popup menus, we use this counter,
- which we increment each time after use. This starts from 1<<16.
+ For the main windows, and popup menus, we use this counter, which we
+ increment each time after use. This starts from WIDGET_ID_TICK_START.
For menu bars, we use numbers starting at 0, counted in
next_menubar_widget_id. */
@@ -1352,17 +1298,13 @@ popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
menu_item_selection = client_data;
}
-/* ARG is the LWLIB ID of the dialog box, represented
- as a Lisp object as (HIGHPART . LOWPART). */
+/* ID is the LWLIB ID of the dialog box. */
static void
-pop_down_menu (Lisp_Object arg)
+pop_down_menu (int id)
{
- LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
- | XINT (XCDR (arg)));
-
block_input ();
- lw_destroy_all_widgets (id);
+ lw_destroy_all_widgets ((LWLIB_ID) id);
unblock_input ();
popup_activated_flag = 0;
}
@@ -1428,11 +1370,9 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
x_activate_timeout_atimer ();
{
- int fact = 4 * sizeof (LWLIB_ID);
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
- record_unwind_protect (pop_down_menu,
- Fcons (make_number (menu_id >> (fact)),
- make_number (menu_id & ~(-1 << (fact)))));
+
+ record_unwind_protect_int (pop_down_menu, (int) menu_id);
/* Process events that apply to the menu. */
popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
@@ -1450,8 +1390,8 @@ cleanup_widget_value_tree (void *arg)
}
Lisp_Object
-xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
- Lisp_Object title, const char **error_name)
+x_menu_show (struct frame *f, int x, int y, int menuflags,
+ Lisp_Object title, const char **error_name)
{
int i;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
@@ -1479,12 +1419,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
/* Create a tree of widget_value objects
representing the panes and their items. */
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("menu", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help =Qnil;
first_wv = wv;
first_pane = 1;
@@ -1540,20 +1476,16 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
/* If the pane has a meaningful name,
make the pane a top-level menu item
with its items as a submenu beneath it. */
- if (!keymaps && strcmp (pane_string, ""))
+ if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, ""))
{
- wv = xmalloc_widget_value ();
+ wv = make_widget_value (pane_string, NULL, true, Qnil);
if (save_wv)
save_wv->next = wv;
else
first_wv->contents = wv;
- wv->name = (char *) pane_string;
- if (keymaps && !NILP (prefix))
+ if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
wv->name++;
- wv->value = 0;
- wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
save_wv = wv;
prev_wv = 0;
}
@@ -1591,20 +1523,18 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
}
#endif /* not HAVE_MULTILINGUAL_MENU */
- wv = xmalloc_widget_value ();
+ wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable),
+ STRINGP (help) ? help : Qnil);
if (prev_wv)
prev_wv->next = wv;
else
save_wv->contents = wv;
- wv->name = SSDATA (item_name);
if (!NILP (descrip))
wv->key = SSDATA (descrip);
- wv->value = 0;
/* If this item has a null value,
make the call_data null so that it won't display a box
when the mouse is on it. */
wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0;
- wv->enabled = !NILP (enable);
if (NILP (type))
wv->button_type = BUTTON_TYPE_NONE;
@@ -1617,11 +1547,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
wv->selected = !NILP (selected);
- if (! STRINGP (help))
- help = Qnil;
-
- wv->help = help;
-
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
@@ -1631,27 +1556,20 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
/* Deal with the title, if it is non-nil. */
if (!NILP (title))
{
- widget_value *wv_title = xmalloc_widget_value ();
- widget_value *wv_sep1 = xmalloc_widget_value ();
- widget_value *wv_sep2 = xmalloc_widget_value ();
+ widget_value *wv_title;
+ widget_value *wv_sep1 = make_widget_value ("--", NULL, false, Qnil);
+ widget_value *wv_sep2 = make_widget_value ("--", NULL, false, Qnil);
- wv_sep2->name = "--";
wv_sep2->next = first_wv->contents;
- wv_sep2->help = Qnil;
-
- wv_sep1->name = "--";
wv_sep1->next = wv_sep2;
- wv_sep1->help = Qnil;
#ifndef HAVE_MULTILINGUAL_MENU
if (STRING_MULTIBYTE (title))
title = ENCODE_MENU_STRING (title);
#endif
- wv_title->name = SSDATA (title);
- wv_title->enabled = true;
+ wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil);
wv_title->button_type = BUTTON_TYPE_NONE;
- wv_title->help = Qnil;
wv_title->next = wv_sep1;
first_wv->contents = wv_title;
}
@@ -1664,7 +1582,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv);
/* Actually create and show the menu until popped down. */
- create_and_show_popup_menu (f, first_wv, x, y, for_click);
+ create_and_show_popup_menu (f, first_wv, x, y,
+ menuflags & MENU_FOR_CLICK);
unbind_to (specpdl_count, Qnil);
@@ -1705,7 +1624,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == aref_addr (menu_items, i))
{
- if (keymaps)
+ if (menuflags & MENU_KEYMAPS)
{
int j;
@@ -1723,7 +1642,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
}
}
}
- else if (!for_click)
+ else if (!(menuflags & MENU_FOR_CLICK))
{
unblock_input ();
/* Make "Cancel" equivalent to C-g. */
@@ -1819,12 +1738,10 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
Also handle timers. */
{
ptrdiff_t count = SPECPDL_INDEX ();
- int fact = 4 * sizeof (LWLIB_ID);
/* xdialog_show_unwind is responsible for popping the dialog box down. */
- record_unwind_protect (pop_down_menu,
- Fcons (make_number (dialog_id >> (fact)),
- make_number (dialog_id & ~(-1 << (fact)))));
+
+ record_unwind_protect_int (pop_down_menu, (int) dialog_id);
popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
@@ -1839,11 +1756,8 @@ static const char * button_names [] = {
"button6", "button7", "button8", "button9", "button10" };
static Lisp_Object
-xdialog_show (struct frame *f,
- bool keymaps,
- Lisp_Object title,
- Lisp_Object header,
- const char **error_name)
+x_dialog_show (struct frame *f, Lisp_Object title,
+ Lisp_Object header, const char **error_name)
{
int i, nb_buttons=0;
char dialog_name[6];
@@ -1870,19 +1784,12 @@ xdialog_show (struct frame *f,
/* Create a tree of widget_value objects
representing the text label and buttons. */
{
- Lisp_Object pane_name, prefix;
+ Lisp_Object pane_name;
const char *pane_string;
pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
- prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
- prev_wv = xmalloc_widget_value ();
- prev_wv->value = (char *) pane_string;
- if (keymaps && !NILP (prefix))
- prev_wv->name++;
- prev_wv->enabled = 1;
- prev_wv->name = "message";
- prev_wv->help = Qnil;
+ prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil);
first_wv = prev_wv;
/* Loop over all panes and items, filling in the tree. */
@@ -1918,15 +1825,13 @@ xdialog_show (struct frame *f,
return Qnil;
}
- wv = xmalloc_widget_value ();
+ wv = make_widget_value (button_names[nb_buttons],
+ SSDATA (item_name),
+ !NILP (enable), Qnil);
prev_wv->next = wv;
- wv->name = (char *) button_names[nb_buttons];
if (!NILP (descrip))
wv->key = SSDATA (descrip);
- wv->value = SSDATA (item_name);
wv->call_data = aref_addr (menu_items, i);
- wv->enabled = !NILP (enable);
- wv->help = Qnil;
prev_wv = wv;
if (! boundary_seen)
@@ -1941,9 +1846,7 @@ xdialog_show (struct frame *f,
if (! boundary_seen)
left_count = nb_buttons - nb_buttons / 2;
- wv = xmalloc_widget_value ();
- wv->name = dialog_name;
- wv->help = Qnil;
+ wv = make_widget_value (dialog_name, NULL, false, Qnil);
/* Frame title: 'Q' = Question, 'I' = Information.
Can also have 'E' = Error if, one day, we want
@@ -1982,20 +1885,13 @@ xdialog_show (struct frame *f,
the proper value. */
if (menu_item_selection != 0)
{
- Lisp_Object prefix;
-
- prefix = Qnil;
i = 0;
while (i < menu_items_used)
{
Lisp_Object entry;
if (EQ (AREF (menu_items, i), Qt))
- {
- prefix
- = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
- i += MENU_ITEMS_PANE_LENGTH;
- }
+ i += MENU_ITEMS_PANE_LENGTH;
else if (EQ (AREF (menu_items, i), Qquote))
{
/* This is the boundary between left-side elts and
@@ -2007,15 +1903,7 @@ xdialog_show (struct frame *f,
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == aref_addr (menu_items, i))
- {
- if (keymaps != 0)
- {
- entry = list1 (entry);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- }
- return entry;
- }
+ return entry;
i += MENU_ITEMS_ITEM_LENGTH;
}
}
@@ -2052,7 +1940,7 @@ xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
/* Display them in a dialog box. */
block_input ();
- selection = xdialog_show (f, 0, title, header, &error_name);
+ selection = x_dialog_show (f, title, header, &error_name);
unblock_input ();
unbind_to (specpdl_count, Qnil);
@@ -2090,7 +1978,7 @@ menu_help_callback (char const *help_string, int pane, int item)
if (EQ (first_item[0], Qt))
pane_name = first_item[MENU_ITEMS_PANE_NAME];
else if (EQ (first_item[0], Qquote))
- /* This shouldn't happen, see xmenu_show. */
+ /* This shouldn't happen, see x_menu_show. */
pane_name = empty_unibyte_string;
else
pane_name = first_item[MENU_ITEMS_ITEM_NAME];
@@ -2132,13 +2020,14 @@ pop_down_menu (Lisp_Object arg)
Lisp_Object
-xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
- Lisp_Object title, const char **error_name)
+x_menu_show (struct frame *f, int x, int y, int menuflags,
+ Lisp_Object title, const char **error_name)
{
Window root;
XMenu *menu;
int pane, selidx, lpane, status;
- Lisp_Object entry, pane_prefix;
+ Lisp_Object entry = Qnil;
+ Lisp_Object pane_prefix;
char *datap;
int ulx, uly, width, height;
int dispwidth, dispheight;
@@ -2160,6 +2049,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
return Qnil;
}
+ USE_SAFE_ALLOCA;
block_input ();
/* Figure out which root window F is on. */
@@ -2172,8 +2062,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
if (menu == NULL)
{
*error_name = "Can't create menu";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
/* Don't GC while we prepare and show the menu,
@@ -2208,7 +2097,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
- if (keymaps && !NILP (prefix))
+ if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
pane_string++;
lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE);
@@ -2216,8 +2105,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't create pane";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
i += MENU_ITEMS_PANE_LENGTH;
@@ -2261,9 +2149,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
if (!NILP (descrip))
{
- /* if alloca is fast, use that to make the space,
- to reduce gc needs. */
- item_data = alloca (maxwidth + SBYTES (descrip) + 1);
+ item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
for (j = SCHARS (item_name); j < maxwidth; j++)
item_data[j] = ' ';
@@ -2281,8 +2167,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't add selection to menu";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
lines++;
@@ -2331,7 +2216,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
if (ulx < 0) x -= ulx;
if (uly < 0) y -= uly;
- if (! for_click)
+ if (!(menuflags & MENU_FOR_CLICK))
{
/* If position was not given by a mouse click, adjust so upper left
corner of the menu as a whole ends up at given coordinates. This
@@ -2356,7 +2241,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
x, y, ButtonReleaseMask, &datap,
menu_help_callback);
- entry = pane_prefix = Qnil;
+ pane_prefix = Qnil;
switch (status)
{
@@ -2385,7 +2270,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
{
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
- if (keymaps)
+ if (menuflags & MENU_KEYMAPS)
{
entry = list1 (entry);
if (!NILP (pane_prefix))
@@ -2407,7 +2292,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
case XM_NO_SELECT:
/* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
the menu was invoked with a mouse event as POSITION). */
- if (! for_click)
+ if (!(menuflags & MENU_FOR_CLICK))
{
unblock_input ();
Fsignal (Qquit, Qnil);
@@ -2415,10 +2300,10 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
break;
}
+ return_entry:
unblock_input ();
- unbind_to (specpdl_count, Qnil);
-
- return entry;
+ SAFE_FREE ();
+ return unbind_to (specpdl_count, entry);
}
#endif /* not USE_X_TOOLKIT */
@@ -2446,13 +2331,13 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
void
syms_of_xmenu (void)
{
- DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
-
#ifdef USE_X_TOOLKIT
- widget_id_tick = (1<<16);
+ enum { WIDGET_ID_TICK_START = 1 << 16 };
+ widget_id_tick = WIDGET_ID_TICK_START;
next_menubar_widget_id = 1;
#endif
+ DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
defsubr (&Smenu_or_popup_active_p);
#if defined (USE_GTK) || defined (USE_X_TOOLKIT)