/* * Name: MicroEMACS * Symbol table stuff for GNU emacs compatability * Version: 29 * Last edit: 19-Apr-86 * By: {sun, amdahl, cbosgd}!rtech!gonzo!daveb * * Symbol tables, and keymap setup. * The terminal specific parts of building the * keymap has been moved to a better place. * * This version matches the standard GNU Emacs 17.49 bindings. * With this file, MicroEMACS is a proper subset of GNU. * * If a GNU feature was misnamed, it was moved. * If a GNU feature was "nearly" right, it was noted for later work. * If a MicroEMACS feature was incompatible, it was dropped. * * Compatibility NOW for the future! */ #include "def.h" #define DIRLIST 0 /* Disarmed! */ # define DEL 0x7f # define ESC 0x1b /* # define DAVEB *//* Dave Brower specials, not GNU compatibility */ /* * Defined by "main.c". */ extern int ctrlg(); /* Abort out of things */ extern int quit(); /* Rude Quit */ extern int ctlxlp(); /* Begin macro */ extern int ctlxrp(); /* End macro */ extern int ctlxe(); /* Execute macro */ extern int showversion(); /* Show version numbers, etc. */ /* * defined by "gnucmds.c" */ extern int savebuffs(); /* GNU style save-some-buffers */ extern int savequit(); /* GNU save-buffers-kill-emacs */ extern int suspend(); /* GNU style suspend */ extern int notmodified(); /* GNU make buffer undirty */ extern int scrollother(); /* GNU scroll other window */ /* * Defined by "search.c". */ extern int forwsearch(); /* Search forward */ extern int backsearch(); /* Search backwards */ extern int searchagain(); /* Repeat last search command */ extern int forwisearch(); /* Incremental search forward */ extern int backisearch(); /* Incremental search backwards */ extern int queryrepl(); /* Query replace */ /* * Defined by "basic.c". */ extern int gotobol(); /* Move to start of line */ extern int backchar(); /* Move backward by characters */ extern int gotoeol(); /* Move to end of line */ extern int forwchar(); /* Move forward by characters */ extern int gotobob(); /* Move to start of buffer */ extern int gotoeob(); /* Move to end of buffer */ extern int forwline(); /* Move forward by lines */ extern int backline(); /* Move backward by lines */ extern int forwpage(); /* Move forward by pages */ extern int backpage(); /* Move backward by pages */ extern int setmark(); /* Set mark */ extern int swapmark(); /* Swap "." and mark */ extern int gotoline(); /* Go to a specified line. */ /* * Defined by "buffer.c". */ extern int listbuffers(); /* Display list of buffers */ extern int usebuffer(); /* Switch a window to a buffer */ extern int killbuffer(); /* Make a buffer go away. */ #if DIRLIST /* * Defined by "dirlist.c". */ extern int dirlist(); /* Directory list. */ #endif /* * Defined by "file.c". */ extern int fileread(); /* Get a file, read only */ extern int filevisit(); /* Get a file, read write */ extern int filewrite(); /* Write a file */ extern int filesave(); /* Save current file */ extern int filename(); /* Adjust file name */ /* * Defined by "random.c". */ extern int selfinsert(); /* Insert character */ extern int showcpos(); /* Show the cursor position */ extern int twiddle(); /* Twiddle characters */ extern int quote(); /* Insert literal */ extern int openline(); /* Open up a blank line */ extern int newline(); /* Insert CR-LF */ extern int deblank(); /* Delete blank lines */ extern int indent(); /* Insert CR-LF, then indent */ extern int forwdel(); /* Forward delete */ extern int backdel(); /* Backward delete */ extern int killline(); /* Kill forward */ extern int yank(); /* Yank back from killbuffer. */ /* * Defined by "region.c". */ extern int killregion(); /* Kill region. */ extern int copyregion(); /* Copy region to kill buffer. */ extern int lowerregion(); /* Lower case region. */ extern int upperregion(); /* Upper case region. */ /* * Defined by "spawn.c". */ extern int spawncli(); /* Run CLI in a subjob. */ /* * Defined by "window.c". */ extern int reposition(); /* Reposition window */ extern int refresh(); /* Refresh the screen */ extern int nextwind(); /* Move to the next window */ extern int prevwind(); /* Move to the previous window */ extern int mvdnwind(); /* Move window down */ extern int mvupwind(); /* Move window up */ extern int onlywind(); /* Make current window only one */ extern int splitwind(); /* Split current window */ extern int enlargewind(); /* Enlarge display window. */ extern int shrinkwind(); /* Shrink window. */ /* * Defined by "word.c". */ extern int backword(); /* Backup by words */ extern int forwword(); /* Advance by words */ extern int upperword(); /* Upper case word. */ extern int lowerword(); /* Lower case word. */ extern int capword(); /* Initial capitalize word. */ extern int delfword(); /* Delete forward word. */ extern int delbword(); /* Delete backward word. */ /* * Defined by "extend.c". */ extern int extend(); /* Extended commands. */ extern int help(); /* Help key. */ extern int bindtokey(); /* Modify key bindings. */ extern int wallchart(); /* Make wall chart. */ typedef struct { short k_key; /* Key to bind. */ int (*k_funcp)(); /* Function. */ char *k_name; /* Function name string. */ } KEY; /* * Default key binding table. This contains * the function names, the symbol table name, and (possibly) * a key binding for the builtin functions. There are no * bindings for C-U or C-X. These are done with special * code, but should be done normally. */ /* GNU standard bindings that are missing are commented out with the * following notations: * * /*B Braindamaged in current implementation. * /*D Design restructuring is needed. * /*E Easy, a few hours. * /*H Hard, (days) but possible if desirable. * /*I Impossible (weeks), much too hard to do right. * /*M Moderate difficulty, a day or so. * /*T On the to do list. * /*U Undecided. * /*X Means unnecessary to do. * /*W Current version is wrong. * * Well, braindamaged is a bit too strong, but doing all the argument * processing in the main loop, and not having meta- ancd ctrl-x * be bindable commands seems kinda funny to me (daveb). */ KEY key[] = { KCTRL|'@', setmark, "set-mark-command", KCTRL|'A', gotobol, "beginning-of-line", KCTRL|'B', backchar, "backward-char", /*DHX KCTRL|'C', ???, "mode-specific-command-prefix", */ KCTRL|'D', forwdel, "delete-char", KCTRL|'E', gotoeol, "end-of-line", KCTRL|'F', forwchar, "forward-char", KCTRL|'G', ctrlg, "keyboard-quit", KCTRL|'H', help, "help-command", /*DHX KCTRL|'I', ???, "indent-for-tab-command", */ KCTRL|'J', indent, "newline-and-indent", KCTRL|'K', killline, "kill-line", KCTRL|'L', refresh, "recenter", /*W actually doesn't recenter... */ KCTRL|'M', newline, "newline", KCTRL|'N', forwline, "next-line", KCTRL|'O', openline, "open-line", KCTRL|'P', backline, "previous-line", KCTRL|'Q', quote, "quoted-insert", KCTRL|'R', backisearch, "isearch-backward", KCTRL|'S', forwisearch, "isearch-forward", KCTRL|'T', twiddle, "transpose-characters", /*BMT KCTRL|'U', ???, "universal-argument," */ KCTRL|'V', forwpage, "scroll-up", KCTRL|'W', killregion, "kill-region", /*BMT KCTRL|'X', ???, "Control-X-prefix", */ KCTRL|'Y', yank, "yank", /*WET doesn't set point! */ KCTRL|'Z', suspend, "suspend-emacs", /*BMT KMETA, ???, "ESC-prefix", */ /*DX KCTRL|']', ???, "abort-recursive-edit", */ /*DIX KCTRL|'_', ???, "undo", */ DEL, backdel, "delete-backward-char", /*DIX KCTLX|KCTRL|'A',???, "add-mode-abbrev", */ KCTLX|KCTRL|'B',listbuffers, "list-buffers", KCTLX|KCTRL|'C',savequit, "save-buffers-kill-emacs", #if DIRLIST KCTLX|KCTRL|'D',dirlist, "list-directory", #endif /*DIX KCTLX|KCTRL|'E',???, "eval-last-sexp", */ KCTLX|KCTRL|'F',filevisit, "find-file", /*DIX KCTLX|KCTRL|'H',???, "inverse-add-mode=abbrev", */ /*MT KCTLX|KCTRL|'I',???, "indent-rigidly", */ KCTLX|KCTRL|'L',lowerregion, "downcase-region", /*ET KCTLX|KCTRL|'N', ???, "set-goal-column" */ KCTLX|KCTRL|'O',deblank, "delete-blank-lines", /*MU KCTLX|KCTRL|'P',???, "mark-page" */ KCTLX|KCTRL|'R',fileread, "file-file-read-only", /*WU incorrect behaviour... */ KCTLX|KCTRL|'S',filesave, "file-buffer", /*EU KCTLX|KCTRL|'T',???, "transpose-lines", */ KCTLX|KCTRL|'U',upperregion, "upcase-region", /*EU KCTLX|KCTRL|'V',findalternate, "find-alternate-file", */ KCTLX|KCTRL|'W',filewrite, "write-file", KCTLX|KCTRL|'X',swapmark, "exchange-point-and-mark", KCTLX|KCTRL|'Z',spawncli, "suspend-emacs", /*MT KCTLX|ESC ???, "repeat-complex-command", */ /*U KCTLX|'$' ???, "set-selective-display", */ KCTLX|'(', ctlxlp, "start-kbd-macro", KCTLX|')', ctlxrp, "end-kbd-macro", /*DIX KCTLX|'+', ???, "add-global-abbrev", */ /*DIX KCTLX|'-', ???, "inverse-add-global-abbrev", */ /*MX KCTLX|'.', ???, "set-fill-prefix", */ /*HX KCTLX|'/', ???, "point-to-register", */ /*MT KCTLX|'0', ???, "delete-window", */ KCTLX|'1', onlywind, "delete-other-windows", KCTLX|'2', splitwind, "split-window-vertically", /*MX KCTLX|'4', ???, "ctl-x-4-prefix", */ /*DHX KCTLX|'5', ???, "split-window-horizontally", */ /*EX KCTLX|';', ???, "set-comment-column", */ /*HU KCTLX|'<', ???, "scroll-left", */ KCTLX|'=', showcpos, "what-cursor-position", /*HU KCTLX|'>', ???, "scroll-right", */ /*MU KCTLX|'[', ???, "backward-page", */ /*MU KCTLX|']', ???, "forward-page", */ KCTLX|'^', enlargewind, "enlarge-window", /*HX KCTLX|'`', ???, "next-error", */ /*MU KCTLX|'A', ???, "append-to-buffer", */ KCTLX|'B', usebuffer, "switch-to-buffer", /*MX KCTLX|'D', ???, "dired", */ KCTLX|'E', ctlxe, "call-last-kbd-macro", /*EU KCTLX|'F', ctlxe, "set-fill-column", */ /*HX KCTLX|'G', ???, "insert-register", */ /*EU KCTLX|'H', ???, "mark-whole-buffer", */ /*MU KCTLX|'I', ???, "insert-file", */ /*HX KCTLX|'J', ???, "register-to-point", */ KCTLX|'K', killbuffer, "kill-buffer", /*MU KCTLX|'L', ???, "count-lines-page", */ /*HU KCTLX|'N', ???, "narrow-to-region", */ KCTLX|'O', nextwind, "other-window", /*HU KCTLX|'P', ???, "narrow-to-page", */ /*MX KCTLX|'Q', ???, "kbd-macro-qry", */ /*HX KCTLX|'R', ???, "copy-rectangle-to-register", */ KCTLX|'S', savebuffs, "save-some-buffers", /*HX KCTLX|'U', ???, "advertised-undo", */ /*HX KCTLX|'W', ???, "widen", */ /*HX KCTLX|'{', ???, "shrink-window-horizontally", */ /*HX KCTLX|'}', ???, "enlarge-window-horizontally", */ /*MT KCTLX|DEL, ???, "backward-kill-sentence," */ /*MU KMETA|KCTRL|'@',???, "mark-sexp", */ /*MU KMETA|KCTRL|'A',???, "beginning-of-defun", */ /*MU KMETA|KCTRL|'B',???, "backwards-sexp", */ /*MX KMETA|KCTRL|'C',???, "exit-recursive-edit", */ /*MU KMETA|KCTRL|'D',???, "down-list", */ /*MU KMETA|KCTRL|'E',???, "end-of-defun", */ /*MU KMETA|KCTRL|'F',???, "forward-sexp", */ /*MU KMETA|KCTRL|'H',???, "mark-defun", */ /*MU KMETA|KCTRL|'J',???, "indent-new-comment-line", */ /*MU KMETA|KCTRL|'K',???, "kill-sexp", */ /*MU KMETA|KCTRL|'N',???, "foward-list", */ /*EU KMETA|KCTRL|'O',???, "split-line", */ /*MU KMETA|KCTRL|'P',???, "backward-list", */ /*HX KMETA|KCTRL|'S',???, "isearch-forward-regexp", */ /*MU KMETA|KCTRL|'T',???, "transpose-sexps", */ /*MU KMETA|KCTRL|'U',???, "backward-up-list", */ KMETA|KCTRL|'V',scrollother, "scroll-other-window", /*ET KMETA|KCTRL|'W',???, "append-next-kill", */ /*IX KMETA|ESC, ??? "eval-expression", */ /*IX KMETA|CTRL|'\', ??? "indent-region", */ /*MU KMETA|' ', ??? "just-one-space", */ /*HT KMETA|'!', ???, "shell-command", */ /*HU KMETA|'$', ???, "spell-word", */ KMETA|'%', queryrepl, "query-replace", /*IX KMETA|'\'', ???, "abbrev-prefix-mark", */ /*TU KMETA|'(', ???, "insert-parenthesis", */ /*HU KMETA|')', ???, "move-past-close-and-reindent", */ /*HX KMETA|',', ???, "tags-loop-continue", */ /*DT KMETA|'-', ???, "negative-argument", */ KMETA|'>', gotoeob, "end-of-buffer", /*MU KMETA|'=', ???, "count-lines-region", */ KMETA|'<', gotobob, "beginning-of-buffer", /*TT KMETA|'@', ???, "mark-word", */ /*MU KMETA|'[', ???, "backward-paragraph", */ /*TT KMETA|'\\', ???, "delete-horizontal-space", */ /*MU KMETA|']', ???, "forward-paragraph", */ /*TT KMETA|'^', ???, "delete-indentation", */ /*MU KMETA|'A', ???, "backward-sentence", */ KMETA|'B', backword, "backward-word", KMETA|'C', capword, "capitalize-word", KMETA|'D', delfword, "kill-word", /*MU KMETA|'E', ???, "forward-sentence", */ KMETA|'F', forwword, "forward-word", /*HT KMETA|'G', ???, "fill-region", */ /*MU KMETA|'H', ???, "mark-paragraph", */ /*DMX KMETA|'I', ???, "tab-to-tab-stop", */ /*MU KMETA|'J', ???, "indent-new-comment-line", */ KMETA|'L', lowerword, "downcase-word", /*EU KMETA|'M', ???, "back-to-indentation", */ /*HT KMETA|'Q', ???, "fill-paragraph", */ KMETA|'R', reposition, "move-to-window-line", /*ET KMETA|'T', ???, "transpose-words", */ KMETA|'U', upperword, "upcase-word", KMETA|'V', backpage, "scroll-down", KMETA|'W', copyregion, "copy-region-as-kill", KMETA|'X', extend, "execute-extended-command", /*HDX KMETA|'Y', ???, "yank-pop", */ /*MU KMETA|'Z', ???, "zap-to-char", */ /*HT KMETA|'|', ???, "shell-command-on-region", */ KMETA|'~', notmodified, "not-modified", KMETA|DEL, delbword, "backward-kill-word", /* ** These are unbound functions, callable by name. ** They are GNU compatible (to various degrees). */ /* -1, ???, "append-next-kill", */ /* -1, ???, "apropos", */ -1, wallchart, "describe-bindings", /*MT -1, ???, "digit-argument", */ -1, showversion, "emacs-version", -1, bindtokey, "global-set-key", -1, gotoline, "goto-line", -1, quit, "kill-emacs", -1, backsearch, "search-backward", -1, forwsearch, "search-forward", -1, selfinsert, "self-insert-command", -1, filename, "set-visited-file-name", /* These are duplicate names for GNU compatible functions, ** or incompatible commands I've left lying around for now. ** The old command names get used as args to keydup() in the ** various tty/xxx/ttykbd.c modules for function keys. */ -1, backchar, "back-char", -1, backline, "back-line", -1, backpage, "back-page", -1, prevwind, "back-window", -1, mvdnwind, "down-window", -1, enlargewind, "enlarge-window", -1, ctlxe, "execute-macro", -1, forwchar, "forw-char", -1, forwline, "forw-line", -1, forwpage, "forw-page", -1, nextwind, "forw-window", -1, help, "help", -1, selfinsert, "ins-self", -1, killregion, "kill-region", -1, searchagain, "search-again", -1, setmark, "set-mark", -1, shrinkwind, "shrink-window", -1, mvupwind, "up-window", /*MT incorrect behaviour */ }; #define NKEY (sizeof(key) / sizeof(key[0])) /* * Symbol table lookup. * Return a pointer to the SYMBOL node, or NULL if * the symbol is not found. */ SYMBOL * symlookup(cp) register char *cp; { register SYMBOL *sp; sp = symbol[symhash(cp)]; while (sp != NULL) { if (strcmp(cp, sp->s_name) == 0) return (sp); sp = sp->s_symp; } return (NULL); } /* * Take a string, and compute the symbol table * bucket number. This is done by adding all of the characters * together, and taking the sum mod NSHASH. The string probably * should not contain any GR characters; if it does the "*cp" * may get a nagative number on some machines, and the "%" * will return a negative number! */ symhash(cp) register char *cp; { register int c; register int n; n = 0; while ((c = *cp++) != 0) n += c; return (n % NSHASH); } /* * Build initial keymap. The funny keys * (commands, odd control characters) are mapped using * a big table and calls to "keyadd". The printing characters * are done with some do-it-yourself handwaving. The terminal * specific keymap initialization code is called at the * very end to finish up. All errors are fatal. */ keymapinit() { register SYMBOL *sp; register KEY *kp; register int i; register int hash; for (i=0; ik_key, kp->k_funcp, kp->k_name); /* Multiple bindings of standard commands */ #ifdef DAVEB keydup(KCTRL|'Z', "scroll-down"); #endif keydup(KCTLX|KCTRL|'G', "keyboard-quit"); keydup(KMETA|KCTRL|'G', "keyboard-quit"); keydup(KMETA|' ', "set-mark-command"); /* * Self insert should be in hash table already, bound to -1. * Bind all printing chars without an explicit binding already. */ if ((sp=symlookup("self-insert-command")) == NULL) abort(); binding[ KCTRL|'I' ] = sp; for ( i = ' ' ; i < DEL ; ++i ) { if (binding[i] != NULL) continue; binding[i] = sp; ++sp->s_nkey; } ttykeymapinit(); } /* * Create a new builtin function "name" * with function "funcp". If the "new" is a real * key, bind it as a side effect. All errors * are fatal. */ keyadd(new, funcp, name) int (*funcp)(); char *name; { register SYMBOL *sp; register int hash; if ((sp=(SYMBOL *)malloc(sizeof(SYMBOL))) == NULL) abort(); hash = symhash(name); sp->s_symp = symbol[hash]; symbol[hash] = sp; sp->s_nkey = 0; sp->s_name = name; sp->s_funcp = funcp; if (new >= 0) { /* Bind this key. */ if (binding[new] != NULL) abort(); binding[new] = sp; ++sp->s_nkey; } } /* * Bind key "new" to the existing routine "name". * If the routine doesn't exist, just give a warning. * It's no error to rebind a key. */ keydup(new, name) register int new; char *name; { register SYMBOL *sp; if ( (sp=symlookup(name))==NULL ) return; if( new >= 0 ) binding[new] = sp; ++sp->s_nkey; }