From: Alan Mackenzie Date: Mon, 20 Nov 2017 18:05:33 +0000 (+0000) Subject: read_key_sequence: correct the handling of raw_keybuf in recursive calls X-Git-Tag: emacs-27.0.90~6144 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=5b5f441ff8986800aa5f175bb5db2dd90e642a3a;p=emacs.git read_key_sequence: correct the handling of raw_keybuf in recursive calls This fixes bug #29349. * src/keyboard.c (raw_keybuf_buffer, raw_keybuf_count_buffer): New variables pointed to by ... (raw_keybuf, raw_keybuf_count): Variables converted to pointers. (GROW_RAW_KEYBUF): enhance with a length argument. (command_loop_1): Initialize the above two pointers to their canonical values. (read_key_sequence): In recursive calls (for menus) the function was overwriting the raw event buffer of the outer call. Correct this by introducing a local buffer for each level of call, and setting this up to be used by the call to read_char. Any contents of this local buffer are appended to the global buffer afterwards. --- diff --git a/src/keyboard.c b/src/keyboard.c index 6b7a6bfa743..b18dc1abbe7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -121,12 +121,17 @@ 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; -static int raw_keybuf_count; - -#define GROW_RAW_KEYBUF \ - if (raw_keybuf_count == ASIZE (raw_keybuf)) \ - raw_keybuf = larger_vector (raw_keybuf, 1, -1) +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; + +#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) /* Number of elements of this_command_keys that precede this key sequence. */ @@ -1365,6 +1370,8 @@ 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 */ i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 0); @@ -8913,6 +8920,11 @@ 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; @@ -8973,7 +8985,7 @@ 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 = 0; last_nonmenu_event = Qnil; @@ -9145,11 +9157,23 @@ 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 @@ -9257,9 +9281,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, && XINT (key) == quit_char && current_buffer != starting_buffer) { - GROW_RAW_KEYBUF; - ASET (raw_keybuf, raw_keybuf_count, key); - raw_keybuf_count++; + GROW_RAW_KEYBUF (1); + ASET (*raw_keybuf, *raw_keybuf_count, key); + (*raw_keybuf_count)++; keybuf[t++] = key; mock_input = t; Vquit_flag = Qnil; @@ -9298,9 +9322,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, current_binding = active_maps (first_event); } - GROW_RAW_KEYBUF; - ASET (raw_keybuf, raw_keybuf_count, key); - raw_keybuf_count++; + GROW_RAW_KEYBUF (1); + ASET (*raw_keybuf, *raw_keybuf_count, key); + (*raw_keybuf_count)++; } /* Clicks in non-text areas get prefixed by the symbol @@ -9346,8 +9370,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, && BUFFERP (XWINDOW (window)->contents) && XBUFFER (XWINDOW (window)->contents) != current_buffer) { - ASET (raw_keybuf, raw_keybuf_count, key); - raw_keybuf_count++; + GROW_RAW_KEYBUF (1); + ASET (*raw_keybuf, *raw_keybuf_count, key); + (*raw_keybuf_count)++; keybuf[t] = key; mock_input = t + 1; @@ -10120,7 +10145,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, @@ -11265,8 +11290,8 @@ syms_of_keyboard (void) this_command_keys = Fmake_vector (make_number (40), Qnil); staticpro (&this_command_keys); - raw_keybuf = Fmake_vector (make_number (30), Qnil); - staticpro (&raw_keybuf); + raw_keybuf_buffer = Fmake_vector (make_number (30), Qnil); + staticpro (raw_keybuf); DEFSYM (Qcommand_execute, "command-execute"); DEFSYM (Qinternal_echo_keystrokes_prefix, "internal-echo-keystrokes-prefix");