X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/3b7ad313e0d7b351c55cf999474b61cdc18ecad1..80184dac072806f282c0bae51bd0b2569083cdda:/src/macros.c diff --git a/src/macros.c b/src/macros.c index 67c8ede6d4..a0212e1044 100644 --- a/src/macros.c +++ b/src/macros.c @@ -29,9 +29,30 @@ Boston, MA 02111-1307, USA. */ Lisp_Object Qexecute_kbd_macro; +/* Kbd macro currently being executed (a string or vector). */ + Lisp_Object Vexecuting_macro; + +/* Index of next character to fetch from that macro. */ + int executing_macro_index; +/* Number of successful iterations so far + for innermost keyboard macro. + This is not bound at each level, + so after an error, it describes the innermost interrupted macro. */ + +int executing_macro_iterations; + +/* This is the macro that was executing. + This is not bound at each level, + so after an error, it describes the innermost interrupted macro. + We use it only as a kind of flag, so no need to protect it. */ + +Lisp_Object executing_macro; + +extern Lisp_Object real_this_command; + Lisp_Object Fexecute_kbd_macro (); DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P", @@ -51,18 +72,25 @@ Non-nil arg (prefix arg) means append to last macro defined;\n\ { current_kboard->kbd_macro_bufsize = 30; current_kboard->kbd_macro_buffer - = (Lisp_Object *)malloc (30 * sizeof (Lisp_Object)); + = (Lisp_Object *)xmalloc (30 * sizeof (Lisp_Object)); } update_mode_lines++; if (NILP (append)) { + if (current_kboard->kbd_macro_bufsize > 200) + { + current_kboard->kbd_macro_bufsize = 30; + current_kboard->kbd_macro_buffer + = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer, + 30 * sizeof (Lisp_Object)); + } current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer; current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer; - message("Defining kbd macro..."); + message ("Defining kbd macro..."); } else { - message("Appending to kbd macro..."); + message ("Appending to kbd macro..."); current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end; Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, make_number (1)); @@ -86,7 +114,7 @@ An argument of zero means repeat until error.") Lisp_Object repeat; { if (NILP (current_kboard->defining_kbd_macro)) - error ("Not defining kbd macro."); + error ("Not defining kbd macro"); if (NILP (repeat)) XSETFASTINT (repeat, 1); @@ -101,7 +129,7 @@ An argument of zero means repeat until error.") = make_event_array ((current_kboard->kbd_macro_end - current_kboard->kbd_macro_buffer), current_kboard->kbd_macro_buffer); - message("Keyboard macro defined"); + message ("Keyboard macro defined"); } if (XFASTINT (repeat) == 0) @@ -117,6 +145,7 @@ An argument of zero means repeat until error.") /* Store character c into kbd macro being defined */ +void store_kbd_macro_char (c) Lisp_Object c; { @@ -144,6 +173,7 @@ store_kbd_macro_char (c) /* Declare that all chars stored so far in the kbd macro being defined really belong to it. This is done in between editor commands. */ +void finalize_kbd_macro_chars () { current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr; @@ -178,25 +208,39 @@ defining others, use \\[name-last-kbd-macro].") (prefix) Lisp_Object prefix; { + /* Don't interfere with recognition of the previous command + from before this macro started. */ + Vthis_command = current_kboard->Vlast_command; + /* C-x z after the macro should repeat the macro. */ + real_this_command = current_kboard->Vlast_kbd_macro; + if (! NILP (current_kboard->defining_kbd_macro)) error ("Can't execute anonymous macro while defining one"); else if (NILP (current_kboard->Vlast_kbd_macro)) error ("No kbd macro has been defined"); else Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix); + + /* command_loop_1 sets this to nil before it returns; + get back the last command within the macro + so that it can be last, again, after we return. */ + Vthis_command = current_kboard->Vlast_command; + return Qnil; } /* Restore Vexecuting_macro and executing_macro_index - called when the unwind-protect in Fexecute_kbd_macro gets invoked. */ + static Lisp_Object pop_kbd_macro (info) Lisp_Object info; { Lisp_Object tem; - Vexecuting_macro = Fcar (info); - tem = Fcdr (info); - executing_macro_index = XINT (tem); + Vexecuting_macro = XCAR (info); + tem = XCDR (info); + executing_macro_index = XINT (XCAR (tem)); + real_this_command = XCDR (tem); return Qnil; } @@ -212,6 +256,9 @@ COUNT is a repeat count, or nil for once, or 0 for infinite loop.") int pdlcount = specpdl_ptr - specpdl; int repeat = 1; struct gcpro gcpro1; + int success_count = 0; + + executing_macro_iterations = 0; if (!NILP (count)) { @@ -221,35 +268,46 @@ COUNT is a repeat count, or nil for once, or 0 for infinite loop.") final = indirect_function (macro); if (!STRINGP (final) && !VECTORP (final)) - error ("Keyboard macros must be strings or vectors."); + error ("Keyboard macros must be strings or vectors"); - XSETFASTINT (tem, executing_macro_index); - tem = Fcons (Vexecuting_macro, tem); + tem = Fcons (Vexecuting_macro, + Fcons (make_number (executing_macro_index), + real_this_command)); record_unwind_protect (pop_kbd_macro, tem); GCPRO1 (final); do { Vexecuting_macro = final; + executing_macro = final; executing_macro_index = 0; current_kboard->Vprefix_arg = Qnil; command_loop_1 (); + executing_macro_iterations = ++success_count; + QUIT; } while (--repeat && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro))); + executing_macro = Qnil; + + real_this_command = Vexecuting_macro; + UNGCPRO; return unbind_to (pdlcount, Qnil); } +void init_macros () { Vexecuting_macro = Qnil; + executing_macro = Qnil; } +void syms_of_macros () { Qexecute_kbd_macro = intern ("execute-kbd-macro"); @@ -275,6 +333,7 @@ syms_of_macros () "Last kbd macro defined, as a string or vector; nil if none defined."); } +void keys_of_macros () { initial_define_key (control_x_map, ('e'), "call-last-kbd-macro");