/* * COMMAND.C * * (C)Copyright 1987 by Matthew Dillon, All Rights Reserved * * )c single character (typing) * 'c single character (typing) * `string' string of characters w/ embedded `' allowed! * (string) same thing w/ embedded () allowed! * * name arg arg command name. The arguments are interpreted as strings * for the command. * * $scanf macro insert scanf'd variable * $filename macro insert current file name * * Any string arguments not part of a command are considered to be typed * text. */ #include "defs.h" #include #define CF_COK 1 /* Can be executed while in command line mode */ #define CF_PAR 2 /* ESCIMM special flag.. save rest of command line */ /* so it can be executed after user entry */ extern char *breakout(); typedef struct { char *name; /* command name */ ubyte args; ubyte flags; int (*func)(); /* function */ } COMM; extern int do_map(), do_unmap(), do_up(), do_down(), do_left(), do_right(), do_return(), do_bs(), do_del(), do_esc(), do_downadd(), do_lastcolumn(), do_firstcolumn(),do_edit(), do_tab(), do_backtab(), do_save(), do_saveas(), do_deline(), do_insline(), do_top(), do_bottom(), do_source(), do_firstnb(), do_quit(), do_find(), do_page(), do_savetabs(), do_split(), do_goto(), do_screentop(), do_screenbottom(), do_join(), do_repeat(), do_tabstop(), do_insertmode(), do_block(), do_bdelete(), do_bcopy(), do_bmove(), do_bsave(), do_wleft(), do_wright(), do_remeol(), do_savemap(), do_toggle(), do_if(), do_tlate(), do_bsource(), do_findr(), do_findstr(), do_newwindow(), do_windowparm(),do_resize(), do_margin(), do_wordwrap(), do_reformat(), do_execute(), do_chfilename(),do_scrollup(), do_scrolldown(),do_recall(), do_scanf(), do_iconify(), do_tomouse(), do_refs(), do_arpload(), do_arpsave(); extern int do_menu(), do_menuclear(), do_menuadd(), do_menudel(), do_menudelhdr(), do_menuon(), do_menuoff(); /* * WLEFT/WRIGHT will check command line mode themselves, and thus can * be marked flags=1 even though they can change the line number. * * No more than 255 commands may exist unless you change the type of hindex[] * * Command names MUST be sorted by their first character */ unsigned char hindex[26]; /* alpha hash into table */ /* args flags */ COMM Comm[] = { "arpload", 0, 0, do_arpload, "arpsave", 0, 0, do_arpsave, "back", 0, CF_COK, do_bs, "backtab", 0, CF_COK, do_backtab, "bcopy", 0, 0, do_bcopy, "bdelete", 0, 0, do_bdelete, "block", 0, 0, do_block, /* checks com name for mode */ "bmove", 0, 0, do_bmove, "bottom", 0, 0, do_bottom, "bs", 0, CF_COK, do_bs, "bsave", 1, CF_COK, do_bsave, "bsource", 0, 0, do_bsource, "chfilename", 1, 0, do_chfilename, "del", 0, CF_COK, do_del, "deline", 0, 0, do_deline, "down", 0, 0, do_down, "downadd", 0, 0, do_downadd, "esc", 0, CF_COK, do_esc, "escimm", 1, CF_PAR, do_esc, "execute", 1, 0, do_execute, "find", 1, 0, do_find, /* checks com name for mode */ "findr", 2, 0, do_findr, /* checks com name for mode */ "findstr", 1, CF_COK, do_findstr, /* checks com name for mode */ "first", 0, CF_COK, do_firstcolumn, "firstnb", 0, CF_COK, do_firstnb, "goto", 1, 0, do_goto, "height", 1, CF_COK, do_windowparm, "iconify", 0, 0, do_iconify, "if", 2, CF_COK, do_if, "ifelse", 3, CF_COK, do_if, "insertmode", 1, CF_COK, do_insertmode, "insfile", 1, 0, do_edit, "insline", 0, 0, do_insline, "join", 0, 0, do_join, "last", 0, CF_COK, do_lastcolumn, "left", 0, CF_COK, do_left, "leftedge", 1, CF_COK, do_windowparm, "map", 2, CF_COK, do_map, "margin", 1, CF_COK, do_margin, "menuon", 0, 0, do_menuon, "menuoff", 0, 0, do_menuoff, "menuadd", 3, 0, do_menuadd, "menudel", 2, 0, do_menudel, "menudelhdr", 1, 0, do_menudelhdr, "menuclear", 0, 0, do_menuclear, "newfile", 1, 0, do_edit, /* checks com name for mode */ "newwindow", 0, 0, do_newwindow, "next", 0, 0, do_find, "nextr", 0, 0, do_findr, "pagedown", 0, 0, do_page, "pageset", 1, 0, do_page, "pageup", 0, 0, do_page, "prev", 0, 0, do_find, "prevr", 0, 0, do_findr, "quit", 0, 0, do_quit, "recall", 0, CF_COK, do_recall, "ref", 0, 0, do_refs, "reformat", 0, 0, do_reformat, "remeol", 0, CF_COK, do_remeol, "repeat", 2, CF_COK, do_repeat, "repstr", 1, CF_COK, do_findstr, "resettoggle", 1, CF_COK, do_toggle, "resize", 2, 0, do_resize, "return", 0, CF_COK, do_return, /* special meaning in command line mode */ "right", 0, CF_COK, do_right, "saveas", 1, CF_COK, do_saveas, "savemap", 1, CF_COK, do_savemap, /* checks com name for mode */ "saveold", 0, CF_COK, do_save, "savesmap", 1, CF_COK, do_savemap, "savetabs", 1, CF_COK, do_savetabs, "scanf", 1, CF_COK, do_scanf, "screenbottom", 0, 0, do_screenbottom, "screentop", 0, 0, do_screentop, "scrollup", 0, 0, do_scrollup, "scrolldown", 0, 0, do_scrolldown, "settoggle", 1, CF_COK, do_toggle, "source", 1, CF_COK, do_source, "split", 0, 0, do_split, "tab", 0, CF_COK, do_tab, "tabstop", 1, CF_COK, do_tabstop, "tlate", 1, CF_COK, do_tlate, "tmpheight", 1, CF_COK, do_windowparm, "tmpwidth", 1, CF_COK, do_windowparm, "toggle", 1, CF_COK, do_toggle, "tomouse", 0, 0, do_tomouse, "top", 0, 0, do_top, "topedge", 1, CF_COK, do_windowparm, "unblock", 0, 0, do_block, "unmap", 1, CF_COK, do_unmap, "up", 0, 0, do_up, "while", 2, CF_COK, do_if, "width", 1, CF_COK, do_windowparm, "wleft", 0, CF_COK, do_wleft, "wordwrap", 1, CF_COK, do_wordwrap, "wright", 0, CF_COK, do_wright, NULL, 0, 0, NULL }; init_command() { register short hi; register COMM *comm; hi = sizeof(Comm)/sizeof(Comm[0]) - 2; comm = Comm + hi; while (hi >= 0) { hindex[comm->name[0] - 'a'] = hi; --hi; --comm; } } do_command(str) char *str; { register char *arg; char quoted; register short i, j; static int level; if (++level > 20) { title("Recursion Too Deep!"); --level; return(0); } while (arg = breakout(&str, "ed)) { if (quoted) { text_write(arg); continue; } for (i = 0; arg[i]; ++i) { if (arg[i] >= 'A' && arg[i] <= 'Z') arg[i] += 'a' - 'A'; } if (arg[0] >= 'a' && arg[0] <= 'z') { register COMM *comm = &Comm[hindex[arg[0]-'a']]; for (; comm->name && comm->name[0] == arg[0]; ++comm) { if (strcmp(arg, comm->name) == 0) { av[0] = (ubyte *)comm->name; for (j = 1; j <= comm->args; ++j) { av[j] = (ubyte *)breakout(&str, "ed); if (!av[j]) { title("Bad argument"); --level; return(0); } if (av[j][0] == '$') av[j] = (ubyte *)String; } if ((comm->flags & CF_COK) || !Comlinemode) { if (comm->flags & CF_PAR) { if (Partial) free(Partial); Partial = (char *)malloc(strlen(str)+1); strcpy(Partial, str); str += strlen(str); /* skip string */ } (*comm->func)(-1); } if (Abortcommand) goto fail; goto loop; } } } /* Command not found, check for macro */ { char *str; int ret; if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) { str = (char *)strcpy(malloc(strlen(str)+1), str); ret = do_command(str); free(str); if (ret) goto loop; goto fail; } } title("Unknown Command"); fail: --level; return(0); loop: ; } --level; return(1); } do_source() { char buf[256]; long xfi; register char *str; if (xfi = xfopen(av[1], "r", 512)) { while (xfgets(xfi, buf, 256) >= 0) { if (buf[0] == '#') continue; for (str = buf; *str; ++str) { if (*str == 9) *str = ' '; } do_command(buf); } xfclose(xfi); } else { if (av[0]) title("File not found"); } } do_quit() { extern char Quitflag; Quitflag = 1; } do_execute() { Execute(av[1], 0, 0); } /* * repeat X command * * Since repeat takes up 512+ stack, it should not be nested more than * twice. * * (if X is not a number it can be abbr. with 2 chars) * * X = N -number of repeats * line -current line # (lines begin at 1) * lbot -#lines to the bottom, inc. current * cleft -column # (columns begin at 0) * (thus is also chars to the left) * cright-#chars to eol, including current char * tr -#char positions to get to next tab stop * tl -#char positions to get to next backtab stop */ #define SC(a,b) ((a)<<8|(b)) do_repeat() { register ubyte *ptr = av[1]; register unsigned long n; char buf1[256]; char buf2[256]; breakreset(); strcpy(buf1, av[2]); switch((ptr[0]<<8)+ptr[1]) { case SC('l','i'): n = text_lineno(); break; case SC('l','b'): n = text_lines() - text_lineno() + 1; break; case SC('c','l'): n = text_colno(); break; case SC('c','r'): n = text_cols() - text_colno(); break; case SC('t','r'): n = text_tabsize()-(text_colno() % text_tabsize()); break; case SC('t','l'): n = text_colno() % text_tabsize(); if (n == 0) n = text_tabsize(); break; default: n = atoi(av[1]); break; } while (n > 0) { strcpy(buf2, buf1); if (do_command(buf2) == 0 || breakcheck()) { Abortcommand = 1; break; } --n; } } char * breakout(ptr, quoted) register char **ptr; char *quoted; { register char *str = *ptr; register char *base = str; *quoted = 0; while (*str == ' ') ++str; if (!*str) return(NULL); if (*str == '\'' || *str == ')') { if (str[1]) { *quoted = 1; base = str + 1; if (str[2]) ++str; *str = '\0'; *ptr = str; return(base); } return(NULL); } if (*str == '`' || *str == '(') { short count = 1; char opc = *str; char clc = (opc == '(') ? ')' : '\''; base = ++str; while (*str && count) { if (*str == opc) ++count; if (*str == clc) --count; ++str; } if (count == 0) { --str; *quoted = 1; *str = '\0'; *ptr = str + 1; return(base); } } base = str; while (*str && *str != ' ') ++str; if (*str) { *str = '\0'; *ptr = str + 1; return(base); } *ptr = str; return(base); }