For help commands, ensure all keys of a mouse sequence are reported.
This solves the problem where read_key_sequence initializes and uses a global buffer raw_keybuf, yet is called recusrsively. The initialization is now done elsewhere, avoiding the reinitialization of that global buffer. * src/keyboard.c (command_loop_1, read_key_sequence_vs): Initialize raw_event_count before calling read_key_sequence. (read_char_x_menu_prompt): Call x_popup_menu_1 in place of Fx_popup_menu. (init_raw_keybuf_count): New function. (read_key_sequence): Remove initialization of raw_event_count. Add a missing GROW_RAW_KEYBUF invocation. * src/keyboard.h: (init_raw_keybuf_count): New declaration. * src/menu.c: (x_popup_menu_1): New function with the functionality of the former Fx_popup_menu. (Fx_popup_menu): Replace with function which initializes raw_event_count then calls x_popup_menu_1. * src/menu.h: (x_popup_menu_1): New declaration.
This commit is contained in:
parent
4856ee1717
commit
bc092fcaea
4 changed files with 84 additions and 88 deletions
|
@ -43,6 +43,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "systime.h"
|
||||
#include "atimer.h"
|
||||
#include "process.h"
|
||||
#include "menu.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
|
@ -121,17 +122,12 @@ ptrdiff_t this_command_key_count;
|
|||
|
||||
/* This vector is used as a buffer to record the events that were actually read
|
||||
by read_key_sequence. */
|
||||
static Lisp_Object raw_keybuf_buffer;
|
||||
static int raw_keybuf_count_buffer;
|
||||
static Lisp_Object *raw_keybuf = &raw_keybuf_buffer;
|
||||
static int *raw_keybuf_count = &raw_keybuf_count_buffer;
|
||||
static Lisp_Object raw_keybuf;
|
||||
static int raw_keybuf_count;
|
||||
|
||||
#define GROW_RAW_KEYBUF(inc) \
|
||||
if (*raw_keybuf_count > ASIZE (*raw_keybuf) - (inc)) \
|
||||
*raw_keybuf = \
|
||||
larger_vector (*raw_keybuf, \
|
||||
(inc) + *raw_keybuf_count - ASIZE (*raw_keybuf), \
|
||||
-1)
|
||||
#define GROW_RAW_KEYBUF \
|
||||
if (raw_keybuf_count == ASIZE (raw_keybuf)) \
|
||||
raw_keybuf = larger_vector (raw_keybuf, 1, -1)
|
||||
|
||||
/* Number of elements of this_command_keys
|
||||
that precede this key sequence. */
|
||||
|
@ -1370,8 +1366,7 @@ command_loop_1 (void)
|
|||
Vthis_command_keys_shift_translated = Qnil;
|
||||
|
||||
/* Read next key sequence; i gets its length. */
|
||||
raw_keybuf_count = &raw_keybuf_count_buffer; /* For safety */
|
||||
raw_keybuf = &raw_keybuf_buffer; /* Ditto */
|
||||
raw_keybuf_count = 0;
|
||||
i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
|
||||
Qnil, 0, 1, 1, 0);
|
||||
|
||||
|
@ -8460,7 +8455,7 @@ read_char_x_menu_prompt (Lisp_Object map,
|
|||
/* Display the menu and get the selection. */
|
||||
Lisp_Object value;
|
||||
|
||||
value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1));
|
||||
value = x_popup_menu_1 (prev_event, get_keymap (map, 0, 1));
|
||||
if (CONSP (value))
|
||||
{
|
||||
Lisp_Object tem;
|
||||
|
@ -8870,6 +8865,11 @@ test_undefined (Lisp_Object binding)
|
|||
&& EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined)));
|
||||
}
|
||||
|
||||
void init_raw_keybuf_count (void)
|
||||
{
|
||||
raw_keybuf_count = 0;
|
||||
}
|
||||
|
||||
/* Read a sequence of keys that ends with a non prefix character,
|
||||
storing it in KEYBUF, a buffer of size BUFSIZE.
|
||||
Prompt with PROMPT.
|
||||
|
@ -8920,11 +8920,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
/* How many keys there are in the current key sequence. */
|
||||
int t;
|
||||
|
||||
int *outer_raw_keybuf_count;
|
||||
Lisp_Object *outer_raw_keybuf;
|
||||
int inner_raw_keybuf_count_buffer;
|
||||
Lisp_Object inner_raw_keybuf_buffer = Fmake_vector (make_number (30), Qnil);
|
||||
|
||||
/* The length of the echo buffer when we started reading, and
|
||||
the length of this_command_keys when we started reading. */
|
||||
ptrdiff_t echo_start UNINIT;
|
||||
|
@ -8985,7 +8980,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
/* List of events for which a fake prefix key has been generated. */
|
||||
Lisp_Object fake_prefixed_keys = Qnil;
|
||||
|
||||
*raw_keybuf_count = 0;
|
||||
/* raw_keybuf_count is now initialized in (most of) the callers of
|
||||
read_key_sequence. This is so that in a recursive call (for
|
||||
mouse menus) a spurious initialization doesn't erase the contents
|
||||
of raw_keybuf created by the outer call. */
|
||||
/* raw_keybuf_count = 0; */
|
||||
|
||||
last_nonmenu_event = Qnil;
|
||||
|
||||
|
@ -9157,23 +9156,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
{
|
||||
KBOARD *interrupted_kboard = current_kboard;
|
||||
struct frame *interrupted_frame = SELECTED_FRAME ();
|
||||
int i;
|
||||
outer_raw_keybuf_count = raw_keybuf_count;
|
||||
outer_raw_keybuf = raw_keybuf;
|
||||
inner_raw_keybuf_count_buffer = 0;
|
||||
raw_keybuf_count = &inner_raw_keybuf_count_buffer;
|
||||
raw_keybuf = &inner_raw_keybuf_buffer;
|
||||
/* 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);
|
||||
raw_keybuf_count = outer_raw_keybuf_count;
|
||||
raw_keybuf = outer_raw_keybuf;
|
||||
GROW_RAW_KEYBUF (inner_raw_keybuf_count_buffer);
|
||||
for (i = 0; i < inner_raw_keybuf_count_buffer; i++)
|
||||
ASET (*raw_keybuf, (*raw_keybuf_count)++,
|
||||
AREF (inner_raw_keybuf_buffer, i));
|
||||
if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
|
||||
/* When switching to a new tty (with a new keyboard),
|
||||
read_char returns the new buffer, rather than -2
|
||||
|
@ -9281,9 +9268,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
&& XINT (key) == quit_char
|
||||
&& current_buffer != starting_buffer)
|
||||
{
|
||||
GROW_RAW_KEYBUF (1);
|
||||
ASET (*raw_keybuf, *raw_keybuf_count, key);
|
||||
(*raw_keybuf_count)++;
|
||||
GROW_RAW_KEYBUF;
|
||||
ASET (raw_keybuf, raw_keybuf_count, key);
|
||||
raw_keybuf_count++;
|
||||
keybuf[t++] = key;
|
||||
mock_input = t;
|
||||
Vquit_flag = Qnil;
|
||||
|
@ -9322,9 +9309,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
current_binding = active_maps (first_event);
|
||||
}
|
||||
|
||||
GROW_RAW_KEYBUF (1);
|
||||
ASET (*raw_keybuf, *raw_keybuf_count, key);
|
||||
(*raw_keybuf_count)++;
|
||||
GROW_RAW_KEYBUF;
|
||||
ASET (raw_keybuf, raw_keybuf_count, key);
|
||||
raw_keybuf_count++;
|
||||
}
|
||||
|
||||
/* Clicks in non-text areas get prefixed by the symbol
|
||||
|
@ -9370,9 +9357,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
|
|||
&& BUFFERP (XWINDOW (window)->contents)
|
||||
&& XBUFFER (XWINDOW (window)->contents) != current_buffer)
|
||||
{
|
||||
GROW_RAW_KEYBUF (1);
|
||||
ASET (*raw_keybuf, *raw_keybuf_count, key);
|
||||
(*raw_keybuf_count)++;
|
||||
GROW_RAW_KEYBUF;
|
||||
ASET (raw_keybuf, raw_keybuf_count, key);
|
||||
raw_keybuf_count++;
|
||||
keybuf[t] = key;
|
||||
mock_input = t + 1;
|
||||
|
||||
|
@ -9865,6 +9852,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
|
|||
cancel_hourglass ();
|
||||
#endif
|
||||
|
||||
raw_keybuf_count = 0;
|
||||
i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
|
||||
prompt, ! NILP (dont_downcase_last),
|
||||
! NILP (can_return_switch_frame), 0, 0);
|
||||
|
@ -10145,7 +10133,7 @@ shows the events before all translations (except for input methods).
|
|||
The value is always a vector. */)
|
||||
(void)
|
||||
{
|
||||
return Fvector (*raw_keybuf_count, XVECTOR (*raw_keybuf)->contents);
|
||||
return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->contents);
|
||||
}
|
||||
|
||||
DEFUN ("clear-this-command-keys", Fclear_this_command_keys,
|
||||
|
@ -11290,8 +11278,8 @@ syms_of_keyboard (void)
|
|||
this_command_keys = Fmake_vector (make_number (40), Qnil);
|
||||
staticpro (&this_command_keys);
|
||||
|
||||
raw_keybuf_buffer = Fmake_vector (make_number (30), Qnil);
|
||||
staticpro (raw_keybuf);
|
||||
raw_keybuf = Fmake_vector (make_number (30), Qnil);
|
||||
staticpro (&raw_keybuf);
|
||||
|
||||
DEFSYM (Qcommand_execute, "command-execute");
|
||||
DEFSYM (Qinternal_echo_keystrokes_prefix, "internal-echo-keystrokes-prefix");
|
||||
|
|
|
@ -438,6 +438,7 @@ extern unsigned int timers_run;
|
|||
extern bool menu_separator_name_p (const char *);
|
||||
extern bool parse_menu_item (Lisp_Object, int);
|
||||
|
||||
extern void init_raw_keybuf_count (void);
|
||||
extern KBOARD *allocate_kboard (Lisp_Object);
|
||||
extern void delete_kboard (KBOARD *);
|
||||
extern void not_single_kboard_state (KBOARD *);
|
||||
|
|
96
src/menu.c
96
src/menu.c
|
@ -1112,51 +1112,8 @@ into menu items. */)
|
|||
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
|
||||
or a list ((XOFFSET YOFFSET) WINDOW)
|
||||
where XOFFSET and YOFFSET are positions in pixels from the top left
|
||||
corner of WINDOW. (WINDOW may be a window or a frame object.)
|
||||
This controls the position of the top left of the menu as a whole.
|
||||
If POSITION is t, it means to use the current mouse position.
|
||||
|
||||
MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
|
||||
The menu items come from key bindings that have a menu string as well as
|
||||
a definition; actually, the "definition" in such a key binding looks like
|
||||
\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
|
||||
the keymap as a top-level element.
|
||||
|
||||
If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
|
||||
Otherwise, REAL-DEFINITION should be a valid key binding definition.
|
||||
|
||||
You can also use a list of keymaps as MENU.
|
||||
Then each keymap makes a separate pane.
|
||||
|
||||
When MENU is a keymap or a list of keymaps, the return value is the
|
||||
list of events corresponding to the user's choice. Note that
|
||||
`x-popup-menu' does not actually execute the command bound to that
|
||||
sequence of events.
|
||||
|
||||
Alternatively, you can specify a menu of multiple panes
|
||||
with a list of the form (TITLE PANE1 PANE2...),
|
||||
where each pane is a list of form (TITLE ITEM1 ITEM2...).
|
||||
Each ITEM is normally a cons cell (STRING . VALUE);
|
||||
but a string can appear as an item--that makes a nonselectable line
|
||||
in the menu.
|
||||
With this form of menu, the return value is VALUE from the chosen item.
|
||||
|
||||
If POSITION is nil, don't display the menu at all, just precalculate the
|
||||
cached information about equivalent key sequences.
|
||||
|
||||
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
|
||||
`x-popup-menu' does not return. But if POSITION is a mouse button
|
||||
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
|
||||
x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
|
||||
{
|
||||
Lisp_Object keymap, tem, tem2;
|
||||
int xpos = 0, ypos = 0;
|
||||
|
@ -1443,6 +1400,55 @@ no quit occurs and `x-popup-menu' returns nil. */)
|
|||
return selection;
|
||||
}
|
||||
|
||||
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
|
||||
or a list ((XOFFSET YOFFSET) WINDOW)
|
||||
where XOFFSET and YOFFSET are positions in pixels from the top left
|
||||
corner of WINDOW. (WINDOW may be a window or a frame object.)
|
||||
This controls the position of the top left of the menu as a whole.
|
||||
If POSITION is t, it means to use the current mouse position.
|
||||
|
||||
MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
|
||||
The menu items come from key bindings that have a menu string as well as
|
||||
a definition; actually, the "definition" in such a key binding looks like
|
||||
\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
|
||||
the keymap as a top-level element.
|
||||
|
||||
If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
|
||||
Otherwise, REAL-DEFINITION should be a valid key binding definition.
|
||||
|
||||
You can also use a list of keymaps as MENU.
|
||||
Then each keymap makes a separate pane.
|
||||
|
||||
When MENU is a keymap or a list of keymaps, the return value is the
|
||||
list of events corresponding to the user's choice. Note that
|
||||
`x-popup-menu' does not actually execute the command bound to that
|
||||
sequence of events.
|
||||
|
||||
Alternatively, you can specify a menu of multiple panes
|
||||
with a list of the form (TITLE PANE1 PANE2...),
|
||||
where each pane is a list of form (TITLE ITEM1 ITEM2...).
|
||||
Each ITEM is normally a cons cell (STRING . VALUE);
|
||||
but a string can appear as an item--that makes a nonselectable line
|
||||
in the menu.
|
||||
With this form of menu, the return value is VALUE from the chosen item.
|
||||
|
||||
If POSITION is nil, don't display the menu at all, just precalculate the
|
||||
cached information about equivalent key sequences.
|
||||
|
||||
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
|
||||
`x-popup-menu' does not return. But if POSITION is a mouse button
|
||||
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)
|
||||
{
|
||||
init_raw_keybuf_count ();
|
||||
return x_popup_menu_1 (position, menu);
|
||||
}
|
||||
|
||||
/* If F's terminal is not capable of displaying a popup dialog,
|
||||
emulate it with a menu. */
|
||||
|
||||
|
|
|
@ -60,4 +60,5 @@ extern Lisp_Object ns_menu_show (struct frame *, int, int, int,
|
|||
extern Lisp_Object tty_menu_show (struct frame *, int, int, int,
|
||||
Lisp_Object, const char **);
|
||||
extern ptrdiff_t menu_item_width (const unsigned char *);
|
||||
extern Lisp_Object x_popup_menu_1 (Lisp_Object position, Lisp_Object menu);
|
||||
#endif /* MENU_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue