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