|
|
1.1 root 1: /***************************************************************************
2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
3: * is provided to you without charge, and with no warranty. You may give *
4: * away copies of JOVE, including sources, provided that this notice is *
5: * included in all the files. *
6: ***************************************************************************/
7:
8: #include "jove.h"
9: #include "ctype.h"
10: #include "fp.h"
11: #include "chars.h"
12: #include "disp.h"
13:
14: private void
15: add_mac proto((struct macro *)),
16: del_mac proto((struct macro *)),
17: pop_macro_stack proto((void)),
18: push_macro_stack proto((struct macro *, int));
19:
20: private struct macro *mac_exists proto((char *));
21:
22: #define SAVE 01 /* this macro needs saving to a file */
23:
24: struct macro *macros = 0; /* macros */
25: int InMacDefine = NO;
26:
27: private void
28: add_mac(new)
29: struct macro *new;
30: {
31: register struct macro *mp,
32: *prev = 0;
33:
34: for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
35: if (mp == new)
36: return;
37:
38: if (prev)
39: prev->m_nextm = new;
40: else
41: macros = new;
42: new->m_nextm = 0;
43: new->Type = MACRO;
44: }
45:
46: private void
47: del_mac(mac)
48: struct macro *mac;
49: {
50: register struct macro *m;
51:
52: for (m = macros; m != 0; m = m->m_nextm)
53: if (m->m_nextm == mac) {
54: m->m_nextm = mac->m_nextm;
55: break;
56: }
57: free(mac->Name);
58: free(mac->m_body);
59: free((char *) mac);
60: }
61:
62: struct macro KeyMacro; /* Macro used for defining */
63:
64: /* To execute a macro, we have a "stack" of running macros. Whenever
65: we execute a macro, we push it on the stack, run it, then pop it
66: from the stack. */
67: struct m_thread {
68: struct m_thread *mt_prev;
69: struct macro *mt_mp;
70: int mt_offset,
71: mt_count;
72: };
73:
74: private struct m_thread *mac_stack = 0;
75:
76: private struct m_thread *
77: alloc_mthread()
78: {
79: return (struct m_thread *) emalloc(sizeof (struct m_thread));
80: }
81:
82: private void
83: free_mthread(t)
84: struct m_thread *t;
85: {
86: free((char *) t);
87: }
88:
89: void
90: unwind_macro_stack()
91: {
92: while (mac_stack != 0)
93: pop_macro_stack();
94: }
95:
96: private void
97: pop_macro_stack()
98: {
99: register struct m_thread *m;
100:
101: if ((m = mac_stack) == 0)
102: return;
103: mac_stack = m->mt_prev;
104: free_mthread(m);
105: }
106:
107: private void
108: push_macro_stack(m, count)
109: register struct macro *m;
110: int count;
111: {
112: register struct m_thread *t;
113:
114: for (t = mac_stack; t != 0; t = t->mt_prev)
115: if (t->mt_mp == m)
116: complain("[Cannot execute macro recusively]");
117: if (count <= 0)
118: complain("[Cannot execute macro a negative number of times]");
119: t = alloc_mthread();
120: t->mt_prev = mac_stack;
121: mac_stack = t;
122: t->mt_offset = 0;
123: t->mt_mp = m;
124: t->mt_count = count;
125: }
126:
127: void
128: do_macro(mac)
129: struct macro *mac;
130: {
131: push_macro_stack(mac, arg_value());
132: }
133:
134: private struct macro *
135: mac_exists(name)
136: char *name;
137: {
138: register struct macro *mp;
139:
140: for (mp = macros; mp; mp = mp->m_nextm)
141: if (strcmp(mp->Name, name) == 0)
142: return mp;
143: return 0;
144: }
145:
146: void
147: mac_init()
148: {
149: add_mac(&KeyMacro);
150: KeyMacro.Name = "keyboard-macro";
151: KeyMacro.m_len = 0;
152: KeyMacro.m_buflen = 16;
153: KeyMacro.m_body = emalloc((size_t) KeyMacro.m_buflen);
154: }
155:
156: void
157: mac_putc(c)
158: int c;
159: {
160: if (KeyMacro.m_len >= KeyMacro.m_buflen) {
161: KeyMacro.m_buflen += 16;
162: KeyMacro.m_body = realloc(KeyMacro.m_body, (size_t) KeyMacro.m_buflen);
163: if (KeyMacro.m_body == 0) {
164: KeyMacro.m_buflen = KeyMacro.m_len = 0;
165: complain("[Can't allocate storage for keyboard macro]");
166: }
167: }
168: KeyMacro.m_body[KeyMacro.m_len++] = c;
169: }
170:
171: int
172: in_macro()
173: {
174: return (mac_stack != NULL);
175: }
176:
177: int
178: mac_getc()
179: {
180: struct m_thread *mthread;
181: struct macro *m;
182:
183: if ((mthread = mac_stack) == NULL)
184: return EOF;
185: m = mthread->mt_mp;
186: if (mthread->mt_offset == m->m_len) {
187: mthread->mt_offset = 0;
188: if (--mthread->mt_count == 0)
189: pop_macro_stack();
190: return mac_getc();
191: }
192: return m->m_body[mthread->mt_offset++];
193: }
194:
195: void
196: NameMac()
197: {
198: char *name;
199: struct macro *m;
200:
201: if (KeyMacro.m_len == 0)
202: complain("[No keyboard macro to name!]");
203: if (in_macro() || InMacDefine)
204: complain("[Can't name while defining/executing]");
205: if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
206: m = (struct macro *) emalloc(sizeof *m);
207: else {
208: if (strcmp(name, KeyMacro.Name) == 0)
209: complain("[Can't name it that!]");
210: free(m->Name);
211: free(m->m_body);
212: }
213: name = copystr(name);
214: m->Type = KeyMacro.Type;
215: m->m_len = KeyMacro.m_len;
216: m->m_buflen = KeyMacro.m_buflen;
217: m->m_body = emalloc((size_t) m->m_buflen);
218: byte_copy(KeyMacro.m_body, m->m_body, (size_t) m->m_len);
219: m->m_flags = SAVE;
220: m->Name = name;
221: add_mac(m);
222: }
223:
224: void
225: RunMacro()
226: {
227: struct macro *m;
228:
229: if ((m = (struct macro *) findmac(ProcFmt)) != NULL)
230: do_macro(m);
231: }
232:
233: private void
234: pr_putc(c, fp)
235: int c;
236: File *fp;
237: {
238: if (c == '\\' || c == '^')
239: jputc('\\', fp);
240: else if (isctrl(c)) {
241: jputc('^', fp);
242: c = (c == RUBOUT) ? '?' : (c + '@');
243: }
244: jputc(c, fp);
245: }
246:
247: void
248: WriteMacs()
249: {
250: struct macro *m;
251: char *file,
252: filebuf[FILESIZE];
253: File *fp;
254: int i;
255:
256: file = ask_file((char *) 0, (char *) 0, filebuf);
257: fp = open_file(file, iobuff, F_WRITE, YES, YES);
258:
259: /* Don't write the keyboard macro which is always the first */
260: for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
261: fwritef(fp, "define-macro %s ", m->Name);
262: for (i = 0; i < m->m_len; i++)
263: pr_putc(m->m_body[i], fp);
264: jputc('\n', fp);
265: m->m_flags &= ~SAVE;
266: }
267: close_file(fp);
268: }
269:
270: void
271: DefKBDMac()
272: {
273: char *macro_name,
274: *macro_body,
275: nextc,
276: c,
277: macro_buffer[LBSIZE];
278: int i;
279: struct macro *m;
280:
281: macro_name = do_ask(" \r\n", (int (*) proto((int))) 0, (char *) 0,
282: ProcFmt);
283: if (macro_name == 0)
284: complain("[No default]");
285: macro_name = copystr(macro_name);
286: if ((m = mac_exists(macro_name)) != NULL)
287: del_mac(m);
288: macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name);
289: i = 0;
290: while ((c = *macro_body++) != '\0') {
291: if (c == '\\') {
292: if ((nextc = *macro_body++) == LF)
293: complain("[Premature end of line]");
294: c = nextc;
295: } else if (c == '^') {
296: if ((nextc = *macro_body++) == '?')
297: c = RUBOUT;
298: else if (isalpha(nextc) || strchr("@[\\]^_", nextc))
299: c = CTL(nextc);
300: else
301: complain("Bad control-character: '%c'", nextc);
302: }
303: macro_buffer[i++] = c;
304: }
305: m = (struct macro *) emalloc(sizeof (*m));
306: m->Name = macro_name;
307: m->m_len = m->m_buflen = i;
308: m->m_body = emalloc((size_t) i);
309: m->m_flags = InJoverc ? 0 : SAVE;
310: byte_copy(macro_buffer, m->m_body, (size_t) i);
311: add_mac(m);
312: }
313:
314: void
315: Remember()
316: {
317: /* We're already executing the macro; ignore any attempts
318: to define the keyboard macro while we are executing. */
319: if (in_macro())
320: return;
321: if (InMacDefine)
322: message("[Already defining ... continue with definition]");
323: else {
324: UpdModLine = YES;
325: InMacDefine = YES;
326: KeyMacro.m_len = 0;
327: message("Defining...");
328: }
329: }
330:
331: void
332: Forget()
333: {
334: char *cp;
335: struct macro *m = &KeyMacro;
336:
337: UpdModLine = YES;
338: if (InMacDefine) {
339: message("Keyboard macro defined.");
340: InMacDefine = NO;
341:
342: /* try and strip off the key sequence that invoked us */
343: cp = &m->m_body[m->m_len - 2];
344: if (PrefChar(*cp))
345: m->m_len -= 2;
346: else if (commands[cp[1]].c_proc == Forget)
347: m->m_len -= 1;
348: } else
349: complain("[end-kbd-macro: not currently defining macro!]");
350: }
351:
352: void
353: ExecMacro()
354: {
355: do_macro(&KeyMacro);
356: }
357:
358: void
359: MacInter()
360: {
361: if (!Asking)
362: return;
363: Interactive = 1;
364: }
365:
366: int
367: ModMacs()
368: {
369: register struct macro *m;
370:
371: for (m = macros->m_nextm; m != 0; m = m->m_nextm)
372: if (m->m_flags & SAVE)
373: return YES;
374: return NO;
375: }
376:
377: data_obj *
378: findmac(prompt)
379: char *prompt;
380: {
381: char *strings[100];
382: register char **strs = strings;
383: register int com;
384: register struct macro *m = macros;
385:
386: for (; m != 0; m = m->m_nextm)
387: *strs++ = m->Name;
388: *strs = 0;
389:
390: if ((com = complete(strings, prompt, NOTHING)) < 0)
391: return 0;
392: m = macros;
393: while (--com >= 0)
394: m = m->m_nextm;
395: return (data_obj *) m;
396: }
397:
398: void
399: DelMacro()
400: {
401: struct macro *m;
402:
403: if ((m = (struct macro *) findmac(ProcFmt)) == 0)
404: return;
405: if (m == &KeyMacro)
406: complain("[It's illegal to delete the keyboard-macro!]");
407: del_mac(m);
408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.