Mercurial > hg > xemacs-beta
comparison src/macros.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 859a2309aef8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Keyboard macros. | |
2 Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: FSF 19.30. */ | |
22 | |
23 /* A keyboard macro is a string of ASCII characters, or a vector of event | |
24 objects. Only key-press, mouse-press, mouse-release, and menu-selection | |
25 events ever get into a keyboard macro. | |
26 | |
27 When interactively defining a keyboard macro, it will always be a vector | |
28 of events; strings may be executed for backwards compatibility. | |
29 */ | |
30 | |
31 #include <config.h> | |
32 #include "lisp.h" | |
33 #include "events.h" | |
34 #include "macros.h" | |
35 #include "commands.h" | |
36 #include "console.h" | |
37 #include "buffer.h" | |
38 #include "window.h" | |
39 #include "frame.h" | |
40 #include "keymap.h" | |
41 | |
42 Lisp_Object Qexecute_kbd_macro; | |
43 | |
44 /* The current macro and our position in it. When executing nested kbd | |
45 macros, previous values for these are wound through the execution stack | |
46 with unwind-protect. | |
47 */ | |
48 Lisp_Object Vexecuting_macro; | |
49 int executing_macro_index; | |
50 | |
51 | |
52 DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 1, "P" /* | |
53 Record subsequent keyboard and menu input, defining a keyboard macro. | |
54 The commands are recorded even as they are executed. | |
55 Use \\[end-kbd-macro] to finish recording and make the macro available. | |
56 Use \\[name-last-kbd-macro] to give it a permanent name. | |
57 Non-nil arg (prefix arg) means append to last macro defined; | |
58 This begins by re-executing that macro as if you typed it again. | |
59 */ ) | |
60 (append) | |
61 Lisp_Object append; | |
62 { | |
63 /* This function can GC */ | |
64 struct console *con = XCONSOLE (Vselected_console); | |
65 if (!NILP (con->defining_kbd_macro)) | |
66 error ("Already defining kbd macro"); | |
67 | |
68 if (NILP (con->kbd_macro_builder)) | |
69 con->kbd_macro_builder = make_vector (30, Qnil); | |
70 | |
71 zmacs_region_stays = 1; /* set this before calling Fexecute_kbd_macro() | |
72 so that functions there can override */ | |
73 MARK_MODELINE_CHANGED; | |
74 if (NILP (append)) | |
75 { | |
76 con->kbd_macro_ptr = 0; | |
77 con->kbd_macro_end = 0; | |
78 message ("Defining kbd macro..."); | |
79 } | |
80 else | |
81 { | |
82 message ("Appending to kbd macro..."); | |
83 con->kbd_macro_ptr = con->kbd_macro_end; | |
84 Fexecute_kbd_macro (con->last_kbd_macro, make_int (1)); | |
85 } | |
86 con->defining_kbd_macro = Qt; | |
87 | |
88 return Qnil; | |
89 } | |
90 | |
91 DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 1, "P" /* | |
92 Finish defining a keyboard macro. | |
93 The definition was started by \\[start-kbd-macro]. | |
94 The macro is now available for use via \\[call-last-kbd-macro], | |
95 or it can be given a name with \\[name-last-kbd-macro] and then invoked | |
96 under that name. | |
97 | |
98 With numeric arg, repeat macro now that many times, | |
99 counting the definition just completed as the first repetition. | |
100 An argument of zero means repeat until error. | |
101 */ ) | |
102 (arg) | |
103 Lisp_Object arg; | |
104 { | |
105 /* This function can GC */ | |
106 struct console *con = XCONSOLE (Vselected_console); | |
107 int repeat; | |
108 | |
109 if (NILP (con->defining_kbd_macro)) | |
110 error ("Not defining kbd macro."); | |
111 | |
112 if (NILP (arg)) | |
113 repeat = -1; | |
114 else | |
115 repeat = XINT (Fprefix_numeric_value (arg)); | |
116 | |
117 if (!NILP (con->defining_kbd_macro)) | |
118 { | |
119 int i; | |
120 int size = con->kbd_macro_end; | |
121 con->last_kbd_macro = make_vector (size, Qnil); | |
122 for (i = 0; i < con->kbd_macro_end; i++) | |
123 vector_data (XVECTOR (con->last_kbd_macro)) [i] = | |
124 vector_data (XVECTOR (con->kbd_macro_builder)) [i]; | |
125 con->defining_kbd_macro = Qnil; | |
126 MARK_MODELINE_CHANGED; | |
127 message ("Keyboard macro defined"); | |
128 } | |
129 | |
130 zmacs_region_stays = 1; /* set this before calling Fexecute_kbd_macro() | |
131 so that functions there can override */ | |
132 if (repeat < 0) | |
133 return Qnil; | |
134 else if (repeat == 0) | |
135 return Fexecute_kbd_macro (con->last_kbd_macro, Qzero); | |
136 else | |
137 return Fexecute_kbd_macro (con->last_kbd_macro, | |
138 make_int (repeat - 1)); | |
139 } | |
140 | |
141 | |
142 /* Store event into kbd macro being defined | |
143 */ | |
144 void | |
145 store_kbd_macro_event (Lisp_Object event) | |
146 { | |
147 struct console *con = event_console_or_selected (event); | |
148 | |
149 if (con->kbd_macro_ptr == XVECTOR (con->kbd_macro_builder)->size) | |
150 { | |
151 int i; | |
152 int old_size = XVECTOR (con->kbd_macro_builder)->size; | |
153 int new_size = old_size * 2; | |
154 Lisp_Object new = make_vector (new_size, Qnil); | |
155 for (i = 0; i < old_size; i++) | |
156 vector_data (XVECTOR (new)) [i] = | |
157 vector_data (XVECTOR (con->kbd_macro_builder)) [i]; | |
158 con->kbd_macro_builder = new; | |
159 } | |
160 vector_data (XVECTOR (con->kbd_macro_builder)) [con->kbd_macro_ptr++] = | |
161 Fcopy_event (event, Qnil); | |
162 } | |
163 | |
164 /* Extract the next kbd-macro element into the given event. | |
165 If we're done, throws to the catch in Fexecute_kbd_macro(). | |
166 */ | |
167 void | |
168 pop_kbd_macro_event (Lisp_Object event) | |
169 { | |
170 if (NILP (Vexecuting_macro)) abort (); | |
171 | |
172 if (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)) | |
173 { | |
174 if (executing_macro_index < XINT (Flength (Vexecuting_macro))) | |
175 { | |
176 nth_of_key_sequence_as_event (Vexecuting_macro, | |
177 executing_macro_index++, | |
178 event); | |
179 return; | |
180 } | |
181 } | |
182 else if (!EQ (Vexecuting_macro, Qt)) /* Some things replace the macro | |
183 with Qt to force an early exit. */ | |
184 error ("junk in executing-macro"); | |
185 | |
186 Fthrow (Qexecute_kbd_macro, Qt); | |
187 } | |
188 | |
189 | |
190 /* Declare that all chars stored so far in the kbd macro being defined | |
191 really belong to it. This is done in between editor commands. */ | |
192 | |
193 void | |
194 finalize_kbd_macro_chars (struct console *con) | |
195 { | |
196 con->kbd_macro_end = con->kbd_macro_ptr; | |
197 } | |
198 | |
199 DEFUN ("cancel-kbd-macro-events", Fcancel_kbd_macro_events, | |
200 Scancel_kbd_macro_events, 0, 0, 0 /* | |
201 Cancel the events added to a keyboard macro for this command. | |
202 */ ) | |
203 () | |
204 { | |
205 struct console *con = XCONSOLE (Vselected_console); | |
206 | |
207 con->kbd_macro_ptr = con->kbd_macro_end; | |
208 | |
209 return Qnil; | |
210 } | |
211 | |
212 DEFUN ("call-last-kbd-macro", Fcall_last_kbd_macro, Scall_last_kbd_macro, | |
213 0, 1, "p" /* | |
214 Call the last keyboard macro that you defined with \\[start-kbd-macro]. | |
215 | |
216 A prefix argument serves as a repeat count. Zero means repeat until error. | |
217 | |
218 To make a macro permanent so you can call it even after | |
219 defining others, use \\[name-last-kbd-macro]. | |
220 */ ) | |
221 (prefix) | |
222 Lisp_Object prefix; | |
223 { | |
224 /* This function can GC */ | |
225 struct console *con = XCONSOLE (Vselected_console); | |
226 | |
227 if (!NILP (con->defining_kbd_macro)) | |
228 error ("Can't execute anonymous macro while defining one"); | |
229 else if (NILP (con->last_kbd_macro)) | |
230 error ("No kbd macro has been defined"); | |
231 else | |
232 Fexecute_kbd_macro (con->last_kbd_macro, prefix); | |
233 return Qnil; | |
234 } | |
235 | |
236 /* Restore Vexecuting_macro and executing_macro_index - called when | |
237 the unwind-protect in Fexecute_kbd_macro gets invoked. */ | |
238 static Lisp_Object | |
239 pop_kbd_macro (Lisp_Object info) | |
240 { | |
241 Lisp_Object tem; | |
242 Vexecuting_macro = Fcar (info); | |
243 tem = Fcdr (info); | |
244 executing_macro_index = XINT (tem); | |
245 return Qnil; | |
246 } | |
247 | |
248 DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 2, 0 /* | |
249 Execute MACRO as string of editor command characters. | |
250 If MACRO is a symbol, its function definition is used. | |
251 COUNT is a repeat count, or nil for once, or 0 for infinite loop. | |
252 */ ) | |
253 (macro, prefixarg) | |
254 Lisp_Object macro, prefixarg; | |
255 { | |
256 /* This function can GC */ | |
257 Lisp_Object final; | |
258 Lisp_Object tem; | |
259 int speccount = specpdl_depth (); | |
260 int repeat = 1; | |
261 struct gcpro gcpro1; | |
262 struct console *con = XCONSOLE (Vselected_console); | |
263 | |
264 if (!NILP (prefixarg)) | |
265 { | |
266 prefixarg = Fprefix_numeric_value (prefixarg); | |
267 repeat = XINT (prefixarg); | |
268 } | |
269 | |
270 final = indirect_function (macro, 1); | |
271 if (!STRINGP (final) && !VECTORP (final)) | |
272 error ("Keyboard macros must be strings or vectors."); | |
273 | |
274 tem = Fcons (Vexecuting_macro, make_int (executing_macro_index)); | |
275 record_unwind_protect (pop_kbd_macro, tem); | |
276 | |
277 GCPRO1 (final); | |
278 do | |
279 { | |
280 Vexecuting_macro = final; | |
281 executing_macro_index = 0; | |
282 con->prefix_arg = Qnil; | |
283 internal_catch (Qexecute_kbd_macro, call_command_loop, | |
284 Qnil, 0); | |
285 } | |
286 while (--repeat != 0 | |
287 && (STRINGP (Vexecuting_macro) || | |
288 VECTORP (Vexecuting_macro))); | |
289 | |
290 UNGCPRO; | |
291 return unbind_to (speccount, Qnil); | |
292 } | |
293 | |
294 | |
295 void | |
296 syms_of_macros (void) | |
297 { | |
298 defsubr (&Sstart_kbd_macro); | |
299 defsubr (&Send_kbd_macro); | |
300 defsubr (&Scall_last_kbd_macro); | |
301 defsubr (&Sexecute_kbd_macro); | |
302 defsubr (&Scancel_kbd_macro_events); | |
303 defsymbol (&Qexecute_kbd_macro, "execute-kbd-macro"); | |
304 } | |
305 | |
306 void | |
307 vars_of_macros (void) | |
308 { | |
309 DEFVAR_LISP ("executing-macro", &Vexecuting_macro /* | |
310 Currently executing keyboard macro (a vector of events or string); | |
311 nil if none executing. | |
312 */ ); | |
313 | |
314 DEFVAR_LISP ("executing-kbd-macro", &Vexecuting_macro /* | |
315 Currently executing keyboard macro (a vector of events or string); | |
316 nil if none executing. | |
317 */ ); | |
318 } | |
319 | |
320 void | |
321 init_macros (void) | |
322 { | |
323 Vexecuting_macro = Qnil; | |
324 } | |
325 |