Commit | Line | Data |
---|---|---|
5a7f5d07 | 1 | /* Keyboard macros. |
c6c5df7f | 2 | Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc. |
5a7f5d07 JB |
3 | |
4 | This file is part of GNU Emacs. | |
5 | ||
6 | GNU Emacs is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
502ddf23 | 8 | the Free Software Foundation; either version 2, or (at your option) |
5a7f5d07 JB |
9 | any later version. |
10 | ||
11 | GNU Emacs is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Emacs; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | ||
18160b98 | 21 | #include <config.h> |
5a7f5d07 JB |
22 | #include "lisp.h" |
23 | #include "macros.h" | |
24 | #include "commands.h" | |
25 | #include "buffer.h" | |
26 | #include "window.h" | |
27 | ||
28 | Lisp_Object Qexecute_kbd_macro; | |
29 | ||
30 | int defining_kbd_macro; | |
31 | ||
32 | /* The start of storage for the current keyboard macro, and its size. */ | |
33 | Lisp_Object *kbd_macro_buffer; | |
34 | int kbd_macro_bufsize; | |
35 | ||
36 | /* Where to store the next keystroke of the macro. */ | |
37 | Lisp_Object *kbd_macro_ptr; | |
38 | ||
39 | /* The finalized section of the macro starts at kbd_macro_buffer and | |
40 | ends before this. This is not the same as kbd_macro_pointer, because | |
41 | we advance this to kbd_macro_pointer when a key's command is complete. | |
42 | This way, the keystrokes for "end-kbd-macro" are not included in the | |
43 | macro. */ | |
44 | Lisp_Object *kbd_macro_end; | |
45 | ||
46 | Lisp_Object Vlast_kbd_macro; | |
47 | ||
48 | Lisp_Object Vexecuting_macro; | |
49 | int executing_macro_index; | |
50 | ||
51 | Lisp_Object Fexecute_kbd_macro (); | |
52 | \f | |
53 | DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P", | |
54 | "Record subsequent keyboard input, defining a keyboard macro.\n\ | |
55 | The commands are recorded even as they are executed.\n\ | |
56 | Use \\[end-kbd-macro] to finish recording and make the macro available.\n\ | |
57 | Use \\[name-last-kbd-macro] to give it a permanent name.\n\ | |
58 | Non-nil arg (prefix arg) means append to last macro defined;\n\ | |
59 | This begins by re-executing that macro as if you typed it again.") | |
60 | (append) | |
61 | Lisp_Object append; | |
62 | { | |
63 | if (defining_kbd_macro) | |
64 | error ("Already defining kbd macro"); | |
65 | ||
66 | update_mode_lines++; | |
265a9e55 | 67 | if (NILP (append)) |
5a7f5d07 JB |
68 | { |
69 | kbd_macro_ptr = kbd_macro_buffer; | |
70 | kbd_macro_end = kbd_macro_buffer; | |
71 | message("Defining kbd macro..."); | |
72 | } | |
73 | else | |
74 | { | |
75 | message("Appending to kbd macro..."); | |
76 | kbd_macro_ptr = kbd_macro_end; | |
77 | Fexecute_kbd_macro (Vlast_kbd_macro, make_number (1)); | |
78 | } | |
79 | defining_kbd_macro++; | |
80 | ||
81 | return Qnil; | |
82 | } | |
83 | ||
84 | DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "p", | |
85 | "Finish defining a keyboard macro.\n\ | |
86 | The definition was started by \\[start-kbd-macro].\n\ | |
87 | The macro is now available for use via \\[call-last-kbd-macro],\n\ | |
88 | or it can be given a name with \\[name-last-kbd-macro] and then invoked\n\ | |
89 | under that name.\n\ | |
90 | \n\ | |
91 | With numeric arg, repeat macro now that many times,\n\ | |
92 | counting the definition just completed as the first repetition.\n\ | |
93 | An argument of zero means repeat until error.") | |
94 | (arg) | |
95 | Lisp_Object arg; | |
96 | { | |
97 | if (!defining_kbd_macro) | |
98 | error ("Not defining kbd macro."); | |
99 | ||
265a9e55 | 100 | if (NILP (arg)) |
5a7f5d07 JB |
101 | XFASTINT (arg) = 1; |
102 | else | |
103 | CHECK_NUMBER (arg, 0); | |
104 | ||
105 | if (defining_kbd_macro) | |
106 | { | |
107 | defining_kbd_macro = 0; | |
108 | update_mode_lines++; | |
ba8810f9 RS |
109 | Vlast_kbd_macro = make_event_array (kbd_macro_end - kbd_macro_buffer, |
110 | kbd_macro_buffer); | |
5a7f5d07 JB |
111 | message("Keyboard macro defined"); |
112 | } | |
113 | ||
114 | if (XFASTINT (arg) == 0) | |
115 | Fexecute_kbd_macro (Vlast_kbd_macro, arg); | |
116 | else | |
117 | { | |
e86f81cc JB |
118 | XSETINT (arg, XINT (arg)-1); |
119 | if (XINT (arg) > 0) | |
5a7f5d07 JB |
120 | Fexecute_kbd_macro (Vlast_kbd_macro, arg); |
121 | } | |
122 | return Qnil; | |
123 | } | |
124 | ||
125 | /* Store character c into kbd macro being defined */ | |
126 | ||
127 | store_kbd_macro_char (c) | |
128 | Lisp_Object c; | |
129 | { | |
130 | if (defining_kbd_macro) | |
131 | { | |
132 | if (kbd_macro_ptr - kbd_macro_buffer == kbd_macro_bufsize) | |
133 | { | |
134 | register Lisp_Object *new | |
135 | = (Lisp_Object *) xrealloc (kbd_macro_buffer, | |
136 | ((kbd_macro_bufsize *= 2) | |
137 | * sizeof (Lisp_Object))); | |
138 | kbd_macro_ptr += new - kbd_macro_buffer; | |
139 | kbd_macro_end += new - kbd_macro_buffer; | |
140 | kbd_macro_buffer = new; | |
141 | } | |
142 | *kbd_macro_ptr++ = c; | |
143 | } | |
144 | } | |
145 | ||
146 | /* Declare that all chars stored so far in the kbd macro being defined | |
147 | really belong to it. This is done in between editor commands. */ | |
148 | ||
149 | finalize_kbd_macro_chars () | |
150 | { | |
151 | kbd_macro_end = kbd_macro_ptr; | |
152 | } | |
153 | \f | |
154 | DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro, | |
155 | 0, 1, "p", | |
156 | "Call the last keyboard macro that you defined with \\[start-kbd-macro].\n\ | |
157 | \n\ | |
158 | A prefix argument serves as a repeat count. Zero means repeat until error.\n\ | |
159 | \n\ | |
160 | To make a macro permanent so you can call it even after\n\ | |
161 | defining others, use \\[name-last-kbd-macro].") | |
162 | (prefix) | |
163 | Lisp_Object prefix; | |
164 | { | |
165 | if (defining_kbd_macro) | |
166 | error ("Can't execute anonymous macro while defining one"); | |
265a9e55 | 167 | else if (NILP (Vlast_kbd_macro)) |
5a7f5d07 JB |
168 | error ("No kbd macro has been defined"); |
169 | else | |
170 | Fexecute_kbd_macro (Vlast_kbd_macro, prefix); | |
171 | return Qnil; | |
172 | } | |
173 | ||
174 | /* Restore Vexecuting_macro and executing_macro_index - called when | |
175 | the unwind-protect in Fexecute_kbd_macro gets invoked. */ | |
176 | static Lisp_Object | |
177 | pop_kbd_macro (info) | |
178 | Lisp_Object info; | |
179 | { | |
180 | Lisp_Object tem; | |
181 | Vexecuting_macro = Fcar (info); | |
182 | tem = Fcdr (info); | |
183 | executing_macro_index = XINT (tem); | |
184 | return Qnil; | |
185 | } | |
186 | ||
187 | DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0, | |
188 | "Execute MACRO as string of editor command characters.\n\ | |
189 | If MACRO is a symbol, its function definition is used.\n\ | |
190 | COUNT is a repeat count, or nil for once, or 0 for infinite loop.") | |
191 | (macro, prefixarg) | |
192 | Lisp_Object macro, prefixarg; | |
193 | { | |
194 | Lisp_Object final; | |
195 | Lisp_Object tem; | |
196 | int count = specpdl_ptr - specpdl; | |
197 | int repeat = 1; | |
198 | struct gcpro gcpro1; | |
199 | ||
265a9e55 | 200 | if (!NILP (prefixarg)) |
5a7f5d07 JB |
201 | prefixarg = Fprefix_numeric_value (prefixarg), |
202 | repeat = XINT (prefixarg); | |
203 | ||
502ddf23 | 204 | final = indirect_function (macro); |
5a7f5d07 JB |
205 | if (XTYPE (final) != Lisp_String |
206 | && XTYPE (final) != Lisp_Vector) | |
207 | error ("Keyboard macros must be strings or vectors."); | |
208 | ||
209 | XFASTINT (tem) = executing_macro_index; | |
210 | tem = Fcons (Vexecuting_macro, tem); | |
211 | record_unwind_protect (pop_kbd_macro, tem); | |
212 | ||
213 | GCPRO1 (final); | |
214 | do | |
215 | { | |
216 | Vexecuting_macro = final; | |
217 | executing_macro_index = 0; | |
218 | ||
219 | command_loop_1 (); | |
e86f81cc JB |
220 | |
221 | QUIT; | |
5a7f5d07 JB |
222 | } |
223 | while (--repeat && (XTYPE (Vexecuting_macro) == Lisp_String | |
224 | || XTYPE (Vexecuting_macro) == Lisp_Vector)); | |
225 | ||
226 | UNGCPRO; | |
227 | return unbind_to (count, Qnil); | |
228 | } | |
229 | \f | |
230 | init_macros () | |
231 | { | |
232 | Vlast_kbd_macro = Qnil; | |
233 | defining_kbd_macro = 0; | |
234 | ||
235 | Vexecuting_macro = Qnil; | |
236 | } | |
237 | ||
238 | syms_of_macros () | |
239 | { | |
240 | kbd_macro_bufsize = 100; | |
241 | kbd_macro_buffer = (Lisp_Object *) malloc (kbd_macro_bufsize | |
242 | * sizeof (Lisp_Object)); | |
243 | ||
244 | Qexecute_kbd_macro = intern ("execute-kbd-macro"); | |
245 | staticpro (&Qexecute_kbd_macro); | |
246 | ||
247 | defsubr (&Sstart_kbd_macro); | |
248 | defsubr (&Send_kbd_macro); | |
249 | defsubr (&Scall_last_kbd_macro); | |
250 | defsubr (&Sexecute_kbd_macro); | |
251 | ||
252 | DEFVAR_BOOL ("defining-kbd-macro", &defining_kbd_macro, | |
253 | "Non-nil while a keyboard macro is being defined. Don't set this!"); | |
254 | ||
255 | DEFVAR_LISP ("executing-macro", &Vexecuting_macro, | |
256 | "Currently executing keyboard macro (a string); nil if none executing."); | |
257 | ||
258 | DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro, | |
259 | "Currently executing keyboard macro (a string); nil if none executing."); | |
260 | ||
261 | DEFVAR_LISP ("last-kbd-macro", &Vlast_kbd_macro, | |
262 | "Last kbd macro defined, as a string; nil if none defined."); | |
263 | } | |
264 | ||
265 | keys_of_macros () | |
266 | { | |
267 | initial_define_key (control_x_map, ('e'), "call-last-kbd-macro"); | |
268 | initial_define_key (control_x_map, ('('), "start-kbd-macro"); | |
269 | initial_define_key (control_x_map, (')'), "end-kbd-macro"); | |
270 | } |