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