summaryrefslogtreecommitdiff
path: root/src/macros.c
diff options
context:
space:
mode:
authorTim Ruffing <crypto@timruffing.de>2023-12-27 14:32:09 +0100
committerStefan Monnier <monnier@iro.umontreal.ca>2024-03-10 10:40:13 -0400
commit6f46dd516b84ad7d59b49c2e9e3fc1a2d4ef4d1c (patch)
tree4075841773bcb6992af91b1ec81b21d6c0b96f9e /src/macros.c
parentd6f326452ecc761498d627a365c8014a467812eb (diff)
downloademacs-6f46dd516b84ad7d59b49c2e9e3fc1a2d4ef4d1c.tar.gz
Continue reading in 'read-event' etc. at the end of a keyboard macro
This fixes a bug that could make 'read-event', 'read-char', and 'read-char-exclusive' erroneously return -1, an internal magic return value of 'read_char' leaked from C to lisp. Instead of returning -1, the aforementioned lisp functions now transparently continue reading available input (e.g., from the keyboard) when reaching the end of a keyboard macro. * src/keyboard.c (read_char, read_key_sequence): Move handling of the end of a keyboard macro from 'read_char' to its caller 'read_key_sequence', which is the only caller that can meaningfully deal with this case. * src/macros.c (Fexecute_kbd_macro): Document how the end of keyboard macro is processed. * etc/NEWS: Announce this change.
Diffstat (limited to 'src/macros.c')
-rw-r--r--src/macros.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/macros.c b/src/macros.c
index faec9dc646d..230195d9488 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -314,6 +314,48 @@ buffer before the macro is executed. */)
Vreal_this_command));
record_unwind_protect (pop_kbd_macro, tem);
+ /* The following loop starts the execution of possibly multiple
+ iterations of the macro.
+
+ The state variables that control the execution of a single
+ iteration are Vexecuting_kbd_macro and executing_kbd_macro_index,
+ which can be accessed from lisp. The purpose of the variables
+ executing_kbd_macro and executing_kbd_macro_iteration is to
+ remember the most recently started macro and its iteration count.
+ This makes it possible to produce a meaningful message in case of
+ errors during the execution of the macro.
+
+ In a single iteration, individual characters from the macro are
+ read by read_char, which takes care of incrementing
+ executing_kbd_macro_index after each character.
+
+ The end of a macro iteration is handled as follows:
+ - read_key_sequence asks at_end_of_macro_p whether the end of the
+ iteration has been reached. If so, it returns the magic value 0
+ to command_loop_1.
+ - command_loop_1 returns Qnil to command_loop_2.
+ - command_loop_2 returns Qnil to this function
+ (but only the returning is relevant, not the actual value).
+
+ Macro executions form a stack. After the last iteration of the
+ execution of one stack item, or in case of an error during one of
+ the iterations, pop_kbd_macro (invoked via unwind-protect) will
+ restore Vexecuting_kbd_macro and executing_kbd_macro_index, and
+ run 'kbd-macro-termination-hook'.
+
+ If read_char happens to be called at the end of a macro interation,
+ but before read_key_sequence could handle the end (e.g., when lisp
+ code calls 'read-event', 'read-char', or 'read-char-exclusive'),
+ read_char will simply continue reading other available input
+ (Bug#68272). Vexecuting_kbd_macro and executing_kbd_macro remain
+ untouched until the end of the iteration is handled.
+
+ This is similar (in observable behavior) to a posibly simpler
+ implementation of keyboard macros in which this function pushed all
+ characters of the macro into the incoming event queue and returned
+ immediately. Maybe this is the implementation that we ideally
+ would like to have, but switching to it will require a larger code
+ change. */
do
{
Vexecuting_kbd_macro = final;