Support menus on text-mode terminals.
src/xterm.h (xw_popup_dialog): Add prototype. src/xmenu.c (Fx_popup_dialog): Function moved to menu.c. (xmenu_show): Block input here, instead in Fx_popup_menu. (xw_popup_dialog): New function, with X-specific bits of popup dialogs. src/xdisp.c (deep_copy_glyph_row, display_tty_menu_item): New functions. src/window.c (Fset_window_configuration): Use run-time tests of the frame type instead of compile-time conditionals, when menu-bar lines are considered. src/w32term.h (w32con_hide_cursor, w32con_show_cursor) (w32_popup_dialog): New prototypes. src/w32menu.c (Fx_popup_dialog): Function deleted. (w32_popup_dialog): New function, with w32 specific bits of popup dialogs. Block input here. src/w32inevt.c (w32_console_read_socket): Minor change to add debugging TTY events. src/w32fns.c (show_hourglass): If returning early because the frame is not a GUI frame, unblock input. src/w32console.c (w32con_hide_cursor, w32con_show_cursor, cursorX) (cursorY): New functions. src/termhooks.h (cursorX, cursorY): Prototypes of functions on WINDOWSNT, macros that call curX and curY elsewhere. src/termchar.h (struct tty_display_info) <showing_menu>: New flag. src/term.c (tty_hide_cursor, tty_show_cursor) [WINDOWSNT]: Call w32 specific function to hide and show cursor on a text-mode terminal. (tty_menu_struct, struct tty_menu_state): New structures. (tty_menu_create, tty_menu_make_room, tty_menu_search_pane) (tty_menu_calc_size, mouse_get_xy, tty_menu_display) (have_menus_p, tty_menu_add_pane, tty_menu_add_selection) (tty_menu_locate, save_and_enable_current_matrix) (restore_desired_matrix, screen_update, read_menu_input) (tty_menu_activate, tty_menu_destroy, tty_menu_help_callback) (tty_pop_down_menu, tty_menu_last_menubar_item) (tty_menu_new_item_coords, tty_menu_show): New functions. (syms_of_term): New DEFSYMs for tty-menu-* symbols. src/nsterm.h (ns_popup_dialog): Adjust prototype. src/nsmenu.m (ns_menu_show): Block and unblock input here, instead of in x-popup-menu. (ns_popup_dialog): Adapt order of arguments to the other *_menu_show implementations. (Fx_popup_dialog): Function deleted. src/msdos.c (x_set_menu_bar_lines): Delete unused function. src/menu.h (tty_menu_show, menu_item_width): provide prototypes. src/menu.c (have_boxes): New function. (single_keymap_panes): Use it instead of a compile-time conditional. (single_menu_item): Use run-time tests of the frame type instead of compile-time conditionals. (encode_menu_string): New function. (list_of_items, list_of_panes): Use it instead of ENCODE_STRING the macro, since different types of frame need different encoding of menu items. (digest_single_submenu): Use run-time tests of frame type instead of, or in addition to, compile-time conditionals. (menu_item_width, Fmenu_bar_menu_at_x_y): New functions. (Fx_popup_menu): Detect when the function is called from keyboard on a TTY. Don't barf when invoked on a text-mode frame. Check frame type at run time, instead of compile-time conditionals for invoking terminal-specific menu-show functions. Call tty_menu_show on text-mode frames. (Fx_popup_dialog): Moved here from xmenu.c. Test frame types at run time to determine which alternative to invoke; support dialogs on TTYs. src/keyboard.h <Qmouse_movement>: Declare. src/keyboard.c <Qmouse_movement>: Now extern. <Qecho_keystrokes>: New static variable. (read_key_sequence): Accept an additional argument, a flag to prevent redisplay during reading of the key sequence. All callers changed. (read_menu_command): New function. (read_char): When COMMANDFLAG is -2, do not redisplay and do not autosave. (toolkit_menubar_in_use): New function. (make_lispy_event): Use it instead of a compile-time test. src/fns.c (Fyes_or_no_p) [HAVE_MENUS]: Don't condition on window-system being available. src/editfns.c (Fmessage_box) [HAVE_MENUS]: Don't condition the call to x-popup-dialog on the frame type, they all now support popup dialogs. src/dispnew.c (save_current_matrix): Save the margin areas. (restore_current_matrix): Restore margin areas. (update_frame_with_menu): New function. src/dispextern.h (display_tty_menu_item, update_frame_with_menu): Add prototypes. src/alloc.c (make_save_ptr): Now compiled unconditionally. lisp/tmm.el (tmm-menubar): Adapt doc string to TTY menus functionality. lisp/tooltip.el (tooltip-mode): Don't error out on TTYs. lisp/menu-bar.el (popup-menu, popup-menu-normalize-position): Moved here from mouse.el. (popup-menu): Support menu-bar navigation on TTYs using C-f/C-b and arrow keys. (tty-menu-navigation-map): New map for TTY menu navigation. lisp/loadup.el ("tooltip"): Load even if x-show-tip is not available. lisp/frame.el (display-mouse-p): Report text-mode mouse as available on w32. (display-popup-menus-p): Report availability if mouse is available; don't condition on window-system. lisp/faces.el (tty-menu-enabled-face, tty-menu-disabled-face) (tty-menu-selected-face): New faces. configure.ac (HAVE_MENUS): Define unconditionally. doc/emacs/screen.texi (Menu Bar): Adapt to TTY menus. doc/emacs/frames.texi (Frames): Mention menu support on text terminals. doc/emacs/files.texi (Visiting): Mention the "File" menu-bar menu. doc/emacs/display.texi (Standard Faces): Mention TTY faces for menus. doc/lispref/keymaps.texi (Defining Menus, Mouse Menus, Menu Bar): Modify wording to the effect that menus are supported on TTYs. doc/lisprefframes.texi (Pop-Up Menus, Dialog Boxes) (Display Feature Testing): Update for menu support on TTYs. etc/NEWS: Mention the new features.
This commit is contained in:
commit
4ed774157d
46 changed files with 2559 additions and 695 deletions
|
@ -1,3 +1,7 @@
|
|||
2013-10-08 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* configure.ac (HAVE_MENUS): Define unconditionally.
|
||||
|
||||
2013-10-07 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Improve support for popcount and counting trailing zeros (Bug#15550).
|
||||
|
|
17
configure.ac
17
configure.ac
|
@ -1898,11 +1898,8 @@ to configure.])
|
|||
fi
|
||||
fi
|
||||
|
||||
### If we're using X11, we should use the X menu package.
|
||||
HAVE_MENUS=no
|
||||
case ${HAVE_X11} in
|
||||
yes ) HAVE_MENUS=yes ;;
|
||||
esac
|
||||
### We always support menus.
|
||||
HAVE_MENUS=yes
|
||||
|
||||
# Does the opsystem file prohibit the use of the GNU malloc?
|
||||
# Assume not, until told otherwise.
|
||||
|
@ -3183,15 +3180,9 @@ if test "${HAVE_NS}" = "yes"; then
|
|||
## Extra CFLAGS applied to src/*.m files.
|
||||
GNU_OBJC_CFLAGS="$GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE"
|
||||
fi
|
||||
# We also have mouse menus.
|
||||
HAVE_MENUS=yes
|
||||
OTHER_FILES=ns-app
|
||||
fi
|
||||
|
||||
if test "${HAVE_W32}" = "yes"; then
|
||||
HAVE_MENUS=yes
|
||||
fi
|
||||
|
||||
### Use session management (-lSM -lICE) if available
|
||||
HAVE_X_SM=no
|
||||
LIBXSM=
|
||||
|
@ -4672,9 +4663,7 @@ AC_SUBST(OLDXMENU_DEPS)
|
|||
|
||||
if test "${HAVE_MENUS}" = "yes" ; then
|
||||
AC_DEFINE(HAVE_MENUS, 1,
|
||||
[Define to 1 if you have mouse menus.
|
||||
(This is automatic if you use X, but the option to specify it remains.)
|
||||
It is also defined with other window systems that support xmenu.c.])
|
||||
[Define to 1 if you have mouse menus. (This is supported in all configurations, but the option to specify it remains.)])
|
||||
fi
|
||||
|
||||
if test "${GNU_MALLOC}" = "yes" ; then
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2013-10-08 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Support menus on text-mode terminals.
|
||||
* screen.texi (Menu Bar): Adapt to TTY menus.
|
||||
|
||||
* frames.texi (Frames): Mention menu support on text terminals.
|
||||
|
||||
* files.texi (Visiting): Mention the "File" menu-bar menu.
|
||||
|
||||
* display.texi (Standard Faces): Mention TTY faces for menus.
|
||||
|
||||
2013-10-06 Xue Fuqiao <xfq.free@gmail.com>
|
||||
|
||||
* cal-xtra.texi (Calendar Customizing, Diary Display): Remove @refill.
|
||||
|
|
|
@ -710,6 +710,17 @@ This face determines the color of tool bar icons. @xref{Tool Bars}.
|
|||
@cindex customization of @code{menu} face
|
||||
This face determines the colors and font of Emacs's menus. @xref{Menu
|
||||
Bars}.
|
||||
@item tty-menu-enabled-face
|
||||
@cindex faces for text-mode menus
|
||||
@cindex TTY menu faces
|
||||
This face is used to display enabled menu items on text-mode
|
||||
terminals.
|
||||
@item tty-menu-disabled-face
|
||||
This face is used to display disabled menu items on text-mode
|
||||
terminals.
|
||||
@item tty-menu-selected-face
|
||||
This face is used to display on text-mode terminals the menu item that
|
||||
would be selected if you click a mouse or press @key{RET}.
|
||||
@end table
|
||||
|
||||
@node Text Scale
|
||||
|
|
|
@ -286,6 +286,10 @@ exception, dropping a file into a window displaying a Dired buffer
|
|||
moves or copies the file into the displayed directory. For details,
|
||||
see @ref{Drag and Drop}, and @ref{Misc Dired Features}.
|
||||
|
||||
On text-mode terminals and on graphical displays when Emacs was
|
||||
built without a GUI toolkit, you can visit files via the menu-bar
|
||||
``File'' menu, which has a ``Visit New File'' item.
|
||||
|
||||
Each time you visit a file, Emacs automatically scans its contents
|
||||
to detect what character encoding and end-of-line convention it uses,
|
||||
and converts these to Emacs's internal encoding and end-of-line
|
||||
|
|
|
@ -39,7 +39,7 @@ doing so on GNU and Unix systems; and
|
|||
@ifnottex
|
||||
@pxref{MS-DOS Mouse},
|
||||
@end ifnottex
|
||||
for doing so on MS-DOS).
|
||||
for doing so on MS-DOS). Menus are supported on all text terminals.
|
||||
|
||||
@menu
|
||||
* Mouse Commands:: Moving, cutting, and pasting, with the mouse.
|
||||
|
|
|
@ -287,13 +287,12 @@ here, as you can more easily see them yourself.
|
|||
|
||||
@kindex M-`
|
||||
@kindex F10
|
||||
@findex tmm-menubar
|
||||
@findex menu-bar-open
|
||||
On a graphical display, you can use the mouse to choose a command
|
||||
from the menu bar. An arrow on the right edge of a menu item means it
|
||||
leads to a subsidiary menu, or @dfn{submenu}. A @samp{...} at the end
|
||||
of a menu item means that the command will prompt you for further
|
||||
input before it actually does anything.
|
||||
On a display that support a mouse, you can use the mouse to choose a
|
||||
command from the menu bar. An arrow on the right edge of a menu item
|
||||
means it leads to a subsidiary menu, or @dfn{submenu}. A @samp{...}
|
||||
at the end of a menu item means that the command will prompt you for
|
||||
further input before it actually does anything.
|
||||
|
||||
Some of the commands in the menu bar have ordinary key bindings as
|
||||
well; if so, a key binding is shown in parentheses after the item
|
||||
|
@ -305,14 +304,20 @@ the usual way (@pxref{Key Help}).
|
|||
item by pressing @key{F10} (to run the command @code{menu-bar-open}).
|
||||
You can then navigate the menus with the arrow keys. To activate a
|
||||
selected menu item, press @key{RET}; to cancel menu navigation, press
|
||||
@key{ESC}.
|
||||
@kbd{C-g} or @kbd{ESC ESC ESC}.
|
||||
|
||||
On a text terminal, you can use the menu bar by typing @kbd{M-`} or
|
||||
@key{F10} (these run the command @code{tmm-menubar}). This lets you
|
||||
select a menu item with the keyboard. A provisional choice appears in
|
||||
the echo area. You can use the up and down arrow keys to move through
|
||||
the menu to different items, and then you can type @key{RET} to select
|
||||
the item. Each menu item is also designated by a letter or digit
|
||||
(usually the initial of some word in the item's name). This letter or
|
||||
digit is separated from the item name by @samp{==>}. You can type the
|
||||
item's letter or digit to select the item.
|
||||
@findex tmm-menubar
|
||||
@vindex tty-menu-open-use-tmm
|
||||
On a text terminal, you can optionally access the menu-bar menus in
|
||||
the echo area. To this end, customize the variable
|
||||
@code{tty-menu-open-use-tmm} to a non-@code{nil} value. Then typing
|
||||
@key{F10} will run the command @code{tmm-menubar} instead of dropping
|
||||
down the menu. (You can also type @kbd{M-`}, which always invokes
|
||||
@code{tmm-menubar}.) @code{tmm-menubar} lets you select a menu item
|
||||
with the keyboard. A provisional choice appears in the echo area.
|
||||
You can use the up and down arrow keys to move through the menu to
|
||||
different items, and then you can type @key{RET} to select the item.
|
||||
Each menu item is also designated by a letter or digit (usually the
|
||||
initial of some word in the item's name). This letter or digit is
|
||||
separated from the item name by @samp{==>}. You can type the item's
|
||||
letter or digit to select the item.
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2013-10-08 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Support menus on text-mode terminals.
|
||||
* keymaps.texi (Defining Menus, Mouse Menus, Menu Bar): Modify
|
||||
wording to the effect that menus are supported on TTYs.
|
||||
|
||||
* frames.texi (Pop-Up Menus, Dialog Boxes)
|
||||
(Display Feature Testing): Update for menu support on TTYs.
|
||||
|
||||
2013-10-07 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* tips.texi (Comment Tips): Discourage use of triple semi-colons for
|
||||
|
|
|
@ -1741,8 +1741,10 @@ allows to know if the pointer has been hidden.
|
|||
@node Pop-Up Menus
|
||||
@section Pop-Up Menus
|
||||
|
||||
When using a window system, a Lisp program can pop up a menu so that
|
||||
the user can choose an alternative with the mouse.
|
||||
A Lisp program can pop up a menu so that the user can choose an
|
||||
alternative with the mouse. On a text terminal, if the mouse is not
|
||||
available, the user can choose an alternative using the keyboard
|
||||
motion keys---@kbd{C-n}, @kbd{C-p}, or up- and down-arrow keys.
|
||||
|
||||
@defun x-popup-menu position menu
|
||||
This function displays a pop-up menu and returns an indication of
|
||||
|
@ -1763,20 +1765,22 @@ pixels, counting from the top left corner of @var{window}. @var{window}
|
|||
may be a window or a frame.
|
||||
|
||||
If @var{position} is @code{t}, it means to use the current mouse
|
||||
position. If @var{position} is @code{nil}, it means to precompute the
|
||||
key binding equivalents for the keymaps specified in @var{menu},
|
||||
without actually displaying or popping up the menu.
|
||||
position (or the top-left corner of the frame if the mouse is not
|
||||
available on a text terminal). If @var{position} is @code{nil}, it
|
||||
means to precompute the key binding equivalents for the keymaps
|
||||
specified in @var{menu}, without actually displaying or popping up the
|
||||
menu.
|
||||
|
||||
The argument @var{menu} says what to display in the menu. It can be a
|
||||
keymap or a list of keymaps (@pxref{Menu Keymaps}). In this case, the
|
||||
return value is the list of events corresponding to the user's choice.
|
||||
This list has more than one element if the choice occurred in a
|
||||
submenu. (Note that @code{x-popup-menu} does not actually execute the
|
||||
command bound to that sequence of events.) On toolkits that support
|
||||
menu titles, the title is taken from the prompt string of @var{menu}
|
||||
if @var{menu} is a keymap, or from the prompt string of the first
|
||||
keymap in @var{menu} if it is a list of keymaps (@pxref{Defining
|
||||
Menus}).
|
||||
command bound to that sequence of events.) On text terminals and
|
||||
toolkits that support menu titles, the title is taken from the prompt
|
||||
string of @var{menu} if @var{menu} is a keymap, or from the prompt
|
||||
string of the first keymap in @var{menu} if it is a list of keymaps
|
||||
(@pxref{Defining Menus}).
|
||||
|
||||
Alternatively, @var{menu} can have the following form:
|
||||
|
||||
|
@ -1800,7 +1804,7 @@ cell; this makes a non-selectable menu item.
|
|||
|
||||
If the user gets rid of the menu without making a valid choice, for
|
||||
instance by clicking the mouse away from a valid choice or by typing
|
||||
keyboard input, then this normally results in a quit and
|
||||
@kbd{C-g}, then this normally results in a quit and
|
||||
@code{x-popup-menu} does not return. But if @var{position} is a mouse
|
||||
button event (indicating that the user invoked the menu with the
|
||||
mouse) then no quit occurs and @code{x-popup-menu} returns @code{nil}.
|
||||
|
@ -1872,7 +1876,8 @@ window don't matter; only the frame matters.
|
|||
|
||||
If @var{header} is non-@code{nil}, the frame title for the box is
|
||||
@samp{Information}, otherwise it is @samp{Question}. The former is used
|
||||
for @code{message-box} (@pxref{message-box}).
|
||||
for @code{message-box} (@pxref{message-box}). (On text terminals, the
|
||||
box title is not displayed.)
|
||||
|
||||
In some configurations, Emacs cannot display a real dialog box; so
|
||||
instead it displays the same items in a pop-up menu in the center of the
|
||||
|
@ -2284,9 +2289,9 @@ obtain information about displays.
|
|||
|
||||
@defun display-popup-menus-p &optional display
|
||||
This function returns @code{t} if popup menus are supported on
|
||||
@var{display}, @code{nil} if not. Support for popup menus requires that
|
||||
the mouse be available, since the user cannot choose menu items without
|
||||
a mouse.
|
||||
@var{display}, @code{nil} if not. Support for popup menus requires
|
||||
that the mouse be available, since the menu is popped up by clicking
|
||||
the mouse on some portion of the Emacs display.
|
||||
@end defun
|
||||
|
||||
@defun display-graphic-p &optional display
|
||||
|
|
|
@ -2023,7 +2023,7 @@ which is a string that appears as an element of the keymap.
|
|||
the menu's commands. Emacs displays the overall prompt string as the
|
||||
menu title in some cases, depending on the toolkit (if any) used for
|
||||
displaying menus.@footnote{It is required for menus which do not use a
|
||||
toolkit, e.g., under MS-DOS.} Keyboard menus also display the
|
||||
toolkit, e.g., on a text terminal.} Keyboard menus also display the
|
||||
overall prompt string.
|
||||
|
||||
The easiest way to construct a keymap with a prompt string is to
|
||||
|
@ -2371,16 +2371,17 @@ if the menu keymap contains a single nested keymap and no other menu
|
|||
items, the menu shows the contents of the nested keymap directly, not
|
||||
as a submenu.
|
||||
|
||||
However, if Emacs is compiled without X toolkit support, submenus
|
||||
are not supported. Each nested keymap is shown as a menu item, but
|
||||
clicking on it does not automatically pop up the submenu. If you wish
|
||||
to imitate the effect of submenus, you can do that by giving a nested
|
||||
keymap an item string which starts with @samp{@@}. This causes Emacs
|
||||
to display the nested keymap using a separate @dfn{menu pane}; the
|
||||
rest of the item string after the @samp{@@} is the pane label. If
|
||||
Emacs is compiled without X toolkit support, menu panes are not used;
|
||||
in that case, a @samp{@@} at the beginning of an item string is
|
||||
omitted when the menu label is displayed, and has no other effect.
|
||||
However, if Emacs is compiled without X toolkit support, or on text
|
||||
terminals, submenus are not supported. Each nested keymap is shown as
|
||||
a menu item, but clicking on it does not automatically pop up the
|
||||
submenu. If you wish to imitate the effect of submenus, you can do
|
||||
that by giving a nested keymap an item string which starts with
|
||||
@samp{@@}. This causes Emacs to display the nested keymap using a
|
||||
separate @dfn{menu pane}; the rest of the item string after the
|
||||
@samp{@@} is the pane label. If Emacs is compiled without X toolkit
|
||||
support, or if a menu is displayed on a text terminal, menu panes are
|
||||
not used; in that case, a @samp{@@} at the beginning of an item string
|
||||
is omitted when the menu label is displayed, and has no other effect.
|
||||
|
||||
@node Keyboard Menus
|
||||
@subsection Menus and the Keyboard
|
||||
|
@ -2485,10 +2486,10 @@ can do it this way:
|
|||
@subsection The Menu Bar
|
||||
@cindex menu bar
|
||||
|
||||
On graphical displays, there is usually a @dfn{menu bar} at the top
|
||||
of each frame. @xref{Menu Bars,,,emacs, The GNU Emacs Manual}. Menu
|
||||
bar items are subcommands of the fake ``function key''
|
||||
@code{menu-bar}, as defined in the active keymaps.
|
||||
Emacs usually shows a @dfn{menu bar} at the top of each frame.
|
||||
@xref{Menu Bars,,,emacs, The GNU Emacs Manual}. Menu bar items are
|
||||
subcommands of the fake ``function key'' @code{menu-bar}, as defined
|
||||
in the active keymaps.
|
||||
|
||||
To add an item to the menu bar, invent a fake ``function key'' of your
|
||||
own (let's call it @var{key}), and make a binding for the key sequence
|
||||
|
@ -2575,7 +2576,7 @@ in Documentation}.
|
|||
|
||||
A @dfn{tool bar} is a row of clickable icons at the top of a frame,
|
||||
just below the menu bar. @xref{Tool Bars,,,emacs, The GNU Emacs
|
||||
Manual}.
|
||||
Manual}. Emacs normally shows a tool bar on graphical displays.
|
||||
|
||||
On each frame, the frame parameter @code{tool-bar-lines} controls
|
||||
how many lines' worth of height to reserve for the tool bar. A zero
|
||||
|
|
26
etc/NEWS
26
etc/NEWS
|
@ -65,6 +65,22 @@ To use the old backend by default, do on the command line:
|
|||
|
||||
* Changes in Emacs 24.4
|
||||
|
||||
+++
|
||||
** Emacs now supports menus on text-mode terminals.
|
||||
If the terminal supports a mouse, clicking on the menu bar, or on
|
||||
sensitive portions of the mode line or header line, will drop down the
|
||||
menu defined at that position. Likewise, clicking C-mouse-2 or
|
||||
C-mouse-2 or C-mouse-3 on the text area will pop up the menus defined
|
||||
for those locations.
|
||||
|
||||
If the text terminal does not support a mouse, you can activate the
|
||||
first menu-bar menu by typing F10, which invokes `menu-bar-open'.
|
||||
|
||||
If you want the previous behavior, whereby F10 invoked `tmm-menubar',
|
||||
customize the option `tty-menu-open-use-tmm' to a non-nil value.
|
||||
(Typing M-` will always invoke `tmm-menubar', even if
|
||||
`tty-menu-open-use-tmm' is nil.)
|
||||
|
||||
** Key ? also describes prefix bindings like C-h.
|
||||
|
||||
+++
|
||||
|
@ -653,6 +669,16 @@ for something (not just adding elements to it), it ought not to affect you.
|
|||
|
||||
* Lisp Changes in Emacs 24.4
|
||||
|
||||
+++
|
||||
** Functions that pop up menus and dialogs now work on all terminal types,
|
||||
including TTYs.
|
||||
This includes `x-popup-menu', `x-popup-dialog', `message-box',
|
||||
`yes-or-no-p', etc.
|
||||
|
||||
The function `display-popup-menus-p' will now return non-nil for a
|
||||
display or frame whenever a mouse is supported on that display or
|
||||
frame.
|
||||
|
||||
** New bool-vector set operation functions:
|
||||
*** `bool-vector-exclusive-or'
|
||||
*** `bool-vector-union'
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
2013-10-08 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Support menus on text-mode terminals.
|
||||
* tmm.el (tmm-menubar): Adapt doc string to TTY menus
|
||||
functionality.
|
||||
|
||||
* tooltip.el (tooltip-mode): Don't error out on TTYs.
|
||||
|
||||
* menu-bar.el (popup-menu, popup-menu-normalize-position): Moved
|
||||
here from mouse.el.
|
||||
(popup-menu): Support menu-bar navigation on TTYs using C-f/C-b
|
||||
and arrow keys.
|
||||
(tty-menu-navigation-map): New map for TTY menu navigation.
|
||||
|
||||
* loadup.el ("tooltip"): Load even if x-show-tip is not available.
|
||||
|
||||
* frame.el (display-mouse-p): Report text-mode mouse as available
|
||||
on w32.
|
||||
(display-popup-menus-p): Report availability if mouse is
|
||||
available; don't condition on window-system.
|
||||
|
||||
* faces.el (tty-menu-enabled-face, tty-menu-disabled-face)
|
||||
(tty-menu-selected-face): New faces.
|
||||
|
||||
2013-10-08 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/lisp-mode.el: Font-lock cl-lib constructs.
|
||||
|
|
|
@ -2142,7 +2142,6 @@ terminal type to a different value."
|
|||
(frame-set-background-mode frame t)
|
||||
(face-set-after-frame-default frame)))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Standard faces.
|
||||
|
@ -2551,6 +2550,26 @@ It is used for characters of no fonts too."
|
|||
:version "24.1"
|
||||
:group 'basic-faces)
|
||||
|
||||
;; Faces for TTY menus.
|
||||
(defface tty-menu-enabled-face
|
||||
'((t
|
||||
:foreground "yellow" :background "blue" :weight bold))
|
||||
"Face for displaying enabled items in TTY menus."
|
||||
:group 'basic-faces)
|
||||
|
||||
(defface tty-menu-disabled-face
|
||||
'((((class color) (min-colors 16))
|
||||
:foreground "lightgray" :background "blue")
|
||||
(t
|
||||
:foreground "white" :background "blue"))
|
||||
"Face for displaying disabled items in TTY menus."
|
||||
:group 'basic-faces)
|
||||
|
||||
(defface tty-menu-selected-face
|
||||
'((t :background "red"))
|
||||
"Face for displaying the currently selected item in TTY menus."
|
||||
:group 'basic-faces)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Manipulating font names.
|
||||
|
|
|
@ -1304,17 +1304,17 @@ frame's display)."
|
|||
xterm-mouse-mode)
|
||||
;; t-mouse is distributed with the GPM package. It doesn't have
|
||||
;; a toggle.
|
||||
(featurep 't-mouse))))))
|
||||
(featurep 't-mouse)
|
||||
;; No way to check whether a w32 console has a mouse, assume
|
||||
;; it always does.
|
||||
(boundp 'w32-use-full-screen-buffer))))))
|
||||
|
||||
(defun display-popup-menus-p (&optional display)
|
||||
"Return non-nil if popup menus are supported on DISPLAY.
|
||||
DISPLAY can be a display name, a frame, or nil (meaning the selected
|
||||
frame's display).
|
||||
Support for popup menus requires that the mouse be available."
|
||||
(and
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(memq frame-type '(x w32 pc ns)))
|
||||
(display-mouse-p display)))
|
||||
(display-mouse-p display))
|
||||
|
||||
(defun display-graphic-p (&optional display)
|
||||
"Return non-nil if DISPLAY is a graphic display.
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
(load "vc/vc-hooks")
|
||||
(load "vc/ediff-hook")
|
||||
(if (fboundp 'x-show-tip) (load "tooltip"))
|
||||
(if (not (eq system-type 'ms-dos)) (load "tooltip"))
|
||||
|
||||
;If you want additional libraries to be preloaded and their
|
||||
;doc strings kept in the DOC file rather than in core,
|
||||
|
|
209
lisp/menu-bar.el
209
lisp/menu-bar.el
|
@ -2182,13 +2182,211 @@ See `menu-bar-mode' for more information."
|
|||
(declare-function x-menu-bar-open "term/x-win" (&optional frame))
|
||||
(declare-function w32-menu-bar-open "term/w32-win" (&optional frame))
|
||||
|
||||
(defun popup-menu (menu &optional position prefix from-menu-bar)
|
||||
"Popup the given menu and call the selected option.
|
||||
MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
|
||||
`x-popup-menu'.
|
||||
The menu is shown at the place where POSITION specifies. About
|
||||
the form of POSITION, see `popup-menu-normalize-position'.
|
||||
PREFIX is the prefix argument (if any) to pass to the command.
|
||||
FROM-MENU-BAR, if non-nil, means we are dropping one of menu-bar's menus."
|
||||
(let* ((map (cond
|
||||
((keymapp menu) menu)
|
||||
((and (listp menu) (keymapp (car menu))) menu)
|
||||
(t (let* ((map (easy-menu-create-menu (car menu) (cdr menu)))
|
||||
(filter (when (symbolp map)
|
||||
(plist-get (get map 'menu-prop) :filter))))
|
||||
(if filter (funcall filter (symbol-function map)) map)))))
|
||||
(frame (selected-frame))
|
||||
event cmd)
|
||||
(if from-menu-bar
|
||||
(let* ((xy (posn-x-y position))
|
||||
(menu-symbol (menu-bar-menu-at-x-y (car xy) (cdr xy))))
|
||||
(setq position (list menu-symbol (list frame '(menu-bar)
|
||||
xy 0))))
|
||||
(setq position (popup-menu-normalize-position position)))
|
||||
;; The looping behavior was taken from lmenu's popup-menu-popup
|
||||
(while (and map (setq event
|
||||
;; map could be a prefix key, in which case
|
||||
;; we need to get its function cell
|
||||
;; definition.
|
||||
(x-popup-menu position (indirect-function map))))
|
||||
;; Strangely x-popup-menu returns a list.
|
||||
;; mouse-major-mode-menu was using a weird:
|
||||
;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
|
||||
(setq cmd
|
||||
(cond
|
||||
((and from-menu-bar
|
||||
(consp event)
|
||||
(numberp (car event))
|
||||
(numberp (cdr event)))
|
||||
(let ((x (car event))
|
||||
(y (cdr event))
|
||||
menu-symbol)
|
||||
(setq menu-symbol (menu-bar-menu-at-x-y x y))
|
||||
(setq position (list menu-symbol (list frame '(menu-bar)
|
||||
event 0)))
|
||||
(setq map
|
||||
(or
|
||||
(lookup-key global-map (vector 'menu-bar menu-symbol))
|
||||
(lookup-key (current-local-map) (vector 'menu-bar
|
||||
menu-symbol))))))
|
||||
((and (not (keymapp map)) (listp map))
|
||||
;; We were given a list of keymaps. Search them all
|
||||
;; in sequence until a first binding is found.
|
||||
(let ((mouse-click (apply 'vector event))
|
||||
binding)
|
||||
(while (and map (null binding))
|
||||
(setq binding (lookup-key (car map) mouse-click))
|
||||
(if (numberp binding) ; `too long'
|
||||
(setq binding nil))
|
||||
(setq map (cdr map)))
|
||||
binding))
|
||||
(t
|
||||
;; We were given a single keymap.
|
||||
(lookup-key map (apply 'vector event)))))
|
||||
;; Clear out echoing, which perhaps shows a prefix arg.
|
||||
(message "")
|
||||
;; Maybe try again but with the submap.
|
||||
(setq map (if (keymapp cmd) cmd)))
|
||||
;; If the user did not cancel by refusing to select,
|
||||
;; and if the result is a command, run it.
|
||||
(when (and (null map) (commandp cmd))
|
||||
(setq prefix-arg prefix)
|
||||
;; `setup-specified-language-environment', for instance,
|
||||
;; expects this to be set from a menu keymap.
|
||||
(setq last-command-event (car (last event)))
|
||||
;; mouse-major-mode-menu was using `command-execute' instead.
|
||||
(call-interactively cmd))))
|
||||
|
||||
(defun popup-menu-normalize-position (position)
|
||||
"Convert the POSITION to the form which `popup-menu' expects internally.
|
||||
POSITION can an event, a posn- value, a value having
|
||||
form ((XOFFSET YOFFSET) WINDOW), or nil.
|
||||
If nil, the current mouse position is used."
|
||||
(pcase position
|
||||
;; nil -> mouse cursor position
|
||||
(`nil
|
||||
(let ((mp (mouse-pixel-position)))
|
||||
(list (list (cadr mp) (cddr mp)) (car mp))))
|
||||
;; Value returned from `event-end' or `posn-at-point'.
|
||||
((pred posnp)
|
||||
(let ((xy (posn-x-y position)))
|
||||
(list (list (car xy) (cdr xy))
|
||||
(posn-window position))))
|
||||
;; Event.
|
||||
((pred eventp)
|
||||
(popup-menu-normalize-position (event-end position)))
|
||||
(t position)))
|
||||
|
||||
(defvar tty-menu-navigation-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
;; The next line is disabled because it breaks interpretation of
|
||||
;; escape sequences, produced by TTY arrow keys, as tty-menu-*
|
||||
;; commands. Instead, we explicitly bind some keys to
|
||||
;; tty-menu-exit.
|
||||
;;(define-key map [t] 'tty-menu-exit)
|
||||
|
||||
;; The tty-menu-* are just symbols interpreted by term.c, they are
|
||||
;; not real commands.
|
||||
(substitute-key-definition 'keyboard-quit 'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'keyboard-escape-quit 'tty-menu-exit
|
||||
map (current-global-map))
|
||||
;; The bindings of menu-bar items are so that clicking on the menu
|
||||
;; bar when a menu is already shown pops down that menu.
|
||||
;; FIXME: we should iterate over all the visible menu-bar items,
|
||||
;; instead of naming them explicitly here. Also, this doesn't
|
||||
;; include items added by current major mode.
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar file])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar edit])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar options])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar buffer])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar tools])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition (lookup-key (current-global-map) [menu-bar help-menu])
|
||||
'tty-menu-exit
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'forward-char 'tty-menu-next-menu
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'backward-char 'tty-menu-prev-menu
|
||||
map (current-global-map))
|
||||
;; The following two will need to be revised if we ever support
|
||||
;; a right-to-left menu bar.
|
||||
(substitute-key-definition 'right-char 'tty-menu-next-menu
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'left-char 'tty-menu-prev-menu
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'next-line 'tty-menu-next-item
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'previous-line 'tty-menu-prev-item
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'newline 'tty-menu-select
|
||||
map (current-global-map))
|
||||
(substitute-key-definition 'newline-and-indent 'tty-menu-select
|
||||
map (current-global-map))
|
||||
(define-key map [?\C-r] 'tty-menu-select)
|
||||
(define-key map [?\C-j] 'tty-menu-select)
|
||||
(define-key map [return] 'tty-menu-select)
|
||||
(define-key map [linefeed] 'tty-menu-select)
|
||||
(define-key map [down-mouse-1] 'tty-menu-select)
|
||||
(define-key map [drag-mouse-1] 'tty-menu-select)
|
||||
(define-key map [mode-line drag-mouse-1] 'tty-menu-select)
|
||||
(define-key map [mode-line down-mouse-1] 'tty-menu-select)
|
||||
(define-key map [header-line mouse-1] 'tty-menu-select)
|
||||
(define-key map [header-line drag-mouse-1] 'tty-menu-select)
|
||||
(define-key map [header-line down-mouse-1] 'tty-menu-select)
|
||||
(define-key map [mode-line mouse-1] 'tty-menu-ignore)
|
||||
(define-key map [mode-line mouse-2] 'tty-menu-ignore)
|
||||
(define-key map [mode-line mouse-3] 'tty-menu-ignore)
|
||||
(define-key map [mode-line C-mouse-1] 'tty-menu-ignore)
|
||||
(define-key map [mode-line C-mouse-2] 'tty-menu-ignore)
|
||||
(define-key map [mode-line C-mouse-3] 'tty-menu-ignore)
|
||||
;; The mouse events must be bound to tty-menu-ignore, otherwise
|
||||
;; the initial mouse click will select and immediately pop down
|
||||
;; the menu.
|
||||
(define-key map [mouse-1] 'tty-menu-ignore)
|
||||
(define-key map [C-mouse-1] 'tty-menu-ignore)
|
||||
(define-key map [C-mouse-2] 'tty-menu-ignore)
|
||||
(define-key map [C-mouse-3] 'tty-menu-ignore)
|
||||
(define-key map [mouse-movement] 'tty-menu-mouse-movement)
|
||||
map)
|
||||
"Keymap used while processing TTY menus.")
|
||||
|
||||
|
||||
(defcustom tty-menu-open-use-tmm nil
|
||||
"If non-nil, \\[menu-bar-open] on a TTY will invoke `tmm-menubar'.
|
||||
|
||||
If nil, \\[menu-bar-open] will drop down the menu corresponding to the
|
||||
first (leftmost) menu-bar item; you can select other items by typing
|
||||
\\[forward-char], \\[backward-char], \\[right-char] and \\[left-char]."
|
||||
:type '(choice (const :tag "F10 drops down TTY menus" nil)
|
||||
(const :tag "F10 invokes tmm-menubar" t))
|
||||
:group 'display
|
||||
:version "24.4")
|
||||
|
||||
(defvar tty-menu--initial-menu-x 1
|
||||
"X coordinate of the first menu-bar menu dropped by F10.
|
||||
|
||||
This is meant to be used only for debugging TTY menus.")
|
||||
|
||||
(defun menu-bar-open (&optional frame)
|
||||
"Start key navigation of the menu bar in FRAME.
|
||||
|
||||
This function decides which method to use to access the menu
|
||||
depending on FRAME's terminal device. On X displays, it calls
|
||||
`x-menu-bar-open'; on Windows, `w32-menu-bar-open' otherwise it
|
||||
calls `tmm-menubar'.
|
||||
`x-menu-bar-open'; on Windows, `w32-menu-bar-open'; otherwise it
|
||||
calls either `popup-menu' or `tmm-menubar' depending on whether
|
||||
\`tty-menu-open-use-tmm' is nil or not.
|
||||
|
||||
If FRAME is nil or not given, use the selected frame."
|
||||
(interactive)
|
||||
|
@ -2196,6 +2394,13 @@ If FRAME is nil or not given, use the selected frame."
|
|||
(cond
|
||||
((eq type 'x) (x-menu-bar-open frame))
|
||||
((eq type 'w32) (w32-menu-bar-open frame))
|
||||
((null tty-menu-open-use-tmm)
|
||||
(let* ((x tty-menu--initial-menu-x)
|
||||
(menu (menu-bar-menu-at-x-y x 0 frame)))
|
||||
(popup-menu (or
|
||||
(lookup-key global-map (vector 'menu-bar menu))
|
||||
(lookup-key (current-local-map) (vector 'menu-bar menu)))
|
||||
(posn-at-x-y x 0 nil t) nil t)))
|
||||
(t (with-selected-frame (or frame (selected-frame))
|
||||
(tmm-menubar))))))
|
||||
|
||||
|
|
|
@ -144,79 +144,6 @@ Expects to be bound to `down-mouse-1' in `key-translation-map'."
|
|||
|
||||
;; Provide a mode-specific menu on a mouse button.
|
||||
|
||||
(defun popup-menu (menu &optional position prefix)
|
||||
"Popup the given menu and call the selected option.
|
||||
MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
|
||||
`x-popup-menu'.
|
||||
The menu is shown at the place where POSITION specifies. About
|
||||
the form of POSITION, see `popup-menu-normalize-position'.
|
||||
PREFIX is the prefix argument (if any) to pass to the command."
|
||||
(let* ((map (cond
|
||||
((keymapp menu) menu)
|
||||
((and (listp menu) (keymapp (car menu))) menu)
|
||||
(t (let* ((map (easy-menu-create-menu (car menu) (cdr menu)))
|
||||
(filter (when (symbolp map)
|
||||
(plist-get (get map 'menu-prop) :filter))))
|
||||
(if filter (funcall filter (symbol-function map)) map)))))
|
||||
event cmd
|
||||
(position (popup-menu-normalize-position position)))
|
||||
;; The looping behavior was taken from lmenu's popup-menu-popup
|
||||
(while (and map (setq event
|
||||
;; map could be a prefix key, in which case
|
||||
;; we need to get its function cell
|
||||
;; definition.
|
||||
(x-popup-menu position (indirect-function map))))
|
||||
;; Strangely x-popup-menu returns a list.
|
||||
;; mouse-major-mode-menu was using a weird:
|
||||
;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
|
||||
(setq cmd
|
||||
(if (and (not (keymapp map)) (listp map))
|
||||
;; We were given a list of keymaps. Search them all
|
||||
;; in sequence until a first binding is found.
|
||||
(let ((mouse-click (apply 'vector event))
|
||||
binding)
|
||||
(while (and map (null binding))
|
||||
(setq binding (lookup-key (car map) mouse-click))
|
||||
(if (numberp binding) ; `too long'
|
||||
(setq binding nil))
|
||||
(setq map (cdr map)))
|
||||
binding)
|
||||
;; We were given a single keymap.
|
||||
(lookup-key map (apply 'vector event))))
|
||||
;; Clear out echoing, which perhaps shows a prefix arg.
|
||||
(message "")
|
||||
;; Maybe try again but with the submap.
|
||||
(setq map (if (keymapp cmd) cmd)))
|
||||
;; If the user did not cancel by refusing to select,
|
||||
;; and if the result is a command, run it.
|
||||
(when (and (null map) (commandp cmd))
|
||||
(setq prefix-arg prefix)
|
||||
;; `setup-specified-language-environment', for instance,
|
||||
;; expects this to be set from a menu keymap.
|
||||
(setq last-command-event (car (last event)))
|
||||
;; mouse-major-mode-menu was using `command-execute' instead.
|
||||
(call-interactively cmd))))
|
||||
|
||||
(defun popup-menu-normalize-position (position)
|
||||
"Convert the POSITION to the form which `popup-menu' expects internally.
|
||||
POSITION can an event, a posn- value, a value having
|
||||
form ((XOFFSET YOFFSET) WINDOW), or nil.
|
||||
If nil, the current mouse position is used."
|
||||
(pcase position
|
||||
;; nil -> mouse cursor position
|
||||
(`nil
|
||||
(let ((mp (mouse-pixel-position)))
|
||||
(list (list (cadr mp) (cddr mp)) (car mp))))
|
||||
;; Value returned from `event-end' or `posn-at-point'.
|
||||
((pred posnp)
|
||||
(let ((xy (posn-x-y position)))
|
||||
(list (list (car xy) (cdr xy))
|
||||
(posn-window position))))
|
||||
;; Event.
|
||||
((pred eventp)
|
||||
(popup-menu-normalize-position (event-end position)))
|
||||
(t position)))
|
||||
|
||||
(defun minor-mode-menu-from-indicator (indicator)
|
||||
"Show menu for minor mode specified by INDICATOR.
|
||||
Interactively, INDICATOR is read using completion.
|
||||
|
|
|
@ -50,7 +50,11 @@
|
|||
"Text-mode emulation of looking and choosing from a menubar.
|
||||
See the documentation for `tmm-prompt'.
|
||||
X-POSITION, if non-nil, specifies a horizontal position within the menu bar;
|
||||
we make that menu bar item (the one at that position) the default choice."
|
||||
we make that menu bar item (the one at that position) the default choice.
|
||||
|
||||
Note that \\[menu-bar-open] by default drops down TTY menus; if you want it
|
||||
to invoke `tmm-menubar' instead, customize the variable
|
||||
\`tty-menu-open-use-tmm' to a non-nil value."
|
||||
(interactive)
|
||||
(run-hooks 'menu-bar-update-hook)
|
||||
;; Obey menu-bar-final-items; put those items last.
|
||||
|
|
|
@ -58,9 +58,7 @@ echo area, instead of making a pop-up window."
|
|||
:init-value t
|
||||
:initialize 'custom-initialize-delay
|
||||
:group 'tooltip
|
||||
(unless (or (null tooltip-mode) (fboundp 'x-show-tip))
|
||||
(error "Sorry, tooltips are not yet available on this system"))
|
||||
(if tooltip-mode
|
||||
(if (and tooltip-mode (fboundp 'x-show-tip))
|
||||
(progn
|
||||
(add-hook 'pre-command-hook 'tooltip-hide)
|
||||
(add-hook 'tooltip-functions 'tooltip-help-tips))
|
||||
|
|
113
src/ChangeLog
113
src/ChangeLog
|
@ -1,3 +1,116 @@
|
|||
2013-10-08 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Support menus on text-mode terminals.
|
||||
* xterm.h (xw_popup_dialog): Add prototype.
|
||||
|
||||
* xmenu.c (Fx_popup_dialog): Function moved to menu.c.
|
||||
(xmenu_show): Block input here, instead in Fx_popup_menu.
|
||||
(xw_popup_dialog): New function, with X-specific bits of popup
|
||||
dialogs.
|
||||
|
||||
* xdisp.c (deep_copy_glyph_row, display_tty_menu_item): New
|
||||
functions.
|
||||
|
||||
* window.c (Fset_window_configuration): Use run-time tests of the
|
||||
frame type instead of compile-time conditionals, when menu-bar
|
||||
lines are considered.
|
||||
|
||||
* w32term.h (w32con_hide_cursor, w32con_show_cursor)
|
||||
(w32_popup_dialog): New prototypes.
|
||||
|
||||
* w32menu.c (Fx_popup_dialog): Function deleted.
|
||||
(w32_popup_dialog): New function, with w32 specific bits of popup
|
||||
dialogs. Block input here.
|
||||
|
||||
* w32inevt.c (w32_console_read_socket): Minor change to add
|
||||
debugging TTY events.
|
||||
|
||||
* w32fns.c (show_hourglass): If returning early because the frame
|
||||
is not a GUI frame, unblock input.
|
||||
|
||||
* w32console.c (w32con_hide_cursor, w32con_show_cursor, cursorX)
|
||||
(cursorY): New functions.
|
||||
|
||||
* termhooks.h (cursorX, cursorY): Prototypes of functions on
|
||||
WINDOWSNT, macros that call curX and curY elsewhere.
|
||||
|
||||
* termchar.h (struct tty_display_info) <showing_menu>: New flag.
|
||||
|
||||
* term.c (tty_hide_cursor, tty_show_cursor) [WINDOWSNT]: Call w32
|
||||
specific function to hide and show cursor on a text-mode terminal.
|
||||
(tty_menu_struct, struct tty_menu_state): New structures.
|
||||
(tty_menu_create, tty_menu_make_room, tty_menu_search_pane)
|
||||
(tty_menu_calc_size, mouse_get_xy, tty_menu_display)
|
||||
(have_menus_p, tty_menu_add_pane, tty_menu_add_selection)
|
||||
(tty_menu_locate, save_and_enable_current_matrix)
|
||||
(restore_desired_matrix, screen_update, read_menu_input)
|
||||
(tty_menu_activate, tty_menu_destroy, tty_menu_help_callback)
|
||||
(tty_pop_down_menu, tty_menu_last_menubar_item)
|
||||
(tty_menu_new_item_coords, tty_menu_show): New functions.
|
||||
(syms_of_term): New DEFSYMs for tty-menu-* symbols.
|
||||
|
||||
* nsterm.h (ns_popup_dialog): Adjust prototype.
|
||||
|
||||
* nsmenu.m (ns_menu_show): Block and unblock input here, instead
|
||||
of in x-popup-menu.
|
||||
(ns_popup_dialog): Adapt order of arguments to the other
|
||||
*_menu_show implementations.
|
||||
(Fx_popup_dialog): Function deleted.
|
||||
|
||||
* msdos.c (x_set_menu_bar_lines): Delete unused function.
|
||||
|
||||
* menu.h (tty_menu_show, menu_item_width): provide prototypes.
|
||||
|
||||
* menu.c (have_boxes): New function.
|
||||
(single_keymap_panes): Use it instead of a compile-time
|
||||
conditional.
|
||||
(single_menu_item): Use run-time tests of the frame type instead
|
||||
of compile-time conditionals.
|
||||
(encode_menu_string): New function.
|
||||
(list_of_items, list_of_panes): Use it instead of ENCODE_STRING
|
||||
the macro, since different types of frame need different encoding
|
||||
of menu items.
|
||||
(digest_single_submenu): Use run-time tests of frame type instead
|
||||
of, or in addition to, compile-time conditionals.
|
||||
(menu_item_width, Fmenu_bar_menu_at_x_y): New functions.
|
||||
(Fx_popup_menu): Detect when the function is called from keyboard
|
||||
on a TTY. Don't barf when invoked on a text-mode frame. Check
|
||||
frame type at run time, instead of compile-time conditionals for
|
||||
invoking terminal-specific menu-show functions. Call
|
||||
tty_menu_show on text-mode frames.
|
||||
(Fx_popup_dialog): Moved here from xmenu.c. Test frame types at
|
||||
run time to determine which alternative to invoke; support dialogs
|
||||
on TTYs.
|
||||
|
||||
* keyboard.h <Qmouse_movement>: Declare.
|
||||
|
||||
* keyboard.c <Qmouse_movement>: Now extern.
|
||||
<Qecho_keystrokes>: New static variable.
|
||||
(read_key_sequence): Accept an additional argument, a flag to
|
||||
prevent redisplay during reading of the key sequence. All callers
|
||||
changed.
|
||||
(read_menu_command): New function.
|
||||
(read_char): When COMMANDFLAG is -2, do not redisplay and do not
|
||||
autosave.
|
||||
(toolkit_menubar_in_use): New function.
|
||||
(make_lispy_event): Use it instead of a compile-time test.
|
||||
|
||||
* fns.c (Fyes_or_no_p) [HAVE_MENUS]: Don't condition on
|
||||
window-system being available.
|
||||
|
||||
* editfns.c (Fmessage_box) [HAVE_MENUS]: Don't condition the call
|
||||
to x-popup-dialog on the frame type, they all now support popup
|
||||
dialogs.
|
||||
|
||||
* dispnew.c (save_current_matrix): Save the margin areas.
|
||||
(restore_current_matrix): Restore margin areas.
|
||||
(update_frame_with_menu): New function.
|
||||
|
||||
* dispextern.h (display_tty_menu_item, update_frame_with_menu):
|
||||
Add prototypes.
|
||||
|
||||
* alloc.c (make_save_ptr): Now compiled unconditionally.
|
||||
|
||||
2013-10-08 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
* dispnew.c (set_window_update_flags): Add buffer arg. Adjust comment.
|
||||
|
|
|
@ -3408,7 +3408,6 @@ make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c,
|
|||
return val;
|
||||
}
|
||||
|
||||
#if defined HAVE_NS || defined HAVE_NTGUI
|
||||
Lisp_Object
|
||||
make_save_ptr (void *a)
|
||||
{
|
||||
|
@ -3418,7 +3417,6 @@ make_save_ptr (void *a)
|
|||
p->data[0].pointer = a;
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
Lisp_Object
|
||||
make_save_ptr_int (void *a, ptrdiff_t b)
|
||||
|
|
2
src/cm.h
2
src/cm.h
|
@ -139,7 +139,7 @@ struct cm
|
|||
#define MultiDownCost(tty) (tty)->Wcm->cc_multidown
|
||||
#define MultiLeftCost(tty) (tty)->Wcm->cc_multileft
|
||||
#define MultiRightCost(tty) (tty)->Wcm->cc_multiright
|
||||
#endif
|
||||
#endif /* NoCMShortHand */
|
||||
|
||||
#define cmat(tty,row,col) (curY(tty) = (row), curX(tty) = (col))
|
||||
#define cmplus(tty,n) \
|
||||
|
|
|
@ -3256,6 +3256,7 @@ extern int clear_mouse_face (Mouse_HLInfo *);
|
|||
extern int cursor_in_mouse_face_p (struct window *w);
|
||||
extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
|
||||
int, int, enum draw_glyphs_face);
|
||||
extern void display_tty_menu_item (const char *, int, int, int, int, int);
|
||||
|
||||
/* Flags passed to try_window. */
|
||||
#define TRY_WINDOW_CHECK_MARGINS (1 << 0)
|
||||
|
@ -3427,6 +3428,8 @@ extern void hide_hourglass (void);
|
|||
|
||||
int popup_activated (void);
|
||||
|
||||
/* Defined in dispnew.c */
|
||||
|
||||
extern Lisp_Object buffer_posn_from_coords (struct window *,
|
||||
int *, int *,
|
||||
struct display_pos *,
|
||||
|
@ -3442,6 +3445,7 @@ extern Lisp_Object marginal_area_string (struct window *, enum window_part,
|
|||
int *, int *, int *, int *);
|
||||
extern void redraw_frame (struct frame *);
|
||||
extern bool update_frame (struct frame *, bool, bool);
|
||||
extern void update_frame_with_menu (struct frame *);
|
||||
extern void bitch_at_user (void);
|
||||
extern void adjust_frame_glyphs (struct frame *);
|
||||
void free_glyphs (struct frame *);
|
||||
|
@ -3467,7 +3471,7 @@ void change_frame_size (struct frame *, int, int, bool, bool, bool);
|
|||
void init_display (void);
|
||||
void syms_of_display (void);
|
||||
extern Lisp_Object Qredisplay_dont_pause;
|
||||
void spec_glyph_lookup_face (struct window *, GLYPH *);
|
||||
extern void spec_glyph_lookup_face (struct window *, GLYPH *);
|
||||
|
||||
/* Defined in terminal.c */
|
||||
|
||||
|
|
|
@ -1844,9 +1844,28 @@ save_current_matrix (struct frame *f)
|
|||
struct glyph_row *from = f->current_matrix->rows + i;
|
||||
struct glyph_row *to = saved->rows + i;
|
||||
ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
|
||||
|
||||
to->glyphs[TEXT_AREA] = xmalloc (nbytes);
|
||||
memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
|
||||
to->used[TEXT_AREA] = from->used[TEXT_AREA];
|
||||
to->enabled_p = from->enabled_p;
|
||||
to->hash = from->hash;
|
||||
if (from->used[LEFT_MARGIN_AREA])
|
||||
{
|
||||
nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
|
||||
to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
|
||||
memcpy (to->glyphs[LEFT_MARGIN_AREA],
|
||||
from->glyphs[LEFT_MARGIN_AREA], nbytes);
|
||||
to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
|
||||
}
|
||||
if (from->used[RIGHT_MARGIN_AREA])
|
||||
{
|
||||
nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
|
||||
to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
|
||||
memcpy (to->glyphs[RIGHT_MARGIN_AREA],
|
||||
from->glyphs[RIGHT_MARGIN_AREA], nbytes);
|
||||
to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
|
||||
}
|
||||
}
|
||||
|
||||
return saved;
|
||||
|
@ -1866,9 +1885,30 @@ restore_current_matrix (struct frame *f, struct glyph_matrix *saved)
|
|||
struct glyph_row *from = saved->rows + i;
|
||||
struct glyph_row *to = f->current_matrix->rows + i;
|
||||
ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
|
||||
|
||||
memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
|
||||
to->used[TEXT_AREA] = from->used[TEXT_AREA];
|
||||
xfree (from->glyphs[TEXT_AREA]);
|
||||
nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
|
||||
if (nbytes)
|
||||
{
|
||||
memcpy (to->glyphs[LEFT_MARGIN_AREA],
|
||||
from->glyphs[LEFT_MARGIN_AREA], nbytes);
|
||||
to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
|
||||
xfree (from->glyphs[LEFT_MARGIN_AREA]);
|
||||
}
|
||||
else
|
||||
to->used[LEFT_MARGIN_AREA] = 0;
|
||||
nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
|
||||
if (nbytes)
|
||||
{
|
||||
memcpy (to->glyphs[RIGHT_MARGIN_AREA],
|
||||
from->glyphs[RIGHT_MARGIN_AREA], nbytes);
|
||||
to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
|
||||
xfree (from->glyphs[RIGHT_MARGIN_AREA]);
|
||||
}
|
||||
else
|
||||
to->used[RIGHT_MARGIN_AREA] = 0;
|
||||
}
|
||||
|
||||
xfree (saved->rows);
|
||||
|
@ -3047,6 +3087,47 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
|
|||
return paused_p;
|
||||
}
|
||||
|
||||
/* Update a TTY frame F that has a menu dropped down over some of its
|
||||
glyphs. This is like the second part of update_frame, but it
|
||||
doesn't call build_frame_matrix, because we already have the
|
||||
desired matrix prepared, and don't want it to be overwritten by the
|
||||
text of the normal display. */
|
||||
void
|
||||
update_frame_with_menu (struct frame *f)
|
||||
{
|
||||
struct window *root_window = XWINDOW (f->root_window);
|
||||
bool paused_p;
|
||||
|
||||
eassert (FRAME_TERMCAP_P (f));
|
||||
|
||||
/* We are working on frame matrix basis. Set the frame on whose
|
||||
frame matrix we operate. */
|
||||
set_frame_matrix_frame (f);
|
||||
|
||||
/* Update the display */
|
||||
update_begin (f);
|
||||
/* Force update_frame_1 not to stop due to pending input, and not
|
||||
try scrolling. */
|
||||
paused_p = update_frame_1 (f, 1, 1);
|
||||
update_end (f);
|
||||
|
||||
if (FRAME_TTY (f)->termscript)
|
||||
fflush (FRAME_TTY (f)->termscript);
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
/* Check window matrices for lost pointers. */
|
||||
#if GLYPH_DEBUG
|
||||
#if 0
|
||||
/* We cannot possibly survive the matrix pointers check, since
|
||||
we have overwritten parts of the frame glyph matrix without
|
||||
making any updates to the window matrices. */
|
||||
check_window_matrix_pointers (root_window);
|
||||
#endif
|
||||
add_frame_display_history (f, paused_p);
|
||||
#endif
|
||||
|
||||
/* Reset flags indicating that a window should be updated. */
|
||||
set_window_update_flags (root_window, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -3472,22 +3472,17 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
|
|||
{
|
||||
Lisp_Object val = Fformat (nargs, args);
|
||||
#ifdef HAVE_MENUS
|
||||
/* The MS-DOS frames support popup menus even though they are
|
||||
not FRAME_WINDOW_P. */
|
||||
if (FRAME_WINDOW_P (XFRAME (selected_frame))
|
||||
|| FRAME_MSDOS_P (XFRAME (selected_frame)))
|
||||
{
|
||||
Lisp_Object pane, menu;
|
||||
struct gcpro gcpro1;
|
||||
pane = list1 (Fcons (build_string ("OK"), Qt));
|
||||
GCPRO1 (pane);
|
||||
menu = Fcons (val, pane);
|
||||
Fx_popup_dialog (Qt, menu, Qt);
|
||||
UNGCPRO;
|
||||
return val;
|
||||
}
|
||||
#endif /* HAVE_MENUS */
|
||||
Lisp_Object pane, menu;
|
||||
struct gcpro gcpro1;
|
||||
|
||||
pane = list1 (Fcons (build_string ("OK"), Qt));
|
||||
GCPRO1 (pane);
|
||||
menu = Fcons (val, pane);
|
||||
Fx_popup_dialog (Qt, menu, Qt);
|
||||
UNGCPRO;
|
||||
#else /* !HAVE_MENUS */
|
||||
message3 (val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2434,8 +2434,8 @@ a space; `yes-or-no-p' adds \"(yes or no) \" to it.
|
|||
The user must confirm the answer with RET, and can edit it until it
|
||||
has been confirmed.
|
||||
|
||||
Under a windowing system a dialog box will be used if `last-nonmenu-event'
|
||||
is nil, and `use-dialog-box' is non-nil. */)
|
||||
If dialog boxes are supported, a dialog box will be used
|
||||
if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */)
|
||||
(Lisp_Object prompt)
|
||||
{
|
||||
register Lisp_Object ans;
|
||||
|
@ -2446,8 +2446,7 @@ is nil, and `use-dialog-box' is non-nil. */)
|
|||
|
||||
#ifdef HAVE_MENUS
|
||||
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
|
||||
&& use_dialog_box
|
||||
&& window_system_available (SELECTED_FRAME ()))
|
||||
&& use_dialog_box)
|
||||
{
|
||||
Lisp_Object pane, menu, obj;
|
||||
redisplay_preserve_echo_area (4);
|
||||
|
|
|
@ -1248,9 +1248,6 @@ extern void x_set_tool_bar_lines (struct frame *f,
|
|||
Lisp_Object oldval);
|
||||
extern void x_activate_menubar (struct frame *);
|
||||
extern void x_real_positions (struct frame *, int *, int *);
|
||||
extern void x_set_menu_bar_lines (struct frame *,
|
||||
Lisp_Object,
|
||||
Lisp_Object);
|
||||
extern void free_frame_menubar (struct frame *);
|
||||
extern void x_free_frame_resources (struct frame *);
|
||||
|
||||
|
|
164
src/keyboard.c
164
src/keyboard.c
|
@ -289,7 +289,7 @@ static struct input_event * volatile kbd_store_ptr;
|
|||
at inopportune times. */
|
||||
|
||||
/* Symbols to head events. */
|
||||
static Lisp_Object Qmouse_movement;
|
||||
Lisp_Object Qmouse_movement;
|
||||
static Lisp_Object Qscroll_bar_movement;
|
||||
Lisp_Object Qswitch_frame;
|
||||
static Lisp_Object Qfocus_in, Qfocus_out;
|
||||
|
@ -354,6 +354,8 @@ Lisp_Object Qvertical_line;
|
|||
static Lisp_Object Qvertical_scroll_bar;
|
||||
Lisp_Object Qmenu_bar;
|
||||
|
||||
static Lisp_Object Qecho_keystrokes;
|
||||
|
||||
static void recursive_edit_unwind (Lisp_Object buffer);
|
||||
static Lisp_Object command_loop (void);
|
||||
static Lisp_Object Qcommand_execute;
|
||||
|
@ -1305,7 +1307,7 @@ some_mouse_moved (void)
|
|||
sans error-handling encapsulation. */
|
||||
|
||||
static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
|
||||
bool, bool, bool);
|
||||
bool, bool, bool, bool);
|
||||
void safe_run_hooks (Lisp_Object);
|
||||
static void adjust_point_for_property (ptrdiff_t, bool);
|
||||
|
||||
|
@ -1431,7 +1433,7 @@ command_loop_1 (void)
|
|||
|
||||
/* Read next key sequence; i gets its length. */
|
||||
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
|
||||
Qnil, 0, 1, 1);
|
||||
Qnil, 0, 1, 1, 0);
|
||||
|
||||
/* A filter may have run while we were reading the input. */
|
||||
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
|
||||
|
@ -1691,6 +1693,31 @@ command_loop_1 (void)
|
|||
}
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
read_menu_command (void)
|
||||
{
|
||||
Lisp_Object cmd;
|
||||
Lisp_Object keybuf[30];
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
int i;
|
||||
|
||||
/* We don't want to echo the keystrokes while navigating the
|
||||
menus. */
|
||||
specbind (Qecho_keystrokes, make_number (0));
|
||||
|
||||
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
|
||||
Qnil, 0, 1, 1, 1);
|
||||
|
||||
unbind_to (count, Qnil);
|
||||
|
||||
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
|
||||
Fkill_emacs (Qnil);
|
||||
if (i == 0 || i == -1)
|
||||
return Qt;
|
||||
|
||||
return read_key_sequence_cmd;
|
||||
}
|
||||
|
||||
/* Adjust point to a boundary of a region that has such a property
|
||||
that should be treated intangible. For the moment, we check
|
||||
`composition', `display' and `invisible' properties.
|
||||
|
@ -2358,6 +2385,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
|
|||
/* Read a character from the keyboard; call the redisplay if needed. */
|
||||
/* commandflag 0 means do not autosave, but do redisplay.
|
||||
-1 means do not redisplay, but do autosave.
|
||||
-2 means do neither.
|
||||
1 means do both. */
|
||||
|
||||
/* The arguments MAP is for menu prompting. MAP is a keymap.
|
||||
|
@ -2722,7 +2750,7 @@ read_char (int commandflag, Lisp_Object map,
|
|||
|
||||
/* Maybe auto save due to number of keystrokes. */
|
||||
|
||||
if (commandflag != 0
|
||||
if (commandflag != 0 && commandflag != -2
|
||||
&& auto_save_interval > 0
|
||||
&& num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
|
||||
&& !detect_input_pending_run_timers (0))
|
||||
|
@ -2774,7 +2802,7 @@ read_char (int commandflag, Lisp_Object map,
|
|||
9 at 200k, 11 at 300k, and 12 at 500k. It is 15 at 1 meg. */
|
||||
|
||||
/* Auto save if enough time goes by without input. */
|
||||
if (commandflag != 0
|
||||
if (commandflag != 0 && commandflag != -2
|
||||
&& num_nonmacro_input_events > last_auto_save
|
||||
&& INTEGERP (Vauto_save_timeout)
|
||||
&& XINT (Vauto_save_timeout) > 0)
|
||||
|
@ -3870,7 +3898,22 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
}
|
||||
}
|
||||
else
|
||||
wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
|
||||
{
|
||||
bool do_display = true;
|
||||
|
||||
if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
|
||||
{
|
||||
struct tty_display_info *tty = CURTTY ();
|
||||
|
||||
/* When this TTY is displaying a menu, we must prevent
|
||||
any redisplay, because we modify the frame's glyph
|
||||
matrix behind the back of the display engine. */
|
||||
if (tty->showing_menu)
|
||||
do_display = false;
|
||||
}
|
||||
|
||||
wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
|
||||
}
|
||||
|
||||
if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
|
||||
gobble_input ();
|
||||
|
@ -5363,6 +5406,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
|
|||
extra_info))));
|
||||
}
|
||||
|
||||
/* Return non-zero if F is a GUI frame that uses some toolkit-managed
|
||||
menu bar. This really means that Emacs draws and manages the menu
|
||||
bar as part of its normal display, and therefore can compute its
|
||||
geometry. */
|
||||
static bool
|
||||
toolkit_menubar_in_use (struct frame *f)
|
||||
{
|
||||
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
|
||||
return !(!FRAME_WINDOW_P (f));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Given a struct input_event, build the lisp event which represents
|
||||
it. If EVENT is 0, build a mouse movement event from the mouse
|
||||
movement buffer, which should have a movement event in it.
|
||||
|
@ -5514,64 +5571,64 @@ make_lispy_event (struct input_event *event)
|
|||
if (event->kind == MOUSE_CLICK_EVENT)
|
||||
{
|
||||
struct frame *f = XFRAME (event->frame_or_window);
|
||||
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
|
||||
int row, column;
|
||||
#endif
|
||||
|
||||
/* Ignore mouse events that were made on frame that
|
||||
have been deleted. */
|
||||
if (! FRAME_LIVE_P (f))
|
||||
return Qnil;
|
||||
|
||||
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
|
||||
/* EVENT->x and EVENT->y are frame-relative pixel
|
||||
coordinates at this place. Under old redisplay, COLUMN
|
||||
and ROW are set to frame relative glyph coordinates
|
||||
which are then used to determine whether this click is
|
||||
in a menu (non-toolkit version). */
|
||||
pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
|
||||
&column, &row, NULL, 1);
|
||||
|
||||
/* In the non-toolkit version, clicks on the menu bar
|
||||
are ordinary button events in the event buffer.
|
||||
Distinguish them, and invoke the menu.
|
||||
|
||||
(In the toolkit version, the toolkit handles the menu bar
|
||||
and Emacs doesn't know about it until after the user
|
||||
makes a selection.) */
|
||||
if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
|
||||
&& (event->modifiers & down_modifier))
|
||||
if (!toolkit_menubar_in_use (f))
|
||||
{
|
||||
Lisp_Object items, item;
|
||||
pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
|
||||
&column, &row, NULL, 1);
|
||||
|
||||
/* Find the menu bar item under `column'. */
|
||||
item = Qnil;
|
||||
items = FRAME_MENU_BAR_ITEMS (f);
|
||||
for (i = 0; i < ASIZE (items); i += 4)
|
||||
/* In the non-toolkit version, clicks on the menu bar
|
||||
are ordinary button events in the event buffer.
|
||||
Distinguish them, and invoke the menu.
|
||||
|
||||
(In the toolkit version, the toolkit handles the
|
||||
menu bar and Emacs doesn't know about it until
|
||||
after the user makes a selection.) */
|
||||
if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
|
||||
&& (event->modifiers & down_modifier))
|
||||
{
|
||||
Lisp_Object pos, string;
|
||||
string = AREF (items, i + 1);
|
||||
pos = AREF (items, i + 3);
|
||||
if (NILP (string))
|
||||
break;
|
||||
if (column >= XINT (pos)
|
||||
&& column < XINT (pos) + SCHARS (string))
|
||||
Lisp_Object items, item;
|
||||
|
||||
/* Find the menu bar item under `column'. */
|
||||
item = Qnil;
|
||||
items = FRAME_MENU_BAR_ITEMS (f);
|
||||
for (i = 0; i < ASIZE (items); i += 4)
|
||||
{
|
||||
item = AREF (items, i);
|
||||
break;
|
||||
Lisp_Object pos, string;
|
||||
string = AREF (items, i + 1);
|
||||
pos = AREF (items, i + 3);
|
||||
if (NILP (string))
|
||||
break;
|
||||
if (column >= XINT (pos)
|
||||
&& column < XINT (pos) + SCHARS (string))
|
||||
{
|
||||
item = AREF (items, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ELisp manual 2.4b says (x y) are window
|
||||
relative but code says they are
|
||||
frame-relative. */
|
||||
position = list4 (event->frame_or_window,
|
||||
Qmenu_bar,
|
||||
Fcons (event->x, event->y),
|
||||
make_number (event->timestamp));
|
||||
|
||||
return list2 (item, position);
|
||||
}
|
||||
|
||||
/* ELisp manual 2.4b says (x y) are window relative but
|
||||
code says they are frame-relative. */
|
||||
position = list4 (event->frame_or_window,
|
||||
Qmenu_bar,
|
||||
Fcons (event->x, event->y),
|
||||
make_number (event->timestamp));
|
||||
|
||||
return list2 (item, position);
|
||||
}
|
||||
#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
|
||||
|
||||
position = make_lispy_position (f, event->x, event->y,
|
||||
event->timestamp);
|
||||
|
@ -8792,6 +8849,9 @@ test_undefined (Lisp_Object binding)
|
|||
|
||||
Echo starting immediately unless `prompt' is 0.
|
||||
|
||||
If PREVENT_REDISPLAY is non-zero, avoid redisplay by calling
|
||||
read_char with a suitable COMMANDFLAG argument.
|
||||
|
||||
Where a key sequence ends depends on the currently active keymaps.
|
||||
These include any minor mode keymaps active in the current buffer,
|
||||
the current buffer's local map, and the global map.
|
||||
|
@ -8824,7 +8884,7 @@ test_undefined (Lisp_Object binding)
|
|||
static int
|
||||
read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
||||
bool dont_downcase_last, bool can_return_switch_frame,
|
||||
bool fix_current_buffer)
|
||||
bool fix_current_buffer, bool prevent_redisplay)
|
||||
{
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
|
||||
|
@ -8905,8 +8965,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
{
|
||||
if (!NILP (prompt))
|
||||
{
|
||||
/* Install the string STR as the beginning of the string of
|
||||
echoing, so that it serves as a prompt for the next
|
||||
/* Install the string PROMPT as the beginning of the string
|
||||
of echoing, so that it serves as a prompt for the next
|
||||
character. */
|
||||
kset_echo_string (current_kboard, prompt);
|
||||
current_kboard->echo_after_prompt = SCHARS (prompt);
|
||||
|
@ -9061,7 +9121,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
{
|
||||
KBOARD *interrupted_kboard = current_kboard;
|
||||
struct frame *interrupted_frame = SELECTED_FRAME ();
|
||||
key = read_char (NILP (prompt),
|
||||
/* Calling read_char with COMMANDFLAG = -2 avoids
|
||||
redisplay in read_char and its subroutines. */
|
||||
key = read_char (prevent_redisplay ? -2 : NILP (prompt),
|
||||
current_binding, last_nonmenu_event,
|
||||
&used_mouse_menu, NULL);
|
||||
if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
|
||||
|
@ -9757,7 +9819,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
|
|||
|
||||
i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
|
||||
prompt, ! NILP (dont_downcase_last),
|
||||
! NILP (can_return_switch_frame), 0);
|
||||
! NILP (can_return_switch_frame), 0, 0);
|
||||
|
||||
#if 0 /* The following is fine for code reading a key sequence and
|
||||
then proceeding with a lengthy computation, but it's not good
|
||||
|
@ -11003,6 +11065,8 @@ syms_of_keyboard (void)
|
|||
|
||||
DEFSYM (Qhelp_form_show, "help-form-show");
|
||||
|
||||
DEFSYM (Qecho_keystrokes, "echo-keystrokes");
|
||||
|
||||
Fset (Qinput_method_exit_on_first_char, Qnil);
|
||||
Fset (Qinput_method_use_echo_area, Qnil);
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@ extern Lisp_Object Qswitch_frame;
|
|||
extern Lisp_Object Qevent_kind;
|
||||
|
||||
/* The values of Qevent_kind properties. */
|
||||
extern Lisp_Object Qmouse_click;
|
||||
extern Lisp_Object Qmouse_click, Qmouse_movement;
|
||||
|
||||
extern Lisp_Object Qhelp_echo;
|
||||
|
||||
|
|
568
src/menu.c
568
src/menu.c
|
@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "termhooks.h"
|
||||
#include "blockinput.h"
|
||||
#include "dispextern.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#ifdef USE_X_TOOLKIT
|
||||
#include "../lwlib/lwlib.h"
|
||||
|
@ -50,10 +51,16 @@ extern HMENU current_popup_menu;
|
|||
|
||||
#include "menu.h"
|
||||
|
||||
/* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
|
||||
/* Return non-zero if menus can handle radio and toggle buttons. */
|
||||
static bool
|
||||
have_boxes (void)
|
||||
{
|
||||
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
|
||||
#define HAVE_BOXES 1
|
||||
if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
Lisp_Object menu_items;
|
||||
|
||||
|
@ -283,13 +290,14 @@ single_keymap_panes (Lisp_Object keymap, Lisp_Object pane_name,
|
|||
|
||||
push_menu_pane (pane_name, prefix);
|
||||
|
||||
#ifndef HAVE_BOXES
|
||||
/* Remember index for first item in this pane so we can go back and
|
||||
add a prefix when (if) we see the first button. After that, notbuttons
|
||||
is set to 0, to mark that we have seen a button and all non button
|
||||
items need a prefix. */
|
||||
skp.notbuttons = menu_items_used;
|
||||
#endif
|
||||
if (!have_boxes ())
|
||||
{
|
||||
/* Remember index for first item in this pane so we can go back
|
||||
and add a prefix when (if) we see the first button. After
|
||||
that, notbuttons is set to 0, to mark that we have seen a
|
||||
button and all non button items need a prefix. */
|
||||
skp.notbuttons = menu_items_used;
|
||||
}
|
||||
|
||||
GCPRO1 (skp.pending_maps);
|
||||
map_keymap_canonical (keymap, single_menu_item, Qnil, &skp);
|
||||
|
@ -345,77 +353,72 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) || defined (MSDOS)
|
||||
#ifndef HAVE_BOXES
|
||||
/* Simulate radio buttons and toggle boxes by putting a prefix in
|
||||
front of them. */
|
||||
{
|
||||
Lisp_Object prefix = Qnil;
|
||||
Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
|
||||
if (!NILP (type))
|
||||
{
|
||||
Lisp_Object selected
|
||||
= AREF (item_properties, ITEM_PROPERTY_SELECTED);
|
||||
if (!have_boxes ())
|
||||
{
|
||||
Lisp_Object prefix = Qnil;
|
||||
Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
|
||||
if (!NILP (type))
|
||||
{
|
||||
Lisp_Object selected
|
||||
= AREF (item_properties, ITEM_PROPERTY_SELECTED);
|
||||
|
||||
if (skp->notbuttons)
|
||||
/* The first button. Line up previous items in this menu. */
|
||||
{
|
||||
int idx = skp->notbuttons; /* Index for first item this menu. */
|
||||
int submenu = 0;
|
||||
Lisp_Object tem;
|
||||
while (idx < menu_items_used)
|
||||
{
|
||||
tem
|
||||
= AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
|
||||
if (NILP (tem))
|
||||
{
|
||||
idx++;
|
||||
submenu++; /* Skip sub menu. */
|
||||
}
|
||||
else if (EQ (tem, Qlambda))
|
||||
{
|
||||
idx++;
|
||||
submenu--; /* End sub menu. */
|
||||
}
|
||||
else if (EQ (tem, Qt))
|
||||
idx += 3; /* Skip new pane marker. */
|
||||
else if (EQ (tem, Qquote))
|
||||
idx++; /* Skip a left, right divider. */
|
||||
else
|
||||
{
|
||||
if (!submenu && SREF (tem, 0) != '\0'
|
||||
&& SREF (tem, 0) != '-')
|
||||
ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
|
||||
concat2 (build_string (" "), tem));
|
||||
idx += MENU_ITEMS_ITEM_LENGTH;
|
||||
}
|
||||
}
|
||||
skp->notbuttons = 0;
|
||||
}
|
||||
if (skp->notbuttons)
|
||||
/* The first button. Line up previous items in this menu. */
|
||||
{
|
||||
int idx = skp->notbuttons; /* Index for first item this menu. */
|
||||
int submenu = 0;
|
||||
Lisp_Object tem;
|
||||
while (idx < menu_items_used)
|
||||
{
|
||||
tem
|
||||
= AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
|
||||
if (NILP (tem))
|
||||
{
|
||||
idx++;
|
||||
submenu++; /* Skip sub menu. */
|
||||
}
|
||||
else if (EQ (tem, Qlambda))
|
||||
{
|
||||
idx++;
|
||||
submenu--; /* End sub menu. */
|
||||
}
|
||||
else if (EQ (tem, Qt))
|
||||
idx += 3; /* Skip new pane marker. */
|
||||
else if (EQ (tem, Qquote))
|
||||
idx++; /* Skip a left, right divider. */
|
||||
else
|
||||
{
|
||||
if (!submenu && SREF (tem, 0) != '\0'
|
||||
&& SREF (tem, 0) != '-')
|
||||
ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
|
||||
concat2 (build_string (" "), tem));
|
||||
idx += MENU_ITEMS_ITEM_LENGTH;
|
||||
}
|
||||
}
|
||||
skp->notbuttons = 0;
|
||||
}
|
||||
|
||||
/* Calculate prefix, if any, for this item. */
|
||||
if (EQ (type, QCtoggle))
|
||||
prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
|
||||
else if (EQ (type, QCradio))
|
||||
prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
|
||||
}
|
||||
/* Not a button. If we have earlier buttons, then we need a prefix. */
|
||||
else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
|
||||
&& SREF (item_string, 0) != '-')
|
||||
prefix = build_string (" ");
|
||||
/* Calculate prefix, if any, for this item. */
|
||||
if (EQ (type, QCtoggle))
|
||||
prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
|
||||
else if (EQ (type, QCradio))
|
||||
prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
|
||||
}
|
||||
/* Not a button. If we have earlier buttons, then we need a prefix. */
|
||||
else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
|
||||
&& SREF (item_string, 0) != '-')
|
||||
prefix = build_string (" ");
|
||||
|
||||
if (!NILP (prefix))
|
||||
item_string = concat2 (prefix, item_string);
|
||||
if (!NILP (prefix))
|
||||
item_string = concat2 (prefix, item_string);
|
||||
}
|
||||
#endif /* not HAVE_BOXES */
|
||||
|
||||
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
if (!NILP (map))
|
||||
if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
|
||||
&& !NILP (map))
|
||||
/* Indicate visually that this is a submenu. */
|
||||
item_string = concat2 (item_string, build_string (" >"));
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_X_WINDOWS || MSDOS */
|
||||
|
||||
push_menu_item (item_string, enabled, key,
|
||||
AREF (item_properties, ITEM_PROPERTY_DEF),
|
||||
|
@ -426,7 +429,8 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
|
|||
|
||||
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
|
||||
/* Display a submenu using the toolkit. */
|
||||
if (! (NILP (map) || NILP (enabled)))
|
||||
if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame))
|
||||
&& ! (NILP (map) || NILP (enabled)))
|
||||
{
|
||||
push_submenu_start ();
|
||||
single_keymap_panes (map, Qnil, key, skp->maxdepth - 1);
|
||||
|
@ -455,6 +459,16 @@ keymap_panes (Lisp_Object *keymaps, ptrdiff_t nmaps)
|
|||
finish_menu_items ();
|
||||
}
|
||||
|
||||
/* Encode a menu string as appropriate for menu-updating-frame's type. */
|
||||
static Lisp_Object
|
||||
encode_menu_string (Lisp_Object str)
|
||||
{
|
||||
/* TTY menu strings are encoded by write_glyphs, when they are
|
||||
delivered to the glass, so no need to encode them here. */
|
||||
if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame)))
|
||||
return str;
|
||||
return ENCODE_MENU_STRING (str);
|
||||
}
|
||||
|
||||
/* Push the items in a single pane defined by the alist PANE. */
|
||||
static void
|
||||
|
@ -466,13 +480,13 @@ list_of_items (Lisp_Object pane)
|
|||
{
|
||||
item = XCAR (tail);
|
||||
if (STRINGP (item))
|
||||
push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
|
||||
push_menu_item (encode_menu_string (item), Qnil, Qnil, Qt,
|
||||
Qnil, Qnil, Qnil, Qnil);
|
||||
else if (CONSP (item))
|
||||
{
|
||||
item1 = XCAR (item);
|
||||
CHECK_STRING (item1);
|
||||
push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
|
||||
push_menu_item (encode_menu_string (item1), Qt, XCDR (item),
|
||||
Qt, Qnil, Qnil, Qnil, Qnil);
|
||||
}
|
||||
else
|
||||
|
@ -497,7 +511,7 @@ list_of_panes (Lisp_Object menu)
|
|||
elt = XCAR (tail);
|
||||
pane_name = Fcar (elt);
|
||||
CHECK_STRING (pane_name);
|
||||
push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
|
||||
push_menu_pane (encode_menu_string (pane_name), Qnil);
|
||||
pane_data = Fcdr (elt);
|
||||
CHECK_CONS (pane_data);
|
||||
list_of_items (pane_data);
|
||||
|
@ -614,6 +628,7 @@ digest_single_submenu (int start, int end, bool top_level_items)
|
|||
int submenu_depth = 0;
|
||||
widget_value **submenu_stack;
|
||||
bool panes_seen = 0;
|
||||
struct frame *f = XFRAME (Vmenu_updating_frame);
|
||||
|
||||
submenu_stack = alloca (menu_items_used * sizeof *submenu_stack);
|
||||
wv = xmalloc_widget_value ();
|
||||
|
@ -663,30 +678,35 @@ digest_single_submenu (int start, int end, bool top_level_items)
|
|||
|
||||
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
|
||||
|
||||
/* TTY menus display menu items via tty_write_glyphs, which
|
||||
will encode the strings as appropriate. */
|
||||
if (!FRAME_TERMCAP_P (f))
|
||||
{
|
||||
#ifdef HAVE_NTGUI
|
||||
if (STRINGP (pane_name))
|
||||
{
|
||||
if (unicode_append_menu)
|
||||
/* Encode as UTF-8 for now. */
|
||||
pane_name = ENCODE_UTF_8 (pane_name);
|
||||
else if (STRING_MULTIBYTE (pane_name))
|
||||
pane_name = ENCODE_SYSTEM (pane_name);
|
||||
if (STRINGP (pane_name))
|
||||
{
|
||||
if (unicode_append_menu)
|
||||
/* Encode as UTF-8 for now. */
|
||||
pane_name = ENCODE_UTF_8 (pane_name);
|
||||
else if (STRING_MULTIBYTE (pane_name))
|
||||
pane_name = ENCODE_SYSTEM (pane_name);
|
||||
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
#elif defined (USE_LUCID) && defined (HAVE_XFT)
|
||||
if (STRINGP (pane_name))
|
||||
{
|
||||
pane_name = ENCODE_UTF_8 (pane_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
if (STRINGP (pane_name))
|
||||
{
|
||||
pane_name = ENCODE_UTF_8 (pane_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
#elif !defined (HAVE_MULTILINGUAL_MENU)
|
||||
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
|
||||
{
|
||||
pane_name = ENCODE_MENU_STRING (pane_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
|
||||
{
|
||||
pane_name = ENCODE_MENU_STRING (pane_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
pane_string = (NILP (pane_name)
|
||||
? "" : SSDATA (pane_name));
|
||||
|
@ -737,47 +757,52 @@ digest_single_submenu (int start, int end, bool top_level_items)
|
|||
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
|
||||
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
|
||||
|
||||
/* TTY menu items and their descriptions will be encoded by
|
||||
tty_write_glyphs. */
|
||||
if (!FRAME_TERMCAP_P (f))
|
||||
{
|
||||
#ifdef HAVE_NTGUI
|
||||
if (STRINGP (item_name))
|
||||
{
|
||||
if (unicode_append_menu)
|
||||
item_name = ENCODE_UTF_8 (item_name);
|
||||
else if (STRING_MULTIBYTE (item_name))
|
||||
item_name = ENCODE_SYSTEM (item_name);
|
||||
if (STRINGP (item_name))
|
||||
{
|
||||
if (unicode_append_menu)
|
||||
item_name = ENCODE_UTF_8 (item_name);
|
||||
else if (STRING_MULTIBYTE (item_name))
|
||||
item_name = ENCODE_SYSTEM (item_name);
|
||||
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
|
||||
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
|
||||
{
|
||||
descrip = ENCODE_SYSTEM (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
|
||||
{
|
||||
descrip = ENCODE_SYSTEM (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
#elif USE_LUCID
|
||||
if (STRINGP (item_name))
|
||||
{
|
||||
item_name = ENCODE_UTF_8 (item_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
if (STRINGP (item_name))
|
||||
{
|
||||
item_name = ENCODE_UTF_8 (item_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
|
||||
if (STRINGP (descrip))
|
||||
{
|
||||
descrip = ENCODE_UTF_8 (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
if (STRINGP (descrip))
|
||||
{
|
||||
descrip = ENCODE_UTF_8 (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
#elif !defined (HAVE_MULTILINGUAL_MENU)
|
||||
if (STRING_MULTIBYTE (item_name))
|
||||
{
|
||||
item_name = ENCODE_MENU_STRING (item_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
if (STRING_MULTIBYTE (item_name))
|
||||
{
|
||||
item_name = ENCODE_MENU_STRING (item_name);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
|
||||
}
|
||||
|
||||
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
|
||||
{
|
||||
descrip = ENCODE_MENU_STRING (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
|
||||
{
|
||||
descrip = ENCODE_MENU_STRING (descrip);
|
||||
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
wv = xmalloc_widget_value ();
|
||||
if (prev_wv)
|
||||
|
@ -1011,6 +1036,85 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data
|
|||
}
|
||||
#endif /* HAVE_NS */
|
||||
|
||||
int
|
||||
menu_item_width (const char *str)
|
||||
{
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
for (len = 0, p = str; *p; )
|
||||
{
|
||||
int ch_len;
|
||||
int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
|
||||
|
||||
len += CHAR_WIDTH (ch);
|
||||
p += ch_len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
DEFUN ("menu-bar-menu-at-x-y", Fmenu_bar_menu_at_x_y, Smenu_bar_menu_at_x_y,
|
||||
2, 3, 0,
|
||||
doc: /* Return the menu-bar menu on FRAME at pixel coordinates X, Y.
|
||||
X and Y are frame-relative pixel coordinates, assumed to define
|
||||
a location within the menu bar.
|
||||
If FRAME is nil or omitted, it defaults to the selected frame.
|
||||
|
||||
Value is the symbol of the menu at X/Y, or nil if the specified
|
||||
coordinates are not within the FRAME's menu bar. The symbol can
|
||||
be used to look up the menu like this:
|
||||
|
||||
(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,
|
||||
Emacs does not manage the menu bar and cannot convert coordinates
|
||||
into menu items. */)
|
||||
(Lisp_Object x, Lisp_Object y, Lisp_Object frame)
|
||||
{
|
||||
int row, col;
|
||||
struct frame *f = decode_any_frame (frame);
|
||||
|
||||
if (!FRAME_LIVE_P (f))
|
||||
return Qnil;
|
||||
|
||||
pixel_to_glyph_coords (f, XINT (x), XINT (y), &col, &row, NULL, 1);
|
||||
if (0 <= row && row < FRAME_MENU_BAR_LINES (f))
|
||||
{
|
||||
Lisp_Object items, item;
|
||||
int i;
|
||||
|
||||
/* Find the menu bar item under `col'. */
|
||||
item = Qnil;
|
||||
items = FRAME_MENU_BAR_ITEMS (f);
|
||||
/* This loop assumes a single menu-bar line, and will fail to
|
||||
find an item if it is not in the first line. Note that
|
||||
make_lispy_event in keyboard.c makes the same assumption. */
|
||||
for (i = 0; i < ASIZE (items); i += 4)
|
||||
{
|
||||
Lisp_Object pos, str;
|
||||
|
||||
str = AREF (items, i + 1);
|
||||
pos = AREF (items, i + 3);
|
||||
if (NILP (str))
|
||||
return item;
|
||||
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) + menu_item_width (SSDATA (str)))
|
||||
{
|
||||
item = AREF (items, i);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
|
||||
doc: /* Pop up a deck-of-cards menu and return user's selection.
|
||||
POSITION is a position specification. This is either a mouse button event
|
||||
|
@ -1056,7 +1160,7 @@ event (indicating that the user invoked the menu with the mouse) then
|
|||
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;
|
||||
|
@ -1065,6 +1169,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
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;
|
||||
|
||||
|
@ -1077,8 +1182,6 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
{
|
||||
bool get_current_pos_p = 0;
|
||||
|
||||
check_window_system (SELECTED_FRAME ());
|
||||
|
||||
/* Decode the first argument: find the window and the coordinates. */
|
||||
if (EQ (position, Qt)
|
||||
|| (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
|
||||
|
@ -1100,6 +1203,22 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
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);
|
||||
|
@ -1194,11 +1313,6 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
xpos += XINT (x);
|
||||
ypos += XINT (y);
|
||||
|
||||
/* FIXME: Find a more general check! */
|
||||
if (!(FRAME_X_P (f) || FRAME_MSDOS_P (f)
|
||||
|| FRAME_W32_P (f) || FRAME_NS_P (f)))
|
||||
error ("Can not put GUI menu on this terminal");
|
||||
|
||||
XSETFRAME (Vmenu_updating_frame, f);
|
||||
}
|
||||
#endif /* HAVE_MENUS */
|
||||
|
@ -1287,7 +1401,8 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
#ifdef HAVE_MENUS
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
/* Hide a previous tip, if any. */
|
||||
Fx_hide_tip ();
|
||||
if (!FRAME_TERMCAP_P (f))
|
||||
Fx_hide_tip ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */
|
||||
|
@ -1296,7 +1411,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
can occur if you press ESC or click outside a menu without selecting
|
||||
a menu item.
|
||||
*/
|
||||
if (current_popup_menu)
|
||||
if (current_popup_menu && FRAME_W32_P (f))
|
||||
{
|
||||
discard_menu_items ();
|
||||
FRAME_DISPLAY_INFO (f)->grabbed = 0;
|
||||
|
@ -1310,26 +1425,34 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
#endif
|
||||
|
||||
/* Display them in a menu. */
|
||||
block_input ();
|
||||
|
||||
/* FIXME: Use a terminal hook! */
|
||||
#if defined HAVE_NTGUI
|
||||
selection = w32_menu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name);
|
||||
#elif defined HAVE_NS
|
||||
selection = ns_menu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name);
|
||||
#else /* MSDOS and X11 */
|
||||
if (FRAME_W32_P (f))
|
||||
selection = w32_menu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name);
|
||||
else
|
||||
#endif
|
||||
#if defined HAVE_NS
|
||||
if (FRAME_NS_P (f))
|
||||
selection = ns_menu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name);
|
||||
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). */
|
||||
selection = xmenu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name,
|
||||
last_event_timestamp);
|
||||
if (FRAME_X_P (f) || FRAME_MSDOS_P (f))
|
||||
selection = xmenu_show (f, xpos, ypos, for_click,
|
||||
keymaps, title, &error_name,
|
||||
last_event_timestamp);
|
||||
else
|
||||
#endif
|
||||
|
||||
unblock_input ();
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
selection = tty_menu_show (f, xpos, ypos, for_click, keymaps, title,
|
||||
kbd_menu_navigation, &error_name);
|
||||
|
||||
#ifdef HAVE_NS
|
||||
unbind_to (specpdl_count, Qnil);
|
||||
|
@ -1338,7 +1461,8 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */
|
||||
FRAME_DISPLAY_INFO (f)->grabbed = 0;
|
||||
if (FRAME_W32_P (f))
|
||||
FRAME_DISPLAY_INFO (f)->grabbed = 0;
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_MENUS */
|
||||
|
@ -1349,6 +1473,145 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
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.
|
||||
This is normally a mouse button event or a window or frame.
|
||||
If POSITION is t, it means to use the frame the mouse is on.
|
||||
The dialog box appears in the middle of the specified frame.
|
||||
|
||||
CONTENTS specifies the alternatives to display in the dialog box.
|
||||
It is a list of the form (DIALOG ITEM1 ITEM2...).
|
||||
Each ITEM is a cons cell (STRING . VALUE).
|
||||
The return value is VALUE from the chosen item.
|
||||
|
||||
An ITEM may also be just a string--that makes a nonselectable item.
|
||||
An ITEM may also be nil--that means to put all preceding items
|
||||
on the left of the dialog box and all following items on the right.
|
||||
\(By default, approximately half appear on each side.)
|
||||
|
||||
If HEADER is non-nil, the frame title for the box is "Information",
|
||||
otherwise it is "Question".
|
||||
|
||||
If the user gets rid of the dialog box without making a valid choice,
|
||||
for instance using the window manager, then this produces a quit and
|
||||
`x-popup-dialog' does not return. */)
|
||||
(Lisp_Object position, Lisp_Object contents, Lisp_Object header)
|
||||
{
|
||||
struct frame *f = NULL;
|
||||
Lisp_Object window;
|
||||
|
||||
/* Decode the first argument: find the window or frame to use. */
|
||||
if (EQ (position, Qt)
|
||||
|| (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
|
||||
|| EQ (XCAR (position), Qtool_bar))))
|
||||
{
|
||||
#if 0 /* Using the frame the mouse is on may not be right. */
|
||||
/* Use the mouse's current position. */
|
||||
struct frame *new_f = SELECTED_FRAME ();
|
||||
Lisp_Object bar_window;
|
||||
enum scroll_bar_part part;
|
||||
Time time;
|
||||
Lisp_Object x, y;
|
||||
|
||||
(*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
|
||||
|
||||
if (new_f != 0)
|
||||
XSETFRAME (window, new_f);
|
||||
else
|
||||
window = selected_window;
|
||||
#endif
|
||||
window = selected_window;
|
||||
}
|
||||
else if (CONSP (position))
|
||||
{
|
||||
Lisp_Object tem = XCAR (position);
|
||||
if (CONSP (tem))
|
||||
window = Fcar (XCDR (position));
|
||||
else
|
||||
{
|
||||
tem = Fcar (XCDR (position)); /* EVENT_START (position) */
|
||||
window = Fcar (tem); /* POSN_WINDOW (tem) */
|
||||
}
|
||||
}
|
||||
else if (WINDOWP (position) || FRAMEP (position))
|
||||
window = position;
|
||||
else
|
||||
window = Qnil;
|
||||
|
||||
/* Decode where to put the menu. */
|
||||
|
||||
if (FRAMEP (window))
|
||||
f = XFRAME (window);
|
||||
else if (WINDOWP (window))
|
||||
{
|
||||
CHECK_LIVE_WINDOW (window);
|
||||
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
|
||||
}
|
||||
else
|
||||
/* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
|
||||
but I don't want to make one now. */
|
||||
CHECK_WINDOW (window);
|
||||
|
||||
/* Force a redisplay before showing the dialog. If a frame is created
|
||||
just before showing the dialog, its contents may not have been fully
|
||||
drawn, as this depends on timing of events from the X server. Redisplay
|
||||
is not done when a dialog is shown. If redisplay could be done in the
|
||||
X event loop (i.e. the X event loop does not run in a signal handler)
|
||||
this would not be needed.
|
||||
|
||||
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 (FRAME_WINDOW_P (f))
|
||||
return xw_popup_dialog (f, header, contents);
|
||||
else
|
||||
#endif
|
||||
#if defined (HAVE_NTGUI) && defined (HAVE_DIALOGS)
|
||||
if (FRAME_W32_P (f))
|
||||
return w32_popup_dialog (f, header, contents);
|
||||
else
|
||||
#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. */
|
||||
{
|
||||
Lisp_Object x, y, frame, newpos, prompt;
|
||||
int x_coord, y_coord;
|
||||
|
||||
prompt = Fcar (contents);
|
||||
if (FRAME_WINDOW_P (f))
|
||||
{
|
||||
x_coord = FRAME_PIXEL_WIDTH (f);
|
||||
y_coord = FRAME_PIXEL_HEIGHT (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
x_coord = FRAME_COLS (f);
|
||||
/* Center the title at frame middle. (TTY menus have their
|
||||
upper-left corner at the given position.) */
|
||||
if (STRINGP (prompt))
|
||||
x_coord -= SCHARS (prompt);
|
||||
y_coord = FRAME_LINES (f);
|
||||
}
|
||||
XSETFRAME (frame, f);
|
||||
XSETINT (x, x_coord / 2);
|
||||
XSETINT (y, y_coord / 2);
|
||||
newpos = list2 (list2 (x, y), frame);
|
||||
|
||||
return Fx_popup_menu (newpos, list2 (prompt, contents));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_MENUS */
|
||||
|
||||
void
|
||||
syms_of_menu (void)
|
||||
{
|
||||
|
@ -1357,4 +1620,9 @@ 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);
|
||||
}
|
||||
|
|
|
@ -51,4 +51,7 @@ extern Lisp_Object ns_menu_show (struct frame *, int, int, bool, bool,
|
|||
Lisp_Object, const char **);
|
||||
extern Lisp_Object xmenu_show (struct frame *, int, int, bool, bool,
|
||||
Lisp_Object, const char **, Time);
|
||||
extern Lisp_Object tty_menu_show (struct frame *, int, int, int, int,
|
||||
Lisp_Object, int, const char **);
|
||||
extern int menu_item_width (const char *);
|
||||
#endif /* MENU_H */
|
||||
|
|
|
@ -1379,13 +1379,6 @@ IT_delete_glyphs (struct frame *f, int n)
|
|||
emacs_abort ();
|
||||
}
|
||||
|
||||
/* set-window-configuration on window.c needs this. */
|
||||
void
|
||||
x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
|
||||
{
|
||||
set_menu_bar_lines (f, value, oldval);
|
||||
}
|
||||
|
||||
/* This was copied from xfaces.c */
|
||||
|
||||
extern Lisp_Object Qbackground_color;
|
||||
|
|
34
src/nsmenu.m
34
src/nsmenu.m
|
@ -833,6 +833,8 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
|
|||
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
|
||||
widget_value *wv, *first_wv = 0;
|
||||
|
||||
block_input ();
|
||||
|
||||
p.x = x; p.y = y;
|
||||
|
||||
/* now parse stage 2 as in ns_update_menubar */
|
||||
|
@ -1035,6 +1037,7 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
|
|||
popup_activated_flag = 0;
|
||||
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
|
||||
|
||||
unblock_input ();
|
||||
return tem;
|
||||
}
|
||||
|
||||
|
@ -1449,7 +1452,7 @@ - (NSRect) frame
|
|||
|
||||
|
||||
Lisp_Object
|
||||
ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
|
||||
ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents)
|
||||
{
|
||||
id dialog;
|
||||
Lisp_Object window, tem, title;
|
||||
|
@ -1916,34 +1919,6 @@ - (Lisp_Object)runDialogAt: (NSPoint)p
|
|||
}
|
||||
|
||||
|
||||
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.
|
||||
This is normally a mouse button event or a window or frame.
|
||||
If POSITION is t, it means to use the frame the mouse is on.
|
||||
The dialog box appears in the middle of the specified frame.
|
||||
|
||||
CONTENTS specifies the alternatives to display in the dialog box.
|
||||
It is a list of the form (DIALOG ITEM1 ITEM2...).
|
||||
Each ITEM is a cons cell (STRING . VALUE).
|
||||
The return value is VALUE from the chosen item.
|
||||
|
||||
An ITEM may also be just a string--that makes a nonselectable item.
|
||||
An ITEM may also be nil--that means to put all preceding items
|
||||
on the left of the dialog box and all following items on the right.
|
||||
\(By default, approximately half appear on each side.)
|
||||
|
||||
If HEADER is non-nil, the frame title for the box is "Information",
|
||||
otherwise it is "Question".
|
||||
|
||||
If the user gets rid of the dialog box without making a valid choice,
|
||||
for instance using the window manager, then this produces a quit and
|
||||
`x-popup-dialog' does not return. */)
|
||||
(Lisp_Object position, Lisp_Object contents, Lisp_Object header)
|
||||
{
|
||||
return ns_popup_dialog (position, contents, header);
|
||||
}
|
||||
|
||||
DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
|
||||
doc: /* Return t if a menu or popup dialog is active. */)
|
||||
(void)
|
||||
|
@ -1965,7 +1940,6 @@ Each ITEM is a cons cell (STRING . VALUE).
|
|||
update menus there. */
|
||||
trackingMenu = 1;
|
||||
#endif
|
||||
defsubr (&Sx_popup_dialog);
|
||||
defsubr (&Sns_reset_menu);
|
||||
defsubr (&Smenu_or_popup_active_p);
|
||||
|
||||
|
|
|
@ -850,8 +850,8 @@ extern void find_and_call_menu_selection (struct frame *f,
|
|||
extern Lisp_Object find_and_return_menu_selection (struct frame *f,
|
||||
bool keymaps,
|
||||
void *client_data);
|
||||
extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents,
|
||||
Lisp_Object header);
|
||||
extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object header,
|
||||
Lisp_Object contents);
|
||||
|
||||
#define NSAPP_DATA2_RUNASSCRIPT 10
|
||||
extern void ns_run_ascript (void);
|
||||
|
|
1121
src/term.c
1121
src/term.c
File diff suppressed because it is too large
Load diff
|
@ -194,6 +194,9 @@ struct tty_display_info
|
|||
/* Nonzero means use ^S/^Q for flow control. */
|
||||
|
||||
unsigned flow_control : 1;
|
||||
|
||||
/* Non-zero means we are displaying a TTY menu on this tty. */
|
||||
unsigned showing_menu : 1;
|
||||
};
|
||||
|
||||
/* A chain of structures for all tty devices currently in use. */
|
||||
|
|
|
@ -656,6 +656,14 @@ extern unsigned char *encode_terminal_code (struct glyph *, int,
|
|||
extern void close_gpm (int gpm_fd);
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
extern int cursorX (struct tty_display_info *);
|
||||
extern int cursorY (struct tty_display_info *);
|
||||
#else
|
||||
#define cursorX(t) curX(t)
|
||||
#define cursorY(t) curY(t)
|
||||
#endif
|
||||
|
||||
INLINE_HEADER_END
|
||||
|
||||
#endif /* EMACS_TERMHOOKS_H */
|
||||
|
|
|
@ -62,6 +62,7 @@ static HANDLE prev_screen, cur_screen;
|
|||
static WORD char_attr_normal;
|
||||
static DWORD prev_console_mode;
|
||||
|
||||
static CONSOLE_CURSOR_INFO console_cursor_info;
|
||||
#ifndef USE_SEPARATE_SCREEN
|
||||
static CONSOLE_CURSOR_INFO prev_console_cursor;
|
||||
#endif
|
||||
|
@ -95,6 +96,22 @@ w32con_move_cursor (struct frame *f, int row, int col)
|
|||
SetConsoleCursorPosition (cur_screen, cursor_coords);
|
||||
}
|
||||
|
||||
void
|
||||
w32con_hide_cursor (void)
|
||||
{
|
||||
GetConsoleCursorInfo (cur_screen, &console_cursor_info);
|
||||
console_cursor_info.bVisible = FALSE;
|
||||
SetConsoleCursorInfo (cur_screen, &console_cursor_info);
|
||||
}
|
||||
|
||||
void
|
||||
w32con_show_cursor (void)
|
||||
{
|
||||
GetConsoleCursorInfo (cur_screen, &console_cursor_info);
|
||||
console_cursor_info.bVisible = TRUE;
|
||||
SetConsoleCursorInfo (cur_screen, &console_cursor_info);
|
||||
}
|
||||
|
||||
/* Clear from cursor to end of screen. */
|
||||
static void
|
||||
w32con_clear_to_end (struct frame *f)
|
||||
|
@ -552,6 +569,21 @@ Wcm_clear (struct tty_display_info *tty)
|
|||
}
|
||||
|
||||
|
||||
/* Report the current cursor position. The following two functions
|
||||
are used in term.c's tty menu code, so they are not really
|
||||
"stubs". */
|
||||
int
|
||||
cursorX (struct tty_display_info *tty)
|
||||
{
|
||||
return cursor_coords.X;
|
||||
}
|
||||
|
||||
int
|
||||
cursorY (struct tty_display_info *tty)
|
||||
{
|
||||
return cursor_coords.Y;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Faces
|
||||
***********************************************************************/
|
||||
|
|
|
@ -5467,7 +5467,10 @@ show_hourglass (struct atimer *timer)
|
|||
f = SELECTED_FRAME ();
|
||||
|
||||
if (!FRAME_W32_P (f))
|
||||
return;
|
||||
{
|
||||
unblock_input ();
|
||||
return;
|
||||
}
|
||||
|
||||
w32_show_hourglass (f);
|
||||
unblock_input ();
|
||||
|
|
|
@ -712,12 +712,17 @@ w32_console_read_socket (struct terminal *terminal,
|
|||
while (nev > 0)
|
||||
{
|
||||
struct input_event inev;
|
||||
/* Having a separate variable with this value makes
|
||||
debugging easier, as otherwise the compiler might
|
||||
rearrange the switch below in a way that makes it hard to
|
||||
track the event type. */
|
||||
unsigned evtype = queue_ptr->EventType;
|
||||
|
||||
EVENT_INIT (inev);
|
||||
inev.kind = NO_EVENT;
|
||||
inev.arg = Qnil;
|
||||
|
||||
switch (queue_ptr->EventType)
|
||||
switch (evtype)
|
||||
{
|
||||
case KEY_EVENT:
|
||||
add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
|
||||
|
|
147
src/w32menu.c
147
src/w32menu.c
|
@ -115,129 +115,34 @@ static int fill_in_menu (HMENU, widget_value *);
|
|||
void w32_free_menu_strings (HWND);
|
||||
|
||||
#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.
|
||||
This is normally a mouse button event or a window or frame.
|
||||
If POSITION is t, it means to use the frame the mouse is on.
|
||||
The dialog box appears in the middle of the specified frame.
|
||||
|
||||
CONTENTS specifies the alternatives to display in the dialog box.
|
||||
It is a list of the form (TITLE ITEM1 ITEM2...).
|
||||
Each ITEM is a cons cell (STRING . VALUE).
|
||||
The return value is VALUE from the chosen item.
|
||||
|
||||
An ITEM may also be just a string--that makes a nonselectable item.
|
||||
An ITEM may also be nil--that means to put all preceding items
|
||||
on the left of the dialog box and all following items on the right.
|
||||
\(By default, approximately half appear on each side.)
|
||||
|
||||
If HEADER is non-nil, the frame title for the box is "Information",
|
||||
otherwise it is "Question". */)
|
||||
(Lisp_Object position, Lisp_Object contents, Lisp_Object header)
|
||||
#ifdef HAVE_DIALOGS
|
||||
Lisp_Object
|
||||
w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
|
||||
{
|
||||
struct frame *f = NULL;
|
||||
Lisp_Object window;
|
||||
|
||||
/* Decode the first argument: find the window or frame to use. */
|
||||
if (EQ (position, Qt)
|
||||
|| (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
|
||||
|| EQ (XCAR (position), Qtool_bar))))
|
||||
{
|
||||
#if 0 /* Using the frame the mouse is on may not be right. */
|
||||
/* Use the mouse's current position. */
|
||||
struct frame *new_f = SELECTED_FRAME ();
|
||||
Lisp_Object bar_window;
|
||||
enum scroll_bar_part part;
|
||||
Time time;
|
||||
Lisp_Object x, y;
|
||||
|
||||
(*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
|
||||
|
||||
if (new_f != 0)
|
||||
XSETFRAME (window, new_f);
|
||||
else
|
||||
window = selected_window;
|
||||
#endif
|
||||
window = selected_window;
|
||||
}
|
||||
else if (CONSP (position))
|
||||
{
|
||||
Lisp_Object tem = XCAR (position);
|
||||
if (CONSP (tem))
|
||||
window = Fcar (XCDR (position));
|
||||
else
|
||||
{
|
||||
tem = Fcar (XCDR (position)); /* EVENT_START (position) */
|
||||
window = Fcar (tem); /* POSN_WINDOW (tem) */
|
||||
}
|
||||
}
|
||||
else if (WINDOWP (position) || FRAMEP (position))
|
||||
window = position;
|
||||
else
|
||||
window = Qnil;
|
||||
|
||||
/* Decode where to put the menu. */
|
||||
|
||||
if (FRAMEP (window))
|
||||
f = XFRAME (window);
|
||||
else if (WINDOWP (window))
|
||||
{
|
||||
CHECK_LIVE_WINDOW (window);
|
||||
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
|
||||
}
|
||||
else
|
||||
/* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
|
||||
but I don't want to make one now. */
|
||||
CHECK_WINDOW (window);
|
||||
Lisp_Object title;
|
||||
char *error_name;
|
||||
Lisp_Object selection;
|
||||
|
||||
check_window_system (f);
|
||||
|
||||
#ifndef HAVE_DIALOGS
|
||||
/* Decode the dialog items from what was specified. */
|
||||
title = Fcar (contents);
|
||||
CHECK_STRING (title);
|
||||
|
||||
{
|
||||
/* Handle simple Yes/No choices as MessageBox popups. */
|
||||
if (is_simple_dialog (contents))
|
||||
return simple_dialog_show (f, contents, header);
|
||||
else
|
||||
{
|
||||
/* Display a menu with these alternatives
|
||||
in the middle of frame F. */
|
||||
Lisp_Object x, y, frame, newpos;
|
||||
XSETFRAME (frame, f);
|
||||
XSETINT (x, FRAME_PIXEL_WIDTH (f) / 2);
|
||||
XSETINT (y, FRAME_PIXEL_HEIGHT (f) / 2);
|
||||
newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
|
||||
return Fx_popup_menu (newpos,
|
||||
Fcons (Fcar (contents), Fcons (contents, Qnil)));
|
||||
}
|
||||
}
|
||||
#else /* HAVE_DIALOGS */
|
||||
{
|
||||
Lisp_Object title;
|
||||
char *error_name;
|
||||
Lisp_Object selection;
|
||||
list_of_panes (Fcons (contents, Qnil));
|
||||
|
||||
/* Decode the dialog items from what was specified. */
|
||||
title = Fcar (contents);
|
||||
CHECK_STRING (title);
|
||||
/* Display them in a dialog box. */
|
||||
block_input ();
|
||||
selection = w32_dialog_show (f, 0, title, header, &error_name);
|
||||
unblock_input ();
|
||||
|
||||
list_of_panes (Fcons (contents, Qnil));
|
||||
discard_menu_items ();
|
||||
FRAME_DISPLAY_INFO (f)->grabbed = 0;
|
||||
|
||||
/* Display them in a dialog box. */
|
||||
block_input ();
|
||||
selection = w32_dialog_show (f, 0, title, header, &error_name);
|
||||
unblock_input ();
|
||||
|
||||
discard_menu_items ();
|
||||
FRAME_DISPLAY_INFO (f)->grabbed = 0;
|
||||
|
||||
if (error_name) error (error_name);
|
||||
return selection;
|
||||
}
|
||||
#endif /* HAVE_DIALOGS */
|
||||
if (error_name) error (error_name);
|
||||
return selection;
|
||||
}
|
||||
#endif /* HAVE_DIALOGS */
|
||||
|
||||
/* Activate the menu bar of frame F.
|
||||
This is called from keyboard.c when it gets the
|
||||
|
@ -682,6 +587,8 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
block_input ();
|
||||
|
||||
/* Create a tree of widget_value objects
|
||||
representing the panes and their items. */
|
||||
wv = xmalloc_widget_value ();
|
||||
|
@ -940,6 +847,7 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
|
|||
if (!NILP (subprefix_stack[j]))
|
||||
entry = Fcons (subprefix_stack[j], entry);
|
||||
}
|
||||
unblock_input ();
|
||||
return entry;
|
||||
}
|
||||
i += MENU_ITEMS_ITEM_LENGTH;
|
||||
|
@ -947,9 +855,13 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
|
|||
}
|
||||
}
|
||||
else if (!for_click)
|
||||
/* Make "Cancel" equivalent to C-g. */
|
||||
Fsignal (Qquit, Qnil);
|
||||
{
|
||||
unblock_input ();
|
||||
/* Make "Cancel" equivalent to C-g. */
|
||||
Fsignal (Qquit, Qnil);
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
@ -1717,9 +1629,6 @@ syms_of_w32menu (void)
|
|||
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
|
||||
|
||||
defsubr (&Smenu_or_popup_active_p);
|
||||
#ifdef HAVE_MENUS
|
||||
defsubr (&Sx_popup_dialog);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -264,6 +264,10 @@ extern int w32_kbd_mods_to_emacs (DWORD mods, WORD key);
|
|||
|
||||
extern Lisp_Object x_get_focus_frame (struct frame *);
|
||||
|
||||
/* w32console.c */
|
||||
extern void w32con_hide_cursor (void);
|
||||
extern void w32con_show_cursor (void);
|
||||
|
||||
|
||||
#define PIX_TYPE COLORREF
|
||||
|
||||
|
@ -794,6 +798,10 @@ typedef char guichar_t;
|
|||
|
||||
#define GUI_SDATA(x) ((guichar_t*) SDATA (x))
|
||||
|
||||
#if defined HAVE_DIALOGS
|
||||
extern Lisp_Object w32_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
|
||||
#endif
|
||||
|
||||
extern void syms_of_w32term (void);
|
||||
extern void syms_of_w32menu (void);
|
||||
extern void syms_of_w32fns (void);
|
||||
|
|
33
src/window.c
33
src/window.c
|
@ -5540,17 +5540,25 @@ the return value is nil. Otherwise the value is t. */)
|
|||
|| data->frame_cols != previous_frame_cols)
|
||||
change_frame_size (f, data->frame_lines,
|
||||
data->frame_cols, 0, 0, 0);
|
||||
#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
|
||||
#ifdef HAVE_MENUS
|
||||
if (data->frame_menu_bar_lines
|
||||
!= previous_frame_menu_bar_lines)
|
||||
x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
{
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (FRAME_WINDOW_P (f))
|
||||
x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
else /* TTY or MSDOS */
|
||||
#endif
|
||||
set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (data->frame_tool_bar_lines
|
||||
!= previous_frame_tool_bar_lines)
|
||||
x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
|
||||
make_number (0));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* "Swap out" point from the selected window's buffer
|
||||
|
@ -5738,15 +5746,24 @@ the return value is nil. Otherwise the value is t. */)
|
|||
|| previous_frame_cols != FRAME_COLS (f))
|
||||
change_frame_size (f, previous_frame_lines, previous_frame_cols,
|
||||
0, 0, 0);
|
||||
#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
|
||||
#ifdef HAVE_MENUS
|
||||
if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
|
||||
x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
{
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (FRAME_WINDOW_P (f))
|
||||
x_set_menu_bar_lines (f,
|
||||
make_number (previous_frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
else /* TTY or MSDOS */
|
||||
#endif
|
||||
set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
|
||||
make_number (0));
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
|
||||
x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
|
||||
make_number (0));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Now, free glyph matrices in windows that were not reused. */
|
||||
|
|
121
src/xdisp.c
121
src/xdisp.c
|
@ -20584,7 +20584,128 @@ display_menu_bar (struct window *w)
|
|||
compute_line_metrics (&it);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENUS
|
||||
/* Deep copy of a glyph row, including the glyphs. */
|
||||
static void
|
||||
deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
|
||||
{
|
||||
int area, i, sum_used = 0;
|
||||
struct glyph *pointers[1 + LAST_AREA];
|
||||
|
||||
/* Save glyph pointers of TO. */
|
||||
memcpy (pointers, to->glyphs, sizeof to->glyphs);
|
||||
|
||||
/* Do a structure assignment. */
|
||||
*to = *from;
|
||||
|
||||
/* Restore original pointers of TO. */
|
||||
memcpy (to->glyphs, pointers, sizeof to->glyphs);
|
||||
|
||||
/* Count how many glyphs to copy and update glyph pointers. */
|
||||
for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
|
||||
{
|
||||
if (area > LEFT_MARGIN_AREA)
|
||||
{
|
||||
eassert (from->glyphs[area] - from->glyphs[area - 1]
|
||||
== from->used[area - 1]);
|
||||
to->glyphs[area] = to->glyphs[area - 1] + to->used[area - 1];
|
||||
}
|
||||
sum_used += from->used[area];
|
||||
}
|
||||
|
||||
/* Copy the glyphs. */
|
||||
eassert (sum_used <= to->glyphs[LAST_AREA] - to->glyphs[LEFT_MARGIN_AREA]);
|
||||
for (i = 0; i < sum_used; i++)
|
||||
to->glyphs[LEFT_MARGIN_AREA][i] = from->glyphs[LEFT_MARGIN_AREA][i];
|
||||
}
|
||||
|
||||
/* Display one menu item on a TTY, by overwriting the glyphs in the
|
||||
frame F's desired glyph matrix with glyphs produced from the menu
|
||||
item text. Called from term.c to display TTY drop-down menus one
|
||||
item at a time.
|
||||
|
||||
ITEM_TEXT is the menu item text as a C string.
|
||||
|
||||
FACE_ID is the face ID to be used for this menu item. FACE_ID
|
||||
could specify one of 3 faces: a face for an enabled item, a face
|
||||
for a disabled item, or a face for a selected item.
|
||||
|
||||
X and Y are coordinates of the first glyph in the frame's desired
|
||||
matrix to be overwritten by the menu item. Since this is a TTY, Y
|
||||
is the zero-based number of the glyph row and X is the zero-based
|
||||
glyph number in the row, starting from left, where to start
|
||||
displaying the item.
|
||||
|
||||
SUBMENU non-zero means this menu item drops down a submenu, which
|
||||
should be indicated by displaying a proper visual cue after the
|
||||
item text. */
|
||||
|
||||
void
|
||||
display_tty_menu_item (const char *item_text, int width, int face_id,
|
||||
int x, int y, int submenu)
|
||||
{
|
||||
struct it it;
|
||||
struct frame *f = SELECTED_FRAME ();
|
||||
struct window *w = XWINDOW (f->selected_window);
|
||||
int saved_used, saved_truncated, saved_width, saved_reversed;
|
||||
struct glyph_row *row;
|
||||
size_t item_len = strlen (item_text);
|
||||
|
||||
eassert (FRAME_TERMCAP_P (f));
|
||||
|
||||
init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
|
||||
it.first_visible_x = 0;
|
||||
it.last_visible_x = FRAME_COLS (f) - 1;
|
||||
row = it.glyph_row;
|
||||
/* Start with the row contents from the current matrix. */
|
||||
deep_copy_glyph_row (row, f->current_matrix->rows + y);
|
||||
saved_width = row->full_width_p;
|
||||
row->full_width_p = 1;
|
||||
saved_reversed = row->reversed_p;
|
||||
row->reversed_p = 0;
|
||||
row->enabled_p = 1;
|
||||
|
||||
/* Arrange for the menu item glyphs to start at (X,Y) and have the
|
||||
desired face. */
|
||||
it.current_x = it.hpos = x;
|
||||
it.current_y = it.vpos = y;
|
||||
saved_used = row->used[TEXT_AREA];
|
||||
saved_truncated = row->truncated_on_right_p;
|
||||
row->used[TEXT_AREA] = x;
|
||||
it.face_id = face_id;
|
||||
it.line_wrap = TRUNCATE;
|
||||
|
||||
/* FIXME: This should be controlled by a user option. See the
|
||||
comments in redisplay_tool_bar and display_mode_line about this.
|
||||
Also, if paragraph_embedding could ever be R2L, changes will be
|
||||
needed to avoid shifting to the right the row characters in
|
||||
term.c:append_glyph. */
|
||||
it.paragraph_embedding = L2R;
|
||||
|
||||
/* Pad with a space on the left. */
|
||||
display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
|
||||
width--;
|
||||
/* Display the menu item, pad with spaces to WIDTH. */
|
||||
if (submenu)
|
||||
{
|
||||
display_string (item_text, Qnil, Qnil, 0, 0, &it,
|
||||
item_len, 0, FRAME_COLS (f) - 1, -1);
|
||||
width -= item_len;
|
||||
/* Indicate with " >" that there's a submenu. */
|
||||
display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
|
||||
FRAME_COLS (f) - 1, -1);
|
||||
}
|
||||
else
|
||||
display_string (item_text, Qnil, Qnil, 0, 0, &it,
|
||||
width, 0, FRAME_COLS (f) - 1, -1);
|
||||
|
||||
row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
|
||||
row->truncated_on_right_p = saved_truncated;
|
||||
row->hash = row_hash (row);
|
||||
row->full_width_p = saved_width;
|
||||
row->reversed_p = saved_reversed;
|
||||
}
|
||||
#endif /* HAVE_MENUS */
|
||||
|
||||
/***********************************************************************
|
||||
Mode Line
|
||||
|
|
206
src/xmenu.c
206
src/xmenu.c
|
@ -192,149 +192,6 @@ mouse_position_for_popup (struct frame *f, int *x, int *y)
|
|||
|
||||
#endif /* HAVE_X_WINDOWS */
|
||||
|
||||
#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.
|
||||
This is normally a mouse button event or a window or frame.
|
||||
If POSITION is t, it means to use the frame the mouse is on.
|
||||
The dialog box appears in the middle of the specified frame.
|
||||
|
||||
CONTENTS specifies the alternatives to display in the dialog box.
|
||||
It is a list of the form (DIALOG ITEM1 ITEM2...).
|
||||
Each ITEM is a cons cell (STRING . VALUE).
|
||||
The return value is VALUE from the chosen item.
|
||||
|
||||
An ITEM may also be just a string--that makes a nonselectable item.
|
||||
An ITEM may also be nil--that means to put all preceding items
|
||||
on the left of the dialog box and all following items on the right.
|
||||
\(By default, approximately half appear on each side.)
|
||||
|
||||
If HEADER is non-nil, the frame title for the box is "Information",
|
||||
otherwise it is "Question".
|
||||
|
||||
If the user gets rid of the dialog box without making a valid choice,
|
||||
for instance using the window manager, then this produces a quit and
|
||||
`x-popup-dialog' does not return. */)
|
||||
(Lisp_Object position, Lisp_Object contents, Lisp_Object header)
|
||||
{
|
||||
struct frame *f = NULL;
|
||||
Lisp_Object window;
|
||||
|
||||
/* Decode the first argument: find the window or frame to use. */
|
||||
if (EQ (position, Qt)
|
||||
|| (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
|
||||
|| EQ (XCAR (position), Qtool_bar))))
|
||||
{
|
||||
#if 0 /* Using the frame the mouse is on may not be right. */
|
||||
/* Use the mouse's current position. */
|
||||
struct frame *new_f = SELECTED_FRAME ();
|
||||
Lisp_Object bar_window;
|
||||
enum scroll_bar_part part;
|
||||
Time time;
|
||||
Lisp_Object x, y;
|
||||
|
||||
(*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
|
||||
|
||||
if (new_f != 0)
|
||||
XSETFRAME (window, new_f);
|
||||
else
|
||||
window = selected_window;
|
||||
#endif
|
||||
window = selected_window;
|
||||
}
|
||||
else if (CONSP (position))
|
||||
{
|
||||
Lisp_Object tem = XCAR (position);
|
||||
if (CONSP (tem))
|
||||
window = Fcar (XCDR (position));
|
||||
else
|
||||
{
|
||||
tem = Fcar (XCDR (position)); /* EVENT_START (position) */
|
||||
window = Fcar (tem); /* POSN_WINDOW (tem) */
|
||||
}
|
||||
}
|
||||
else if (WINDOWP (position) || FRAMEP (position))
|
||||
window = position;
|
||||
else
|
||||
window = Qnil;
|
||||
|
||||
/* Decode where to put the menu. */
|
||||
|
||||
if (FRAMEP (window))
|
||||
f = XFRAME (window);
|
||||
else if (WINDOWP (window))
|
||||
{
|
||||
CHECK_LIVE_WINDOW (window);
|
||||
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
|
||||
}
|
||||
else
|
||||
/* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
|
||||
but I don't want to make one now. */
|
||||
CHECK_WINDOW (window);
|
||||
|
||||
check_window_system (f);
|
||||
|
||||
/* Force a redisplay before showing the dialog. If a frame is created
|
||||
just before showing the dialog, its contents may not have been fully
|
||||
drawn, as this depends on timing of events from the X server. Redisplay
|
||||
is not done when a dialog is shown. If redisplay could be done in the
|
||||
X event loop (i.e. the X event loop does not run in a signal handler)
|
||||
this would not be needed.
|
||||
|
||||
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)
|
||||
/* Display a menu with these alternatives
|
||||
in the middle of frame F. */
|
||||
{
|
||||
Lisp_Object x, y, frame, newpos;
|
||||
XSETFRAME (frame, f);
|
||||
XSETINT (x, FRAME_PIXEL_WIDTH (f) / 2);
|
||||
XSETINT (y, FRAME_PIXEL_HEIGHT (f) / 2);
|
||||
newpos = list2 (list2 (x, y), frame);
|
||||
|
||||
return Fx_popup_menu (newpos,
|
||||
list2 (Fcar (contents), contents));
|
||||
}
|
||||
#else
|
||||
{
|
||||
Lisp_Object title;
|
||||
const char *error_name;
|
||||
Lisp_Object selection;
|
||||
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
|
||||
|
||||
/* Decode the dialog items from what was specified. */
|
||||
title = Fcar (contents);
|
||||
CHECK_STRING (title);
|
||||
record_unwind_protect_void (unuse_menu_items);
|
||||
|
||||
if (NILP (Fcar (Fcdr (contents))))
|
||||
/* No buttons specified, add an "Ok" button so users can pop down
|
||||
the dialog. Also, the lesstif/motif version crashes if there are
|
||||
no buttons. */
|
||||
contents = list2 (title, Fcons (build_string ("Ok"), Qt));
|
||||
|
||||
list_of_panes (list1 (contents));
|
||||
|
||||
/* Display them in a dialog box. */
|
||||
block_input ();
|
||||
selection = xdialog_show (f, 0, title, header, &error_name);
|
||||
unblock_input ();
|
||||
|
||||
unbind_to (specpdl_count, Qnil);
|
||||
discard_menu_items ();
|
||||
|
||||
if (error_name) error ("%s", error_name);
|
||||
return selection;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef MSDOS
|
||||
|
||||
#if defined USE_GTK || defined USE_MOTIF
|
||||
|
@ -1618,6 +1475,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
block_input ();
|
||||
|
||||
/* Create a tree of widget_value objects
|
||||
representing the panes and their items. */
|
||||
wv = xmalloc_widget_value ();
|
||||
|
@ -1857,6 +1716,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
if (!NILP (subprefix_stack[j]))
|
||||
entry = Fcons (subprefix_stack[j], entry);
|
||||
}
|
||||
unblock_input ();
|
||||
return entry;
|
||||
}
|
||||
i += MENU_ITEMS_ITEM_LENGTH;
|
||||
|
@ -1864,9 +1724,13 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
}
|
||||
}
|
||||
else if (!for_click)
|
||||
/* Make "Cancel" equivalent to C-g. */
|
||||
Fsignal (Qquit, Qnil);
|
||||
{
|
||||
unblock_input ();
|
||||
/* Make "Cancel" equivalent to C-g. */
|
||||
Fsignal (Qquit, Qnil);
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
@ -2163,6 +2027,41 @@ xdialog_show (struct frame *f,
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
|
||||
{
|
||||
Lisp_Object title;
|
||||
const char *error_name;
|
||||
Lisp_Object selection;
|
||||
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
|
||||
|
||||
check_window_system (f);
|
||||
|
||||
/* Decode the dialog items from what was specified. */
|
||||
title = Fcar (contents);
|
||||
CHECK_STRING (title);
|
||||
record_unwind_protect_void (unuse_menu_items);
|
||||
|
||||
if (NILP (Fcar (Fcdr (contents))))
|
||||
/* No buttons specified, add an "Ok" button so users can pop down
|
||||
the dialog. Also, the lesstif/motif version crashes if there are
|
||||
no buttons. */
|
||||
contents = list2 (title, Fcons (build_string ("Ok"), Qt));
|
||||
|
||||
list_of_panes (list1 (contents));
|
||||
|
||||
/* Display them in a dialog box. */
|
||||
block_input ();
|
||||
selection = xdialog_show (f, 0, title, header, &error_name);
|
||||
unblock_input ();
|
||||
|
||||
unbind_to (specpdl_count, Qnil);
|
||||
discard_menu_items ();
|
||||
|
||||
if (error_name) error ("%s", error_name);
|
||||
return selection;
|
||||
}
|
||||
|
||||
#else /* not USE_X_TOOLKIT && not USE_GTK */
|
||||
|
||||
/* The frame of the last activated non-toolkit menu bar.
|
||||
|
@ -2261,6 +2160,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
block_input ();
|
||||
|
||||
/* Figure out which root window F is on. */
|
||||
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
|
||||
&dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
|
||||
|
@ -2271,6 +2172,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;
|
||||
}
|
||||
|
||||
|
@ -2314,6 +2216,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;
|
||||
}
|
||||
i += MENU_ITEMS_PANE_LENGTH;
|
||||
|
@ -2378,6 +2281,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;
|
||||
}
|
||||
i += MENU_ITEMS_ITEM_LENGTH;
|
||||
|
@ -2504,10 +2408,14 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
/* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
|
||||
the menu was invoked with a mouse event as POSITION). */
|
||||
if (! for_click)
|
||||
Fsignal (Qquit, Qnil);
|
||||
{
|
||||
unblock_input ();
|
||||
Fsignal (Qquit, Qnil);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
unbind_to (specpdl_count, Qnil);
|
||||
|
||||
return entry;
|
||||
|
@ -2515,8 +2423,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
|
|||
|
||||
#endif /* not USE_X_TOOLKIT */
|
||||
|
||||
#endif /* HAVE_MENUS */
|
||||
|
||||
#ifndef MSDOS
|
||||
/* Detect if a dialog or menu has been posted. MSDOS has its own
|
||||
implementation on msdos.c. */
|
||||
|
@ -2558,8 +2464,4 @@ syms_of_xmenu (void)
|
|||
Ffset (intern_c_string ("accelerate-menu"),
|
||||
intern_c_string (Sx_menu_bar_open_internal.symbol_name));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENUS
|
||||
defsubr (&Sx_popup_dialog);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1035,6 +1035,10 @@ extern void x_free_dpy_colors (Display *, Screen *, Colormap,
|
|||
|
||||
/* Defined in xmenu.c */
|
||||
|
||||
#if defined USE_X_TOOLKIT || defined USE_GTK
|
||||
extern Lisp_Object xw_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
|
||||
#endif
|
||||
|
||||
#if defined USE_GTK || defined USE_MOTIF
|
||||
extern void x_menu_set_in_use (int);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue