/* Jonathan Payne at Lincoln-Sudbury Regional High School 4-19-83 jove_funcs.c This is like the second half of jove_extend.c. It was divided because the file was taking too long to compile ... */ #include "jove.h" static int nfuncs = 0, nmacros = 0, nvars = 0; struct function functions[NFUNCS], /* Wired functions */ macros[NMACROS], /* Macros */ variables[NVARS]; /* Variables */ tmany(str) char *str; { complain("too many %s", str); } DefFunc(name, func) char *name; int (*func)(); { if (nfuncs >= NFUNCS) tmany("functions"); functions[nfuncs].f_name = name; functions[nfuncs].f.Func = func; functions[nfuncs].f_type = FUNCTION; nfuncs++; } DefVar(name, varptr) char *name; int *varptr; { if (nvars >= NVARS) tmany("variables"); variables[nvars].f_name = name; variables[nvars].f.Var = varptr; variables[nvars].f_type = VARIABLE; nvars++; } DefMac(name, macptr) char *name; struct macro *macptr; { if (nmacros > NVARS) tmany("macros"); macros[nmacros].f_name = name; macros[nmacros].f.Macro = macptr; macros[nmacros].f_type = MACRO; nmacros++; } extern int EscPrefix(), CtlxPrefix(), AppReg(), Apropos(), BackChar(), Bparen(), BackWord(), Bof(), Bol(), Bos(), Bow(), BindAKey(), BindMac(), BufPos(), UnBound(), CasRegLower(), CasRegUpper(), CapWord(), LowWord(), UppWord(), ChrToOct(), ClAndRedraw(), MakeErrors(), CopyRegion(), CTab(), DelBlnkLines(), DelNChar(), DelNWord(), OneWindow(), DelPChar(), DelPWord(), DelReg(), DelWtSpace(), DelCurWindow(), KeyDesc(), DescCom(), Eof(), Eol(), Eos(), Eow(), BufErase(), PtToMark(), Extend(), ExecMacro(), RunMacro(), Leave(), RegToShell(), FindFile(), WindFind(), FindTag(), ToIndent(), ForChar(), Fparen(), ForWord(), FourTime(), GoLine(), GrowWindow(), IncFSearch(), IncRSearch(), InsFile(), InitBindings(), Justify(), BufKill(), KillEOL(), BufList(), NotModified(), NameMac(), Newline(), OpenLine(), LineAI(), NextError(), NextLine(), NextPage(), NextWindow(), OverWrite(), PopMark(), PageNWind(), DoParen(), CParse(), LintParse(), PauseJove(), PrevLine(), PrevPage(), PrevWindow(), QRepSearch(), QuotChar(), ReadFile(), ReadMacs(), RedrawDisplay(), ReInitTTY(), RepSearch(), Beep(), DownScroll(), UpScroll(), ForSearch(), RevSearch(), SelBuf(), SelfInsert(), SetVar(), SetMark(), ShellCom(), ShToBuf(), ShrWindow(), Source(), SpellCom(), SplitWind(), Remember(), Forget(), StrLength(), PauseJove(), TextInsert(), TransChar(), UnBound(), VtKeys(), SaveFile(), WtModBuf(), WriteFile(), WriteMacs(), WrtReg(), Yank(), YankPop(), PrVar(), SetQchars(), WNumLines(); InitFuncs() { DefFunc("Prefix-1", EscPrefix); DefFunc("Prefix-2", CtlxPrefix); DefFunc("append-region", AppReg); DefFunc("apropos", Apropos); DefFunc("backward-char", BackChar); DefFunc("backward-paren", Bparen); DefFunc("backward-word", BackWord); DefFunc("beginning-of-file", Bof); DefFunc("beginning-of-line", Bol); DefFunc("beginning-of-sentence", Bos); DefFunc("beginning-of-window", Bow); DefFunc("bind-to-key", BindAKey); DefFunc("bind-macro-to-key", BindMac); DefFunc("buffer-position", BufPos); DefFunc("case-region-lower", CasRegLower); DefFunc("case-region-upper", CasRegUpper); DefFunc("case-word-capitalize", CapWord); DefFunc("case-word-lower", LowWord); DefFunc("case-word-upper", UppWord); DefFunc("char-to-octal-insert", ChrToOct); DefFunc("clear-and-redraw", ClAndRedraw); DefFunc("compile-it", MakeErrors); DefFunc("copy-region", CopyRegion); DefFunc("c-tab", CTab); DefFunc("delete-blank-lines-around-point", DelBlnkLines); DefFunc("delete-next-char", DelNChar); DefFunc("delete-next-word", DelNWord); DefFunc("delete-other-windows", OneWindow); DefFunc("delete-previous-char", DelPChar); DefFunc("delete-previous-word", DelPWord); DefFunc("delete-to-killbuffer", DelReg); DefFunc("delete-white-space", DelWtSpace); DefFunc("delete-current-window", DelCurWindow); DefFunc("describe-key", KeyDesc); DefFunc("describe-command", DescCom); DefFunc("end-of-file", Eof); DefFunc("end-of-line", Eol); DefFunc("end-of-sentence", Eos); DefFunc("end-of-window", Eow); DefFunc("erase-buffer", BufErase); DefFunc("exchange-point-and-mark", PtToMark); DefFunc("execute-extended-command", Extend); DefFunc("execute-keyboard-macro", ExecMacro); DefFunc("execute-macro", RunMacro); DefFunc("exit-jove", Leave); DefFunc("filter-region", RegToShell); DefFunc("find-file", FindFile); DefFunc("find-file-in-other-window", WindFind); DefFunc("find-tag", FindTag); DefFunc("first-non-blank", ToIndent); DefFunc("forward-char", ForChar); DefFunc("forward-paren", Fparen); DefFunc("forward-word", ForWord); DefFunc("four-times", FourTime); DefFunc("goto-line", GoLine); DefFunc("grow-window", GrowWindow); DefFunc("i-search-forward", IncFSearch); DefFunc("i-search-reverse", IncRSearch); DefFunc("insert-file", InsFile); DefFunc("init-bindings", InitBindings); DefFunc("justify-paragraph", Justify); DefFunc("kill-buffer", BufKill); DefFunc("kill-to-end-of-line", KillEOL); DefFunc("list-buffers", BufList); DefFunc("make-buffer-unmodified", NotModified); DefFunc("name-keyboard-macro", NameMac); DefFunc("newline", Newline); DefFunc("newline-and-backup", OpenLine); DefFunc("newline-and-indent", LineAI); DefFunc("next-error", NextError); DefFunc("next-line", NextLine); DefFunc("next-page", NextPage); DefFunc("next-window", NextWindow); DefFunc("number-lines-in-window", WNumLines); DefFunc("replace-char", OverWrite); DefFunc("page-next-window", PageNWind); DefFunc("paren-flash", DoParen); DefFunc("parse-C-errors", CParse); DefFunc("parse-LINT-errors", LintParse); DefFunc("pause-jove", PauseJove); DefFunc("pop-mark", PopMark); DefFunc("previous-line", PrevLine); DefFunc("previous-page", PrevPage); DefFunc("previous-window", PrevWindow); DefFunc("print", PrVar); DefFunc("query-replace-search", QRepSearch); DefFunc("quote-char", QuotChar); DefFunc("read-file", ReadFile); DefFunc("read-macros-from-file", ReadMacs); DefFunc("redraw-display", RedrawDisplay); DefFunc("reinitialize-terminal", ReInitTTY); DefFunc("replace-search", RepSearch); DefFunc("ring-the-bell", Beep); DefFunc("scroll-down", DownScroll); DefFunc("scroll-up", UpScroll); DefFunc("search-forward", ForSearch); DefFunc("search-reverse", RevSearch); DefFunc("select-buffer", SelBuf); DefFunc("self-insert", SelfInsert); DefFunc("set", SetVar); DefFunc("set-mark", SetMark); DefFunc("set-quote-characters", SetQchars); DefFunc("shell-command", ShellCom); DefFunc("shell-command-to-buffer", ShToBuf); DefFunc("shrink-window", ShrWindow); DefFunc("source", Source); DefFunc("spell-buffer", SpellCom); DefFunc("split-current-window", SplitWind); DefFunc("start-remembering", Remember); DefFunc("stop-remembering", Forget); /* Not bad */ DefFunc("string-length", StrLength); DefFunc("suspend-jove", PauseJove); DefFunc("text-insert", TextInsert); DefFunc("transpose-chars", TransChar); DefFunc("unbound", UnBound); DefFunc("vt100-arrow-keys", VtKeys); DefFunc("write-current-file", SaveFile); DefFunc("write-macros-to-file", WriteMacs); DefFunc("write-modified-files", WtModBuf); DefFunc("write-named-file", WriteFile); DefFunc("write-region", WrtReg); DefFunc("yank", Yank); DefFunc("yank-pop", YankPop); DefFunc((char *) 0, (int (*)()) 0); DefVar("allow-^S-and-^Q", &OKXonXoff); DefVar("auto-indent", &globflags[AUTOIND]); DefVar("c-mode", &globflags[CMODE]); DefVar("case-independent-search", &globflags[CASEIND]); DefVar("files-should-end-with-newline", &EndWNewline); DefVar("internal-tabstop", &tabstop); DefVar("magic", &globflags[MAGIC]); DefVar("make-all-at-once", &MakeAll); DefVar("over-write", &globflags[OVERWRITE]); DefVar("physical-tabstop", &phystab); DefVar("right-margin", &RMargin); DefVar("show-match", &globflags[MATCHING]); DefVar("scroll-step", &ScrollStep); DefVar("text-fill", &globflags[TEXTFILL]); DefVar("use-temporary-buffers", &UseBuffers); DefVar("visible-bell", &VisBell); DefVar("write-files-on-make", &WtOnMk); DefVar((char *) 0, (int *) 0); }; struct function * FindFunc(func) register int (*func)(); { register struct function *fp; for (fp = functions; fp->f_name; fp++) if (fp->f_type == FUNCTION && fp->f.Func == func) return fp; return 0; } BindFunc(map, letter, func) struct function *map[]; int (*func)(); { static struct function *fp = 0; if (!fp || fp->f.Func != func) fp = FindFunc(func); map[letter] = fp; } ZeroMap(map) struct function *map[]; { int i; for (i = 0; i < 0200; i++) map[i] = 0; } BindInserts(func) FUNC func; { register int i; for (i = ' '; i < 0177; i++) BindFunc(mainmap, i, func); BindFunc(mainmap, CTL(I), func); } InitBindings() { BindInserts(SelfInsert); /* Most just insert themselves */ BindFunc(mainmap, CTL(@), SetMark); BindFunc(mainmap, CTL(A), Bol); BindFunc(mainmap, CTL(B), BackChar); BindFunc(mainmap, CTL(C), UnBound); BindFunc(mainmap, CTL(D), DelNChar); BindFunc(mainmap, CTL(E), Eol); BindFunc(mainmap, CTL(F), ForChar); BindFunc(mainmap, CTL(G), Beep); BindFunc(mainmap, CTL(H), DelPChar); BindFunc(mainmap, CTL(I), CTab); BindFunc(mainmap, CTL(J), LineAI); BindFunc(mainmap, CTL(K), KillEOL); BindFunc(mainmap, CTL(L), RedrawDisplay); BindFunc(mainmap, CTL(M), Newline); BindFunc(mainmap, CTL(N), NextLine); BindFunc(mainmap, CTL(O), OpenLine); BindFunc(mainmap, CTL(P), PrevLine); BindFunc(mainmap, CTL(Q), QuotChar); BindFunc(mainmap, CTL(^), QuotChar); BindFunc(mainmap, CTL(R), RevSearch); BindFunc(mainmap, CTL(S), ForSearch); BindFunc(mainmap, CTL(\\), ForSearch); BindFunc(mainmap, CTL(T), TransChar); BindFunc(mainmap, CTL(U), FourTime); BindFunc(mainmap, CTL(V), NextPage); BindFunc(mainmap, CTL(W), DelReg); BindFunc(mainmap, CTL(X), CtlxPrefix); BindFunc(mainmap, CTL(Y), Yank); BindFunc(mainmap, CTL(Z), UpScroll); BindFunc(mainmap, CTL([), EscPrefix); BindFunc(mainmap, ')', DoParen); BindFunc(mainmap, '}', DoParen); BindFunc(mainmap, '\177', DelPChar); BindFunc(pref1map, CTL(B), Bparen); BindFunc(pref1map, CTL(F), Fparen); BindFunc(pref1map, CTL(L), ClAndRedraw); BindFunc(pref1map, CTL(V), PageNWind); BindFunc(pref1map, '>', Eof); BindFunc(pref1map, '<', Bof); BindFunc(pref1map, 'a', Bos); BindFunc(pref1map, 'A', Bos); BindFunc(pref1map, 'B', BackWord); BindFunc(pref1map, 'b', BackWord); BindFunc(pref1map, 'C', CapWord); BindFunc(pref1map, 'c', CapWord); BindFunc(pref1map, 'D', DelNWord); BindFunc(pref1map, 'd', DelNWord); BindFunc(pref1map, 'E', Eos); BindFunc(pref1map, 'e', Eos); BindFunc(pref1map, 'F', ForWord); BindFunc(pref1map, 'f', ForWord); BindFunc(pref1map, 'G', GoLine); BindFunc(pref1map, 'g', GoLine); BindFunc(pref1map, 'J', Justify); BindFunc(pref1map, 'j', Justify); BindFunc(pref1map, 'L', LowWord); BindFunc(pref1map, 'l', LowWord); BindFunc(pref1map, 'M', ToIndent); BindFunc(pref1map, 'm', ToIndent); BindFunc(pref1map, 'Q', QRepSearch); BindFunc(pref1map, 'q', QRepSearch); BindFunc(pref1map, 'R', RepSearch); BindFunc(pref1map, 'r', RepSearch); BindFunc(pref1map, 'V', PrevPage); BindFunc(pref1map, 'v', PrevPage); BindFunc(pref1map, 'U', UppWord); BindFunc(pref1map, 'u', UppWord); BindFunc(pref1map, 'W', CopyRegion); BindFunc(pref1map, 'w', CopyRegion); BindFunc(pref1map, 'X', Extend); BindFunc(pref1map, 'x', Extend); BindFunc(pref1map, 'Y', YankPop); BindFunc(pref1map, 'y', YankPop); BindFunc(pref1map, 'Z', DownScroll); BindFunc(pref1map, 'z', DownScroll); BindFunc(pref1map, '[', VtKeys); /* Vt100 arrows */ BindFunc(pref1map, '\177', DelPWord); BindFunc(pref1map, '\\', DelWtSpace); BindFunc(pref1map, '~', NotModified); BindFunc(pref1map, '.', Eow); BindFunc(pref1map, ',', Bow); /* CTLX prefix */ ZeroMap(pref2map); BindFunc(pref2map, CTL(B), BufList); BindFunc(pref2map, CTL(C), Leave); BindFunc(pref2map, CTL(E), MakeErrors); BindFunc(pref2map, CTL(F), FindFile); BindFunc(pref2map, CTL(I), InsFile); BindFunc(pref2map, CTL(L), CasRegLower); BindFunc(pref2map, CTL(M), WtModBuf); BindFunc(pref2map, CTL(N), NextError); BindFunc(pref2map, CTL(O), DelBlnkLines); BindFunc(pref2map, CTL(R), ReadFile); BindFunc(pref2map, CTL(S), SaveFile); BindFunc(pref2map, CTL(U), CasRegUpper); BindFunc(pref2map, CTL(W), WriteFile); BindFunc(pref2map, CTL(X), PtToMark); BindFunc(pref2map, CTL(\\), SaveFile); BindFunc(pref2map, '1', OneWindow); BindFunc(pref2map, '2', SplitWind); BindFunc(pref2map, '4', WindFind); BindFunc(pref2map, 'B', SelBuf); BindFunc(pref2map, 'b', SelBuf); BindFunc(pref2map, 'c', StrLength); BindFunc(pref2map, 'C', StrLength); BindFunc(pref2map, 'D', DelCurWindow); BindFunc(pref2map, 'd', DelCurWindow); BindFunc(pref2map, 'K', BufKill); BindFunc(pref2map, 'k', BufKill); BindFunc(pref2map, 'N', NextWindow); BindFunc(pref2map, 'n', NextWindow); BindFunc(pref2map, 'O', PrevWindow); BindFunc(pref2map, 'o', PrevWindow); BindFunc(pref2map, 'P', PrevWindow); BindFunc(pref2map, 'p', PrevWindow); BindFunc(pref2map, 'T', FindTag); BindFunc(pref2map, 't', FindTag); BindFunc(pref2map, '!', ShellCom); BindFunc(pref2map, '^', GrowWindow); } char * FuncName() { static char func[60]; return sprintf(func, ": %s ", LastFunc->f_name); } int Interactive; /* True when we invoke with the command handler? */ ExecFunc(fp, interactive) struct function *fp; { int bindinteract = Interactive; Interactive = interactive; LastFunc = fp; switch (fp->f_type) { case MACRO: DoMacro(fp->f.Macro); break; case FUNCTION: if (fp->f.Func) (*fp->f.Func)(); } Interactive = bindinteract; } /* Can only define the keyboard macro. IT can be renamed to another * macro. If the keyboard macro is renamed, we make a copy of it. * The keyboard macro is ALWAYS the keyboard macro. * * We can't define or run the same macro recursively. Each macro has * a bit saying whether or not it is currently being executed/defined. */ struct macro KeyMacro; /* Macro used for defining */ struct macro *macstack[NMACROS]; int stackp = 0; char *rem = "remember"; FixMacros() { register int i; struct macro *mp; for (i = 0; macstack[i]; i++) { mp = macstack[i]; macstack[i] = 0; mp->Flags = mp->Offset = 0; } stackp = -1; KeyMacro.Flags = KeyMacro.Offset = 0; } MacErr(name1, name2) char *name1, *name2; { KeyMacro.Flags = 0; MacNolen(&KeyMacro); complain("Can't %s recursively; no longer %sing", name1, name2); } Remember() { if (KeyMacro.Flags & DEFINE) MacErr(rem, rem); KeyMacro.Flags |= DEFINE; MacNolen(&KeyMacro); message("Remembering..."); } /* Is `c' a prefix character */ PrefChar(c) { return (mainmap[c]->f.Func == EscPrefix || mainmap[c]->f.Func == CtlxPrefix); } Forget() { char *cp; struct macro *m = &KeyMacro; if (m->Flags & DEFINE) { message("Keyboard macro defined"); m->Flags &= ~DEFINE; cp = &m->Body[m->MacLength - 2]; if (PrefChar(*cp)) m->MacLength -= 2; else if (functions[*++cp].f.Func == Forget) m->MacLength--; } } ExecMacro() { DoMacro(&KeyMacro); } DoMacro(mac) struct macro *mac; { if (mac->Flags & DEFINE) MacErr("define", rem); if (mac->Flags & EXECUTE) MacErr("execute", "execut"); if (++stackp >= NMACROS) complain("The impossible with macros just happened"); macstack[stackp] = mac; mac->Offset = 0; mac->Ntimes = exp; mac->Flags |= EXECUTE; } char * copystr(str) char *str; { char *val = emalloc(strlen(str) + 1); strcpy(val, str); return val; } struct macro * macexists(name) char *name; { register int i; for (i = 0; i < nmacros; i++) if (strcmp(macros[i].f.Macro->Name, name) == 0) return macros[i].f.Macro; return 0; } NameMac() { char *name; struct macro *m; if (KeyMacro.MacLength == 0) complain("Define it first!"); if (KeyMacro.Flags & (DEFINE | EXECUTE)) complain("Can't name while defining/executing"); if ((m = macexists(name = ask((char *) 0, FuncName()))) == 0) m = (struct macro *) emalloc(sizeof *m); else { if (strcmp(name, KeyMacro.Name) == 0) complain("Can't name it that!"); free(m->Name); free(m->Body); } name = copystr(name); *m = KeyMacro; /* Copy the keyboard macro */ m->Body = emalloc(m->MacBuflen); copynchar(m->Body, KeyMacro.Body, m->MacLength); m->Ntimes = m->Flags = m->Offset = 0; /* At the beginning */ m->Name = name; DefMac(name, m); } copynchar(t, f, len) register char *t, *f; register int len; { while (len--) *t++ = *f++; } MacInit() { SetMacro(&KeyMacro, "keyboard-macro"); FixMacros(); } MacNolen(m) struct macro *m; { m->MacLength = m->Offset = 0; } SetMacro(m, name) struct macro *m; char *name; { DefMac(name, m); /* Try this before mallocing memory */ MacNolen(m); m->Name = name; m->MacBuflen = 16; m->Body = emalloc(m->MacBuflen); m->Ntimes = m->Flags = 0; } MacPutc(c) int c; { if (KeyMacro.MacLength >= KeyMacro.MacBuflen) { KeyMacro.Body = realloc(KeyMacro.Body, (unsigned) KeyMacro.MacLength + 16); if (KeyMacro.Body == 0) MacErr("malloc", rem); KeyMacro.MacBuflen += 16; } KeyMacro.Body[KeyMacro.Offset++] = c; KeyMacro.MacLength++; } MacGetc() { if (macstack[stackp]->Offset == macstack[stackp]->MacLength) { macstack[stackp]->Offset = 0; if (--macstack[stackp]->Ntimes == 0) { macstack[stackp]->Flags &= ~EXECUTE; stackp--; } return (*Getchar)(); } return macstack[stackp]->Body[macstack[stackp]->Offset++]; } RunMacro() { int com; com = findcom(macros, FuncName()); if (com < 0) return; DoMacro(macros[com].f.Macro); } WriteMacs() { struct function *mp; struct macro *m; int macfd, namelen; char *file; file = ask((char *) 0, FuncName()); if ((macfd = creat(file, 0644)) == -1) complain(IOerr("create", file)); /* Don't write the keyboard macro which is always the first */ for (mp = ¯os[1]; mp < ¯os[NMACROS]; mp++) { m = mp->f.Macro; if (m == 0 || m->MacLength == 0) continue; ignore(write(macfd, (char *) &m->MacLength, sizeof m->MacLength)); namelen = strlen(m->Name) + 1; /* Including the null */ ignore(write(macfd, (char *) &namelen, sizeof namelen)); ignore(write(macfd, m->Name, namelen)); ignore(write(macfd, m->Body, m->MacLength)); } ignore(close(macfd)); } ReadMacs() { char *file; struct macro *m; int macfd, namelen, bodylen; file = ask((char *) 0, FuncName()); if ((macfd = open(file, 0)) == -1) complain(IOerr("open", file)); while (nmacros < NMACROS) { if (read(macfd, (char *) &bodylen, sizeof m->MacLength) == 0) break; m = (struct macro *) emalloc (sizeof *m); m->MacLength = bodylen; m->MacBuflen = (m->MacLength + 16) & ~017; ignore(read(macfd, (char *) &namelen, sizeof namelen)); m->Name = emalloc(namelen); ignore(read(macfd, m->Name, namelen)); m->Body = emalloc(m->MacBuflen); ignore(read(macfd, m->Body, m->MacLength)); DefMac(m->Name, m); } ignore(close(macfd)); }