summaryrefslogtreecommitdiff
path: root/src/macros.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/macros.c')
-rw-r--r--src/macros.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/macros.c b/src/macros.c
new file mode 100644
index 00000000000..e4e0a168ebb
--- /dev/null
+++ b/src/macros.c
@@ -0,0 +1,243 @@
+/* Keyboard macros.
+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "config.h"
+#include "lisp.h"
+#include "macros.h"
+#include "commands.h"
+#include "buffer.h"
+#include "window.h"
+
+int defining_kbd_macro;
+
+char *kbd_macro_buffer;
+char *kbd_macro_ptr;
+char *kbd_macro_end;
+int kbd_macro_bufsize;
+Lisp_Object Vlast_kbd_macro;
+
+Lisp_Object Vexecuting_macro;
+int executing_macro_index;
+
+Lisp_Object Fexecute_kbd_macro ();
+
+DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P",
+ "Record subsequent keyboard input, defining a keyboard macro.\n\
+The commands are recorded even as they are executed.\n\
+Use \\[end-kbd-macro] to finish recording and make the macro available.\n\
+Use \\[name-last-kbd-macro] to give it a permanent name.\n\
+Non-nil arg (prefix arg) means append to last macro defined;\n\
+ This begins by re-executing that macro as if you typed it again.")
+ (append)
+ Lisp_Object append;
+{
+ if (defining_kbd_macro)
+ error ("Already defining kbd macro");
+
+ update_mode_lines++;
+ if (NULL (append))
+ {
+ kbd_macro_ptr = kbd_macro_buffer;
+ kbd_macro_end = kbd_macro_buffer;
+ message("Defining kbd macro...");
+ }
+ else
+ {
+ message("Appending to kbd macro...");
+ kbd_macro_ptr = kbd_macro_end;
+ Fexecute_kbd_macro (Vlast_kbd_macro, make_number (1));
+ }
+ defining_kbd_macro = 1;
+
+ return Qnil;
+}
+
+DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "p",
+ "Finish defining a keyboard macro.\n\
+The definition was started by \\[start-kbd-macro].\n\
+The macro is now available for use via \\[call-last-kbd-macro],\n\
+or it can be given a name with \\[name-last-kbd-macro] and then invoked\n\
+under that name.\n\
+With numeric arg, repeat macro now that many times,\n\
+counting the definition just completed as the first repetition.")
+ (arg)
+ Lisp_Object arg;
+{
+ if (!defining_kbd_macro)
+ error ("Not defining kbd macro.");
+
+ if (NULL (arg))
+ XFASTINT (arg) = 1;
+ else
+ CHECK_NUMBER (arg, 0);
+
+ if (defining_kbd_macro)
+ {
+ defining_kbd_macro = 0;
+ update_mode_lines++;
+ Vlast_kbd_macro = make_string (kbd_macro_buffer,
+ kbd_macro_end - kbd_macro_buffer);
+ message("Keyboard macro defined");
+ }
+
+ if (XFASTINT (arg) == 0)
+ Fexecute_kbd_macro (Vlast_kbd_macro, arg);
+ else
+ {
+ XFASTINT (arg)--;
+ if (XFASTINT (arg) > 0)
+ Fexecute_kbd_macro (Vlast_kbd_macro, arg);
+ }
+ return Qnil;
+}
+
+/* Store character c into kbd macro being defined */
+
+store_kbd_macro_char (c)
+ unsigned char c;
+{
+ if (defining_kbd_macro)
+ {
+ if (kbd_macro_ptr - kbd_macro_buffer == kbd_macro_bufsize)
+ {
+ register char *new = (char *) xrealloc (kbd_macro_buffer, kbd_macro_bufsize *= 2);
+ kbd_macro_ptr += new - kbd_macro_buffer;
+ kbd_macro_end = new + kbd_macro_bufsize;
+ kbd_macro_buffer = new;
+ }
+ *kbd_macro_ptr++ = 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. */
+
+finalize_kbd_macro_chars ()
+{
+ kbd_macro_end = kbd_macro_ptr;
+}
+
+DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro,
+ 0, 1, "p",
+ "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\
+To make a macro permanent so you can call it even after\n\
+defining others, use \\[name-last-kbd-macro].")
+ (prefix)
+ Lisp_Object prefix;
+{
+ if (defining_kbd_macro)
+ error ("Can't execute anonymous macro while defining one");
+ else if (NULL (Vlast_kbd_macro))
+ error ("No kbd macro has been defined");
+ else
+ Fexecute_kbd_macro (Vlast_kbd_macro, prefix);
+ return Qnil;
+}
+
+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);
+ return Qnil;
+}
+
+DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0,
+ "Execute MACRO as string of editor command characters.\n\
+If MACRO is a symbol, its function definition is used.\n\
+COUNT is a repeat count, or nil for once, or 0 for infinite loop.")
+ (macro, prefixarg)
+ Lisp_Object macro, prefixarg;
+{
+ Lisp_Object final;
+ Lisp_Object tem;
+ int count = specpdl_ptr - specpdl;
+ int repeat = 1;
+ struct gcpro gcpro1;
+
+ if (!NULL (prefixarg))
+ prefixarg = Fprefix_numeric_value (prefixarg),
+ repeat = XINT (prefixarg);
+
+ final = macro;
+ while (XTYPE (final) == Lisp_Symbol && !EQ (final, Qunbound))
+ final = XSYMBOL (final)->function;
+ CHECK_STRING (final, 0);
+
+ XFASTINT (tem) = executing_macro_index;
+ tem = Fcons (Vexecuting_macro, tem);
+ record_unwind_protect (pop_kbd_macro, tem);
+
+ GCPRO1 (final);
+ do
+ {
+ Vexecuting_macro = final;
+ executing_macro_index = 0;
+
+ command_loop_1 ();
+ }
+ while (--repeat && XTYPE (Vexecuting_macro) == Lisp_String);
+
+ UNGCPRO;
+ unbind_to (count);
+
+ return Qnil;
+}
+
+init_macros ()
+{
+ Vlast_kbd_macro = Qnil;
+ defining_kbd_macro = 0;
+
+ Vexecuting_macro = Qnil;
+}
+
+syms_of_macros ()
+{
+ kbd_macro_bufsize = 100;
+ kbd_macro_buffer = (char *) malloc (kbd_macro_bufsize);
+
+ defsubr (&Sstart_kbd_macro);
+ defsubr (&Send_kbd_macro);
+ defsubr (&Scall_last_kbd_macro);
+ defsubr (&Sexecute_kbd_macro);
+
+ DEFVAR_BOOL ("defining-kbd-macro", &defining_kbd_macro,
+ "Non-nil means store keyboard input into kbd macro being defined.");
+
+ DEFVAR_LISP ("executing-macro", &Vexecuting_macro,
+ "Currently executing keyboard macro (a string); nil if none executing.");
+
+ DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro,
+ "Currently executing keyboard macro (a string); nil if none executing.");
+
+ DEFVAR_LISP ("last-kbd-macro", &Vlast_kbd_macro,
+ "Last kbd macro defined, as a string; nil if none defined.");
+}
+
+keys_of_macros ()
+{
+ ndefkey (Vctl_x_map, ('e'), "call-last-kbd-macro");
+ ndefkey (Vctl_x_map, ('('), "start-kbd-macro");
+ ndefkey (Vctl_x_map, (')'), "end-kbd-macro");
+}