diff options
| author | Alan Mackenzie | 2017-11-20 18:05:33 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2017-11-20 18:08:43 +0000 |
| commit | 5b5f441ff8986800aa5f175bb5db2dd90e642a3a (patch) | |
| tree | f293bf9b7af092d518185b680e1522c9899b8d61 | |
| parent | 9c6791afcd2b60f069494031ef64a5aac70ca3f8 (diff) | |
| download | emacs-5b5f441ff8986800aa5f175bb5db2dd90e642a3a.tar.gz emacs-5b5f441ff8986800aa5f175bb5db2dd90e642a3a.zip | |
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.
| -rw-r--r-- | src/keyboard.c | 61 |
1 files changed, 43 insertions, 18 deletions
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; | |||
| 121 | 121 | ||
| 122 | /* This vector is used as a buffer to record the events that were actually read | 122 | /* This vector is used as a buffer to record the events that were actually read |
| 123 | by read_key_sequence. */ | 123 | by read_key_sequence. */ |
| 124 | static Lisp_Object raw_keybuf; | 124 | static Lisp_Object raw_keybuf_buffer; |
| 125 | static int raw_keybuf_count; | 125 | static int raw_keybuf_count_buffer; |
| 126 | 126 | static Lisp_Object *raw_keybuf = &raw_keybuf_buffer; | |
| 127 | #define GROW_RAW_KEYBUF \ | 127 | static int *raw_keybuf_count = &raw_keybuf_count_buffer; |
| 128 | if (raw_keybuf_count == ASIZE (raw_keybuf)) \ | 128 | |
| 129 | raw_keybuf = larger_vector (raw_keybuf, 1, -1) | 129 | #define GROW_RAW_KEYBUF(inc) \ |
| 130 | if (*raw_keybuf_count > ASIZE (*raw_keybuf) - (inc)) \ | ||
| 131 | *raw_keybuf = \ | ||
| 132 | larger_vector (*raw_keybuf, \ | ||
| 133 | (inc) + *raw_keybuf_count - ASIZE (*raw_keybuf), \ | ||
| 134 | -1) | ||
| 130 | 135 | ||
| 131 | /* Number of elements of this_command_keys | 136 | /* Number of elements of this_command_keys |
| 132 | that precede this key sequence. */ | 137 | that precede this key sequence. */ |
| @@ -1365,6 +1370,8 @@ command_loop_1 (void) | |||
| 1365 | Vthis_command_keys_shift_translated = Qnil; | 1370 | Vthis_command_keys_shift_translated = Qnil; |
| 1366 | 1371 | ||
| 1367 | /* Read next key sequence; i gets its length. */ | 1372 | /* Read next key sequence; i gets its length. */ |
| 1373 | raw_keybuf_count = &raw_keybuf_count_buffer; /* For safety */ | ||
| 1374 | raw_keybuf = &raw_keybuf_buffer; /* Ditto */ | ||
| 1368 | i = read_key_sequence (keybuf, ARRAYELTS (keybuf), | 1375 | i = read_key_sequence (keybuf, ARRAYELTS (keybuf), |
| 1369 | Qnil, 0, 1, 1, 0); | 1376 | Qnil, 0, 1, 1, 0); |
| 1370 | 1377 | ||
| @@ -8913,6 +8920,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 8913 | /* How many keys there are in the current key sequence. */ | 8920 | /* How many keys there are in the current key sequence. */ |
| 8914 | int t; | 8921 | int t; |
| 8915 | 8922 | ||
| 8923 | int *outer_raw_keybuf_count; | ||
| 8924 | Lisp_Object *outer_raw_keybuf; | ||
| 8925 | int inner_raw_keybuf_count_buffer; | ||
| 8926 | Lisp_Object inner_raw_keybuf_buffer = Fmake_vector (make_number (30), Qnil); | ||
| 8927 | |||
| 8916 | /* The length of the echo buffer when we started reading, and | 8928 | /* The length of the echo buffer when we started reading, and |
| 8917 | the length of this_command_keys when we started reading. */ | 8929 | the length of this_command_keys when we started reading. */ |
| 8918 | ptrdiff_t echo_start UNINIT; | 8930 | ptrdiff_t echo_start UNINIT; |
| @@ -8973,7 +8985,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 8973 | /* List of events for which a fake prefix key has been generated. */ | 8985 | /* List of events for which a fake prefix key has been generated. */ |
| 8974 | Lisp_Object fake_prefixed_keys = Qnil; | 8986 | Lisp_Object fake_prefixed_keys = Qnil; |
| 8975 | 8987 | ||
| 8976 | raw_keybuf_count = 0; | 8988 | *raw_keybuf_count = 0; |
| 8977 | 8989 | ||
| 8978 | last_nonmenu_event = Qnil; | 8990 | last_nonmenu_event = Qnil; |
| 8979 | 8991 | ||
| @@ -9145,11 +9157,23 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 9145 | { | 9157 | { |
| 9146 | KBOARD *interrupted_kboard = current_kboard; | 9158 | KBOARD *interrupted_kboard = current_kboard; |
| 9147 | struct frame *interrupted_frame = SELECTED_FRAME (); | 9159 | struct frame *interrupted_frame = SELECTED_FRAME (); |
| 9160 | int i; | ||
| 9161 | outer_raw_keybuf_count = raw_keybuf_count; | ||
| 9162 | outer_raw_keybuf = raw_keybuf; | ||
| 9163 | inner_raw_keybuf_count_buffer = 0; | ||
| 9164 | raw_keybuf_count = &inner_raw_keybuf_count_buffer; | ||
| 9165 | raw_keybuf = &inner_raw_keybuf_buffer; | ||
| 9148 | /* Calling read_char with COMMANDFLAG = -2 avoids | 9166 | /* Calling read_char with COMMANDFLAG = -2 avoids |
| 9149 | redisplay in read_char and its subroutines. */ | 9167 | redisplay in read_char and its subroutines. */ |
| 9150 | key = read_char (prevent_redisplay ? -2 : NILP (prompt), | 9168 | key = read_char (prevent_redisplay ? -2 : NILP (prompt), |
| 9151 | current_binding, last_nonmenu_event, | 9169 | current_binding, last_nonmenu_event, |
| 9152 | &used_mouse_menu, NULL); | 9170 | &used_mouse_menu, NULL); |
| 9171 | raw_keybuf_count = outer_raw_keybuf_count; | ||
| 9172 | raw_keybuf = outer_raw_keybuf; | ||
| 9173 | GROW_RAW_KEYBUF (inner_raw_keybuf_count_buffer); | ||
| 9174 | for (i = 0; i < inner_raw_keybuf_count_buffer; i++) | ||
| 9175 | ASET (*raw_keybuf, (*raw_keybuf_count)++, | ||
| 9176 | AREF (inner_raw_keybuf_buffer, i)); | ||
| 9153 | if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ | 9177 | if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ |
| 9154 | /* When switching to a new tty (with a new keyboard), | 9178 | /* When switching to a new tty (with a new keyboard), |
| 9155 | read_char returns the new buffer, rather than -2 | 9179 | read_char returns the new buffer, rather than -2 |
| @@ -9257,9 +9281,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 9257 | && XINT (key) == quit_char | 9281 | && XINT (key) == quit_char |
| 9258 | && current_buffer != starting_buffer) | 9282 | && current_buffer != starting_buffer) |
| 9259 | { | 9283 | { |
| 9260 | GROW_RAW_KEYBUF; | 9284 | GROW_RAW_KEYBUF (1); |
| 9261 | ASET (raw_keybuf, raw_keybuf_count, key); | 9285 | ASET (*raw_keybuf, *raw_keybuf_count, key); |
| 9262 | raw_keybuf_count++; | 9286 | (*raw_keybuf_count)++; |
| 9263 | keybuf[t++] = key; | 9287 | keybuf[t++] = key; |
| 9264 | mock_input = t; | 9288 | mock_input = t; |
| 9265 | Vquit_flag = Qnil; | 9289 | Vquit_flag = Qnil; |
| @@ -9298,9 +9322,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 9298 | current_binding = active_maps (first_event); | 9322 | current_binding = active_maps (first_event); |
| 9299 | } | 9323 | } |
| 9300 | 9324 | ||
| 9301 | GROW_RAW_KEYBUF; | 9325 | GROW_RAW_KEYBUF (1); |
| 9302 | ASET (raw_keybuf, raw_keybuf_count, key); | 9326 | ASET (*raw_keybuf, *raw_keybuf_count, key); |
| 9303 | raw_keybuf_count++; | 9327 | (*raw_keybuf_count)++; |
| 9304 | } | 9328 | } |
| 9305 | 9329 | ||
| 9306 | /* Clicks in non-text areas get prefixed by the symbol | 9330 | /* 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, | |||
| 9346 | && BUFFERP (XWINDOW (window)->contents) | 9370 | && BUFFERP (XWINDOW (window)->contents) |
| 9347 | && XBUFFER (XWINDOW (window)->contents) != current_buffer) | 9371 | && XBUFFER (XWINDOW (window)->contents) != current_buffer) |
| 9348 | { | 9372 | { |
| 9349 | ASET (raw_keybuf, raw_keybuf_count, key); | 9373 | GROW_RAW_KEYBUF (1); |
| 9350 | raw_keybuf_count++; | 9374 | ASET (*raw_keybuf, *raw_keybuf_count, key); |
| 9375 | (*raw_keybuf_count)++; | ||
| 9351 | keybuf[t] = key; | 9376 | keybuf[t] = key; |
| 9352 | mock_input = t + 1; | 9377 | mock_input = t + 1; |
| 9353 | 9378 | ||
| @@ -10120,7 +10145,7 @@ shows the events before all translations (except for input methods). | |||
| 10120 | The value is always a vector. */) | 10145 | The value is always a vector. */) |
| 10121 | (void) | 10146 | (void) |
| 10122 | { | 10147 | { |
| 10123 | return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->contents); | 10148 | return Fvector (*raw_keybuf_count, XVECTOR (*raw_keybuf)->contents); |
| 10124 | } | 10149 | } |
| 10125 | 10150 | ||
| 10126 | DEFUN ("clear-this-command-keys", Fclear_this_command_keys, | 10151 | DEFUN ("clear-this-command-keys", Fclear_this_command_keys, |
| @@ -11265,8 +11290,8 @@ syms_of_keyboard (void) | |||
| 11265 | this_command_keys = Fmake_vector (make_number (40), Qnil); | 11290 | this_command_keys = Fmake_vector (make_number (40), Qnil); |
| 11266 | staticpro (&this_command_keys); | 11291 | staticpro (&this_command_keys); |
| 11267 | 11292 | ||
| 11268 | raw_keybuf = Fmake_vector (make_number (30), Qnil); | 11293 | raw_keybuf_buffer = Fmake_vector (make_number (30), Qnil); |
| 11269 | staticpro (&raw_keybuf); | 11294 | staticpro (raw_keybuf); |
| 11270 | 11295 | ||
| 11271 | DEFSYM (Qcommand_execute, "command-execute"); | 11296 | DEFSYM (Qcommand_execute, "command-execute"); |
| 11272 | DEFSYM (Qinternal_echo_keystrokes_prefix, "internal-echo-keystrokes-prefix"); | 11297 | DEFSYM (Qinternal_echo_keystrokes_prefix, "internal-echo-keystrokes-prefix"); |