|
|
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 "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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.