1 /*-
2 * Copyright (c) 2002 Jordan DeLong
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of contributors may be
14 * used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 #include "editor.h"
30
31 /* macro flags */
32 int macro_playing;
33 int macro_repeating;
34 int macro_repeatplay;
35 int macro_recording;
36
37 /* the macro recording buffer */
38 static int rsize;
39 static int rlength;
40 static int rpos;
41 static int *record;
42
43 /* key to be repeated by the key repeater */
44 static int rkey;
45
46 /*
47 * flag if the keyrepeater is being set up; used to
48 * prevent infinite an infinite loop if people do
49 * dumb stuff.
50 */
51 static int gettingrepkey;
52
53 /* initialize the macro recording stuff */
macro_init()54 void macro_init() {
55 record = ckmalloc(LINE_STARTSIZE * sizeof(int));
56 rsize = LINE_STARTSIZE;
57 }
58
59 /* free memory */
macro_shutdown()60 void macro_shutdown() {
61 free(record);
62 }
63
64 /*
65 * add a key to the macro recording, and return the key that the
66 * calling process should use.
67 */
macro_recordkey(int keysym)68 int macro_recordkey(int keysym) {
69 if (keysym == KEYSYM_RECORD || keysym == KEYSYM_PLAYBACK) {
70 minibuff_printf("Macro recording stopped.");
71 macro_recording = 0;
72 /*
73 * this is neccesary to prevent an infinite loop if
74 * someone tries to repeat a macro that ends with
75 * an unfinished repeat command.
76 */
77 if (gettingrepkey)
78 keysym = KEYSYM_CANCEL;
79 else
80 return KEYSYM_NOP;
81 }
82
83 if (rlength + 1 >= rsize) {
84 rsize *= 2;
85 record = ckrealloc(record, rsize * sizeof(int));
86 }
87 record[rlength++] = keysym;
88
89 return keysym;
90 }
91
92 /*
93 * return a key from the macro system; either from the key repeater
94 * or from a playing keyboard macro.
95 */
macro_getkey()96 int macro_getkey() {
97 int c;
98
99 if (macro_repeating) {
100 if (--macro_repeating == 0)
101 input_nodraw--;
102 return rkey;
103 }
104
105 assert(macro_playing && !macro_recording);
106 c = record[rpos++];
107 if (rpos >= rlength) {
108 macro_playing = 0;
109 input_nodraw--;
110 }
111 return c;
112 }
113
114 /* input callback for minibuff repeat prompt */
repcback(vminibuff_t * v,int keysym)115 static int repcback(vminibuff_t *v, int keysym) {
116 if (isdigit(keysym) || keysym == KEYSYM_CANCEL)
117 return 0;
118 else {
119 rkey = keysym;
120 vminibuff_exit(v);
121 }
122
123 return 1;
124 }
125
macro_repeat()126 void macro_repeat() {
127 u_char *repstr;
128
129 /* figure out what to repeat and how many times */
130 repstr = minibuff_cbprompt("Repeat", NULL, repcback, NULL);
131 if (!repstr)
132 return;
133
134 /*
135 * because macros may want to use the key repeater, if you
136 * try to repeat a macro with the repeater it is neccesary
137 * to use a seperate counter to do it.
138 */
139 if (rkey == KEYSYM_PLAYBACK)
140 macro_repeatplay = atoi(repstr);
141 else
142 macro_repeating = atoi(repstr);
143 if (macro_repeating || macro_repeatplay)
144 input_nodraw++;
145 free(repstr);
146 }
147
macro_record()148 void macro_record() {
149 minibuff_printf("Macro recording started.");
150 rlength = 0;
151 macro_recording = 1;
152 }
153
macro_playback()154 void macro_playback() {
155 if (rlength) {
156 rpos = 0;
157 macro_playing = 1;
158 input_nodraw++;
159 } else
160 minibuff_printf("No macro to play.");
161 }
162