}
#endif
-\f
-#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
/* 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)
{
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
the menus in any form, since it would be a no-op. */
free_menubar_widget_value_tree (first_wv);
discard_menu_items ();
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
return;
}
f->menu_bar_items_used = menu_items_used;
/* This undoes save_menu_items. */
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
/* Now GC cannot happen during the lifetime of the widget_value,
so it's safe to store data from a Lisp_String. */
#endif /* USE_X_TOOLKIT || USE_GTK */
\f
-/* 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.
GtkWidget *menu;
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
bool use_pos_func = ! for_click;
#ifdef HAVE_GTK3
popup_widget_loop (1, menu);
}
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
/* Must reset this manually because the button release event is not passed
to Emacs event loop. */
{
int fact = 4 * sizeof (LWLIB_ID);
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
record_unwind_protect (pop_down_menu,
Fcons (make_number (menu_id >> (fact)),
make_number (menu_id & ~(-1 << (fact)))));
/* Process events that apply to the menu. */
popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
}
}
}
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;
int first_pane;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
eassert (FRAME_X_P (f));
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
+ dynwind_end ();
return Qnil;
}
/* 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 = make_widget_value (pane_string, NULL, true, Qnil);
if (save_wv)
save_wv->next = wv;
else
first_wv->contents = wv;
- if (keymaps && !NILP (prefix))
+ if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
wv->name++;
wv->button_type = BUTTON_TYPE_NONE;
save_wv = wv;
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);
+ dynwind_end ();
/* Find the selected item, and its pane, to return
the proper value. */
= 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;
}
}
}
- else if (!for_click)
+ else if (!(menuflags & MENU_FOR_CLICK))
{
unblock_input ();
/* Make "Cancel" equivalent to C-g. */
if (menu)
{
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
record_unwind_protect_ptr (pop_down_menu, menu);
/* Display the menu. */
/* Process events that apply to the menu. */
popup_widget_loop (1, menu);
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
}
}
/* Process events that apply to the dialog box.
Also handle timers. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int fact = 4 * sizeof (LWLIB_ID);
/* xdialog_show_unwind is responsible for popping the dialog box down. */
popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
}
/* 1 means we've seen the boundary between left-hand elts and right-hand. */
int boundary_seen = 0;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
eassert (FRAME_X_P (f));
if (menu_items_n_panes > 1)
{
*error_name = "Multiple panes in dialog box";
+ dynwind_end ();
return Qnil;
}
{
free_menubar_widget_value_tree (first_wv);
*error_name = "Submenu in dialog items";
+ dynwind_end ();
return Qnil;
}
if (EQ (item_name, Qquote))
{
free_menubar_widget_value_tree (first_wv);
*error_name = "Too many dialog items";
+ dynwind_end ();
return Qnil;
}
/* Actually create and show the dialog. */
create_and_show_dialog (f, first_wv);
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
/* Find the selected item, and its pane, to return
the proper value. */
Lisp_Object title;
const char *error_name;
Lisp_Object selection;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
check_window_system (f);
selection = x_dialog_show (f, title, header, &error_name);
unblock_input ();
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
discard_menu_items ();
if (error_name) error ("%s", error_name);
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];
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 maxwidth;
int dummy_int;
unsigned int dummy_uint;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ dynwind_begin ();
eassert (FRAME_X_P (f) || FRAME_MSDOS_P (f));
*error_name = 0;
- if (menu_items_n_panes == 0)
+ if (menu_items_n_panes == 0) {
+ dynwind_end ();
return Qnil;
+ }
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
+ dynwind_end ();
return Qnil;
}
{
*error_name = "Can't create menu";
unblock_input ();
+ dynwind_end ();
return Qnil;
}
- /* Don't GC while we prepare and show the menu,
- because we give the oldxmenu library pointers to the
- contents of strings. */
- inhibit_garbage_collection ();
-
#ifdef HAVE_X_WINDOWS
/* Adjust coordinates to relative to the outer (window manager) window. */
x += FRAME_OUTER_TO_INNER_DIFF_X (f);
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);
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't create pane";
unblock_input ();
+ dynwind_end ();
return Qnil;
}
i += MENU_ITEMS_PANE_LENGTH;
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't add selection to menu";
unblock_input ();
+ dynwind_end ();
return Qnil;
}
i += MENU_ITEMS_ITEM_LENGTH;
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
{
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
- if (keymaps)
+ if (menuflags & MENU_KEYMAPS)
{
entry = list1 (entry);
if (!NILP (pane_prefix))
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);
}
unblock_input ();
- unbind_to (specpdl_count, Qnil);
+ dynwind_end ();
return entry;
}
void
syms_of_xmenu (void)
{
+#include "xmenu.x"
+
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
#ifdef USE_X_TOOLKIT
next_menubar_widget_id = 1;
#endif
- defsubr (&Smenu_or_popup_active_p);
-
#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
- defsubr (&Sx_menu_bar_open_internal);
Ffset (intern_c_string ("accelerate-menu"),
intern_c_string (Sx_menu_bar_open_internal.symbol_name));
#endif