/* Platform-independent code for terminal communications.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2013 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2014 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
static bool
have_boxes (void)
{
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) || defined(HAVE_NS)
if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)))
return 1;
#endif
item_string = concat2 (prefix, item_string);
}
- if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
+ if ((FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
+ || FRAME_MSDOS_P (XFRAME (Vmenu_updating_frame)))
&& !NILP (map))
/* Indicate visually that this is a submenu. */
item_string = concat2 (item_string, build_string (" >"));
}
#endif /* HAVE_NS */
-static int
-item_width (const char *str)
+ptrdiff_t
+menu_item_width (const unsigned char *str)
{
- int len;
- const char *p;
+ ptrdiff_t len;
+ const unsigned char *p;
for (len = 0, p = str; *p; )
{
coordinates are not within the FRAME's menu bar. The symbol can
be used to look up the menu like this:
- (lookup-key global-map [menu-bar SYMBOL])
+ (lookup-key MAP [menu-bar SYMBOL])
+
+where MAP is either the current global map or the current local map,
+since menu-bar items come from both.
This function can return non-nil only on a text-terminal frame
or on an X frame that doesn't use any GUI toolkit. Otherwise,
if (XINT (pos) <= col
/* We use <= so the blank between 2 items on a TTY is
considered part of the previous item. */
- && col <= XINT (pos) + item_width (SSDATA (str)))
+ && col <= XINT (pos) + menu_item_width (SDATA (str)))
{
item = AREF (items, i);
return item;
no quit occurs and `x-popup-menu' returns nil. */)
(Lisp_Object position, Lisp_Object menu)
{
- Lisp_Object keymap, tem;
+ Lisp_Object keymap, tem, tem2;
int xpos = 0, ypos = 0;
Lisp_Object title;
const char *error_name = NULL;
Lisp_Object x, y, window;
bool keymaps = 0;
bool for_click = 0;
+ bool kbd_menu_navigation = 0;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
struct gcpro gcpro1;
keybinding equivalents, but we don't do that any more anyway. */
return Qnil;
-#ifdef HAVE_MENUS
{
bool get_current_pos_p = 0;
for_click = 1;
tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
window = Fcar (tem); /* POSN_WINDOW (tem) */
+ tem2 = Fcar (Fcdr (tem)); /* POSN_POSN (tem) */
+ /* The kbd_menu_navigation flag is set when the menu was
+ invoked by F10, which probably means they have no
+ mouse. In that case, we let them switch between
+ top-level menu-bar menus by using C-f/C-b and
+ horizontal arrow keys, since they cannot click the
+ mouse to open a different submenu. This flag is only
+ supported by tty_menu_show. We set it when POSITION
+ and last_nonmenu_event are different, which means we
+ constructed POSITION by hand (in popup-menu, see
+ menu-bar.el) to look like a mouse click on the menu bar
+ event. */
+ if (!EQ (POSN_POSN (last_nonmenu_event),
+ POSN_POSN (position))
+ && CONSP (tem2) && EQ (Fcar (tem2), Qmenu_bar))
+ kbd_menu_navigation = 1;
tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
x = Fcar (tem);
y = Fcdr (tem);
XSETFRAME (Vmenu_updating_frame, f);
}
-#endif /* HAVE_MENUS */
/* Now parse the lisp menus. */
record_unwind_protect_void (unuse_menu_items);
unbind_to (specpdl_count, Qnil);
-#ifdef HAVE_MENUS
#ifdef HAVE_WINDOW_SYSTEM
/* Hide a previous tip, if any. */
if (!FRAME_TERMCAP_P (f))
else
#endif
#if (defined (HAVE_X_WINDOWS) || defined (MSDOS))
- /* Assume last_event_timestamp is the timestamp of the button event.
- Is this assumption ever violated? We can't use the timestamp
- stored within POSITION because there the top bits from the actual
- timestamp may be truncated away (Bug#4930). */
if (FRAME_X_P (f) || FRAME_MSDOS_P (f))
selection = xmenu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name,
- last_event_timestamp);
+ keymaps, title, &error_name);
else
#endif
+#ifndef MSDOS
if (FRAME_TERMCAP_P (f))
- selection = tty_menu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
+ {
+ ptrdiff_t count1 = SPECPDL_INDEX ();
+
+ /* Avoid crashes if, e.g., another client will connect while we
+ are in a menu. */
+ temporarily_switch_to_single_kboard (f);
+ selection = tty_menu_show (f, xpos, ypos, for_click, keymaps, title,
+ kbd_menu_navigation, &error_name);
+ unbind_to (count1, Qnil);
+ }
+#endif
#ifdef HAVE_NS
unbind_to (specpdl_count, Qnil);
FRAME_DISPLAY_INFO (f)->grabbed = 0;
#endif
-#endif /* HAVE_MENUS */
-
UNGCPRO;
if (error_name) error ("%s", error_name);
return selection;
}
-#ifdef HAVE_MENUS
-
DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
doc: /* Pop up a dialog box and return user's selection.
POSITION specifies which frame to use.
Do this before creating the widget value that points to Lisp
string contents, because Fredisplay may GC and relocate them. */
Fredisplay (Qt);
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+
+#if defined USE_X_TOOLKIT || defined USE_GTK
if (FRAME_WINDOW_P (f))
return xw_popup_dialog (f, header, contents);
- else
#endif
-#if defined (HAVE_NTGUI) && defined (HAVE_DIALOGS)
+#ifdef HAVE_NTGUI
if (FRAME_W32_P (f))
- return w32_popup_dialog (f, header, contents);
- else
+ {
+ Lisp_Object selection = w32_popup_dialog (f, header, contents);
+
+ if (!EQ (selection, Qunsupported__w32_dialog))
+ return selection;
+ }
#endif
#ifdef HAVE_NS
if (FRAME_NS_P (f))
return ns_popup_dialog (position, header, contents);
- else
#endif
/* Display a menu with these alternatives
in the middle of frame F. */
}
}
-#endif /* HAVE_MENUS */
-
void
syms_of_menu (void)
{
menu_items_inuse = Qnil;
defsubr (&Sx_popup_menu);
-
-#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
-#endif
defsubr (&Smenu_bar_menu_at_x_y);
}