home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff153.lzh / Dme / src / command.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  15KB  |  566 lines

  1.  
  2. /*
  3.  * COMMAND.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  *
  7.  * )c             single character (typing)
  8.  * 'c                single character (typing)
  9.  * `string'          string of characters w/ embedded `' allowed!
  10.  * (string)             same thing w/ embedded () allowed!
  11.  * \c             override
  12.  *
  13.  * name arg arg      command name. The arguments are interpreted as strings
  14.  *             for the command.
  15.  *
  16.  * $scanf         macro insert scanf'd variable
  17.  * $filename         macro insert current file name
  18.  *
  19.  * Any string arguments not part of a command are considered to be typed
  20.  * text.
  21.  */
  22.  
  23. #include "defs.h"
  24. #include <stdio.h>
  25.  
  26. #if AREXX
  27. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  28. extern int cmderr;       /* global command error flag for do_rexx()'s use */
  29. #endif
  30.  
  31. #define CF_COK    1   /*    Can be executed while in command line mode    */
  32. #define CF_PAR    2   /*    ESCIMM special flag.. save rest of command line */
  33.             /*    so it can be executed after user entry        */
  34.  
  35. #define CF_ICO    4   /*    OK to execute if iconified, else uniconify first*/
  36.  
  37. extern char *breakout();
  38.  
  39. typedef struct {
  40.    char *name;        /* command name      */
  41.    ubyte args;
  42.    ubyte flags;
  43.    int (*func)();   /* function           */
  44. } COMM;
  45.  
  46. extern int  do_map(),       do_unmap(),     do_up(),        do_down(),
  47.         do_left(),      do_right(),     do_return(),    do_bs(),
  48.         do_del(),       do_esc(),       do_downadd(),   do_lastcolumn(),
  49.         do_firstcolumn(),do_edit(),     do_tab(),       do_backtab(),
  50.         do_save(),      do_saveas(),    do_deline(),    do_insline(),
  51.         do_top(),       do_bottom(),    do_source(),    do_firstnb(),
  52.         do_quit(),      do_find(),      do_page(),      do_savetabs(),
  53.         do_split(),     do_goto(),      do_screentop(), do_screenbottom(),
  54.         do_join(),      do_repeat(),    do_tabstop(),   do_insertmode(),
  55.         do_block(),     do_bdelete(),   do_bcopy(),     do_bmove(),
  56.         do_bsave(),     do_wleft(),     do_wright(),    do_remeol(),
  57.         do_savemap(),   do_toggle(),    do_if(),        do_tlate(),
  58.         do_bsource(),   do_findr(),     do_findstr(),   do_newwindow(),
  59.         do_windowparm(),do_resize(),    do_margin(),    do_wordwrap(),
  60.         do_reformat(),  do_execute(),   do_chfilename(),do_scrollup(),
  61.         do_scrolldown(),do_recall(),    do_scanf(),     do_iconify(),
  62.         do_tomouse(),   do_refs(),      do_arpload(),   do_arpsave(),
  63.         do_arpinsfile(),do_setfont(),   do_ignorecase();
  64.  
  65. extern int  do_menu(), do_menuclear(), do_menuadd(), do_menudel(),
  66.         do_menudelhdr(), do_menuon(), do_menuoff();
  67.  
  68. extern int  do_null(), do_rx();
  69.  
  70. extern int  do_pushmark(),  do_popmark(),   do_swapmark(),  do_purgemark(),
  71.         do_ping(),      do_pong(),      do_undo();
  72.  
  73. #if AREXX
  74. extern int  do_rx(),        do_rx1(),       do_rx2();
  75. #endif
  76.  
  77. /*============================================================================*/
  78.  
  79. /*
  80.  *  WLEFT/WRIGHT will check command line mode themselves, and thus can
  81.  *  be marked flags=1 even though they can change the line number.
  82.  *
  83.  *  No more than 255 commands may exist unless you change the type of hindex[]
  84.  *
  85.  *  Command names MUST be sorted by their first character
  86.  */
  87.  
  88. unsigned char hindex[26];   /*    alpha hash into table    */
  89.  
  90.     /*      args flags    */
  91.  
  92. COMM Comm[] = {
  93.     "arpinsfile",    0,      0, do_arpinsfile,
  94.     "arpload",       0,      0, do_arpload,
  95.     "arpsave",       0,      0, do_arpsave,
  96.     "back",          0, CF_COK, do_bs,
  97.     "backtab",       0, CF_COK, do_backtab,
  98.     "bcopy",         0,      0, do_bcopy,
  99.     "bdelete",       0,      0, do_bdelete,
  100.     "block",         0,      0, do_block,    /* checks com name for mode */
  101.     "bmove",         0,      0, do_bmove,
  102.     "bottom",        0,      0, do_bottom,
  103.     "bs",            0, CF_COK, do_bs,
  104.     "bsave",         1, CF_COK, do_bsave,
  105.     "bsource",       0,      0, do_bsource,
  106.     "chfilename",    1,      0, do_chfilename,
  107.     "del",           0, CF_COK, do_del,
  108.     "deline",        0,      0, do_deline,
  109.     "down",          0,      0, do_down,
  110.     "downadd",       0,      0, do_downadd,
  111.     "esc",           0, CF_COK, do_esc,
  112.     "escimm",        1, CF_PAR, do_esc,
  113.     "execute",       1, CF_ICO, do_execute,
  114.     "find",          1,      0, do_find,     /* checks com name for mode */
  115.     "findr",         2,      0, do_findr,    /* checks com name for mode */
  116.     "findstr",       1, CF_COK, do_findstr,  /* checks com name for mode */
  117.     "first",         0, CF_COK, do_firstcolumn,
  118.     "firstnb",       0, CF_COK, do_firstnb,
  119.     "goto",          1,      0, do_goto,
  120.     "height",        1, CF_COK, do_windowparm,
  121.     "iconify",       0, CF_ICO, do_iconify,
  122.     "if",            2, CF_COK, do_if,
  123.     "ifelse",        3, CF_COK, do_if,
  124.     "ignorecase",    1, CF_COK, do_ignorecase,
  125.     "insertmode",    1, CF_COK, do_insertmode,
  126.     "insfile",       1,      0, do_edit,
  127.     "insline",       0,      0, do_insline,
  128.     "join",          0,      0, do_join,
  129.     "last",          0, CF_COK, do_lastcolumn,
  130.     "left",          0, CF_COK, do_left,
  131.     "leftedge",      1, CF_COK, do_windowparm,
  132.     "map",           2, CF_COK, do_map,
  133.     "margin",        1, CF_COK, do_margin,
  134.     "menuon",        0,      0, do_menuon,
  135.     "menuoff",       0,      0, do_menuoff,
  136.     "menuadd",       3,      0, do_menuadd,
  137.     "menudel",       2,      0, do_menudel,
  138.     "menudelhdr",    1,      0, do_menudelhdr,
  139.     "menuclear",     0,      0, do_menuclear,
  140.     "newfile",       1,      0, do_edit,     /* checks com name for mode */
  141.     "newwindow",     0, CF_ICO, do_newwindow,
  142.     "next",          0,      0, do_find,
  143.     "nextr",         0,      0, do_findr,
  144.     "null",          0, CF_COK, do_null,
  145.     "pagedown",      0,      0, do_page,
  146.     "pageset",       1,      0, do_page,
  147.     "pageup",        0,      0, do_page,
  148.     "ping",          1, CF_ICO, do_ping,
  149.     "pong",          1,      0, do_pong,
  150.     "prev",          0,      0, do_find,
  151.     "prevr",         0,      0, do_findr,
  152.     "popmark",       0,      0, do_popmark,
  153.     "purgemark",     0,      0, do_purgemark,
  154.     "pushmark",      0,      0, do_pushmark,
  155.     "quit",          0, CF_ICO, do_quit,
  156.     "recall",        0, CF_COK, do_recall,
  157.     "ref",           0,      0, do_refs,
  158.     "reformat",      0,      0, do_reformat,
  159.     "remeol",        0, CF_COK, do_remeol,
  160.     "repeat",        2, CF_ICO|CF_COK, do_repeat,
  161.     "repstr",        1, CF_COK, do_findstr,
  162.     "resettoggle",   1, CF_COK, do_toggle,
  163.     "resize",        2,      0, do_resize,
  164.     "return",        0, CF_COK, do_return,   /* special meaning in command line mode */
  165.     "right",         0, CF_COK, do_right,
  166. #if AREXX
  167.     "rx",            1,      0, do_rx,       /* explicit ARexx macro invocation      */
  168.     "rx1",           2,      0, do_rx1,      /* explicit, with 1 arg  to ARexx macro */
  169.     "rx2",           3,      0, do_rx2,      /* explicit, with 2 args to ARexx macro */
  170. #endif
  171.     "saveas",        1, CF_ICO|CF_COK, do_saveas,
  172.     "savemap",       1, CF_ICO|CF_COK, do_savemap,  /* checks com name for mode */
  173.     "saveold",       0, CF_ICO|CF_COK, do_save,
  174.     "savesmap",      1, CF_ICO|CF_COK, do_savemap,
  175.     "savetabs",      1, CF_ICO|CF_COK, do_savetabs,
  176.     "scanf",         1, CF_COK, do_scanf,
  177.     "screenbottom",  0,      0, do_screenbottom,
  178.     "screentop",     0,      0, do_screentop,
  179.     "scrollup",      0,      0, do_scrollup,
  180.     "scrolldown",    0,      0, do_scrolldown,
  181.     "setfont",       2,      0, do_setfont,
  182.     "settoggle",     1, CF_COK, do_toggle,
  183.     "source",        1, CF_COK, do_source,
  184.     "split",         0,      0, do_split,
  185.     "swapmark",      0,      0, do_swapmark,
  186.     "tab",           0, CF_COK, do_tab,
  187.     "tabstop",       1, CF_COK, do_tabstop,
  188.     "tlate",         1, CF_COK, do_tlate,
  189.     "tmpheight",     1, CF_COK, do_windowparm,
  190.     "tmpwidth",      1, CF_COK, do_windowparm,
  191.     "toggle",        1, CF_COK, do_toggle,
  192.     "tomouse",       0,      0, do_tomouse,
  193.     "top",           0,      0, do_top,
  194.     "topedge",       1, CF_COK, do_windowparm,
  195.     "unblock",       0,      0, do_block,
  196.     "undo",          0,      0, do_undo,
  197.     "unmap",         1, CF_ICO|CF_COK, do_unmap,
  198.     "up",            0,      0, do_up,
  199.     "while",         2, CF_ICO|CF_COK, do_if,
  200.     "width",         1, CF_COK, do_windowparm,
  201.     "wleft",         0, CF_COK, do_wleft,
  202.     "wordwrap",      1, CF_COK, do_wordwrap,
  203.     "wright",        0, CF_COK, do_wright,
  204.     NULL, 0, 0, NULL
  205. };
  206.  
  207. init_command()
  208. {
  209.     register short hi;
  210.     register COMM *comm;
  211.  
  212.     hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
  213.     comm = Comm + hi;
  214.  
  215.     while (hi >= 0) {
  216.     hindex[comm->name[0] - 'a'] = hi;
  217.     --hi;
  218.     --comm;
  219.     }
  220. }
  221.  
  222. #define MAXIA    5
  223.  
  224. do_command(str)
  225. char *str;
  226. {
  227.     register char *arg;
  228.     char *aux1, *aux2;
  229.     char *repstr[MAXIA];
  230.     char quoted;
  231.     short repi = 0;
  232.     register short i, j;
  233.     static int level;
  234.  
  235.     if (++level > 20) {
  236.     title("Recursion Too Deep!");
  237.     --level;
  238. #if AREXX
  239.     foundcmd = 1;    /* to prevent us from trying an ARexx macro */
  240. #endif
  241.     return(0);
  242.     }
  243.     while (arg = breakout(&str, "ed, &aux1)) {
  244.     if (quoted) {
  245.         if (Ep->iconmode)
  246.         uniconify();
  247.         text_write(arg);
  248.         goto loop;
  249.     }
  250.     for (i = 0; arg[i]; ++i) {
  251.         if (arg[i] >= 'A' && arg[i] <= 'Z')
  252.         arg[i] += 'a' - 'A';
  253.     }
  254.  
  255.     if (arg[0] >= 'a' && arg[0] <= 'z') {
  256.         register COMM *comm = &Comm[hindex[arg[0]-'a']];
  257.         for (; comm->name && comm->name[0] == arg[0]; ++comm) {
  258.         if (strcmp(arg, comm->name) == 0) {
  259. #if AREXX
  260.             foundcmd = 1;
  261. #endif
  262.             av[0] = (ubyte *)comm->name;
  263.             for (j = 1; j <= comm->args; ++j) {
  264.             av[j] = (ubyte *)breakout(&str, "ed, &aux2);
  265.             if (aux2) {
  266.                 if (repi == MAXIA) {
  267.                 free(aux2);
  268.                 title("Command too complex");
  269.                 goto fail;
  270.                 } else {
  271.                 repstr[repi++] = aux2;
  272.                 }
  273.             }
  274.             if (!av[j]) {
  275.                 title("Bad argument");
  276.                 goto fail;
  277.             }
  278.             }
  279.             av[j] = NULL;   /* end of arglist */
  280.             if ((comm->flags & CF_COK) || !Comlinemode) {
  281.             if (comm->flags & CF_PAR) {
  282.                 if (Partial)
  283.                 free(Partial);
  284.                 Partial = (char *)malloc(strlen(str)+1);
  285.                 strcpy(Partial, str);
  286.                 str += strlen(str);     /*  skip string */
  287.             }
  288.             if (Ep->iconmode && !(comm->flags & CF_ICO))
  289.                 uniconify();
  290.             (*comm->func)(-1);
  291.             }
  292.             if (Abortcommand)
  293.             goto fail;
  294.             goto loop;
  295.         }
  296.         }
  297.     }
  298.  
  299.     /* Command not found, check for macro    */
  300.  
  301.     {
  302.         char *str;
  303.         int ret;
  304.         if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) {
  305.         str = (char *)strcpy(malloc(strlen(str)+1), str);
  306.         ret = do_command(str);
  307.         free(str);
  308. #if AREXX
  309.         if (ret) {
  310.             foundcmd = 1;   /* dunno about this yet for ARexx macros */
  311.             goto loop;
  312.         }
  313. #else
  314.         if (ret)
  315.             goto loop;
  316. #endif
  317.         goto fail;
  318.         }
  319.     }
  320.  
  321.     /* Command still not found, check for public macro  */
  322.     /* code to be added */
  323.  
  324. #if AREXX
  325.     do_rxImplied(arg, str);
  326. #else
  327.     title("Unknown Command");
  328. #endif
  329. fail:
  330.     --level;
  331.     while (--repi >= 0)
  332.         free(repstr[repi]);
  333.     if (aux1)
  334.         free(aux1);
  335.     return(0);
  336. loop:
  337.     if (aux1)
  338.         free(aux1);
  339.     }
  340.     --level;
  341.     while (--repi >= 0)
  342.     free(repstr[repi]);
  343.     return(1);
  344. }
  345.  
  346. do_null()
  347. {
  348. }
  349.  
  350. do_source()
  351. {
  352.     char buf[256];
  353.     long xfi;
  354.     register char *str;
  355.  
  356.     if (xfi = xfopen(av[1], "r", 512)) {
  357.     while (xfgets(xfi, buf, 256) >= 0) {
  358.         if (buf[0] == '#')
  359.         continue;
  360.         for (str = buf; *str; ++str) {
  361.         if (*str == 9)
  362.             *str = ' ';
  363.         }
  364.         do_command(buf);
  365.     }
  366.     xfclose(xfi);
  367.     } else {
  368.     if (av[0])
  369.         title("File not found");
  370.     }
  371. }
  372.  
  373.  
  374. do_quit()
  375. {
  376.     extern char Quitflag;
  377.  
  378.     Quitflag = 1;
  379. }
  380.  
  381. do_execute()
  382. {
  383.     Execute(av[1], NULL, NULL);
  384. }
  385.  
  386. /*
  387.  * repeat X command
  388.  *
  389.  * Since repeat takes up 512+ stack, it should not be nested more than
  390.  * twice.
  391.  *
  392.  * (if X is not a number it can be abbr. with 2 chars)
  393.  *
  394.  * X =    N     -number of repeats
  395.  *    line  -current line # (lines begin at 1)
  396.  *    lbot  -#lines to the bottom, inc. current
  397.  *    cleft -column # (columns begin at 0)
  398.  *        (thus is also chars to the left)
  399.  *    cright-#chars to eol, including current char
  400.  *    tr    -#char positions to get to next tab stop
  401.  *    tl    -#char positions to get to next backtab stop
  402.  */
  403.  
  404. #define SC(a,b) ((a)<<8|(b))
  405.  
  406. do_repeat()
  407. {
  408.     register ubyte *ptr = av[1];
  409.     register unsigned long n;
  410.     char buf1[256];
  411.     char buf2[256];
  412.  
  413.     breakreset();
  414.     strcpy(buf1, av[2]);
  415.     switch((ptr[0]<<8)+ptr[1]) {
  416.     case SC('l','i'):
  417.     n = text_lineno();
  418.     break;
  419.     case SC('l','b'):
  420.     n = text_lines() - text_lineno() + 1;
  421.     break;
  422.     case SC('c','l'):
  423.     n = text_colno();
  424.     break;
  425.     case SC('c','r'):
  426.     n = text_cols() - text_colno();
  427.     break;
  428.     case SC('t','r'):
  429.     n = text_tabsize()-(text_colno() % text_tabsize());
  430.     break;
  431.     case SC('t','l'):
  432.     n = text_colno() % text_tabsize();
  433.     if (n == 0)
  434.         n = text_tabsize();
  435.     break;
  436.     default:
  437.     n = atoi(av[1]);
  438.     break;
  439.     }
  440.     while (n > 0) {
  441.     strcpy(buf2, buf1);
  442.     if (do_command(buf2) == 0 || breakcheck()) {
  443.         Abortcommand = 1;
  444.         break;
  445.     }
  446.     --n;
  447.     }
  448. }
  449.  
  450. /*
  451.  *  BREAKOUT()
  452.  *
  453.  *  Break out the next argument.  The argument is space delimited and
  454.  *  might be quoted with `' or (), or single quoted as 'c or )c
  455.  *
  456.  *  Also:    $var        -variable insertion
  457.  *        ^c        -control character
  458.  */
  459.  
  460. char *
  461. breakout(ptr, quoted, paux)
  462. register char **ptr;
  463. char **paux;
  464. char *quoted;
  465. {
  466.     register char *str = *ptr;
  467.     char *base;
  468.     short count = 0;
  469.     char opc = 0;
  470.     char clc = 0;
  471.     char immode = 0;
  472.     char isaux = 0;
  473.     char buf[256];
  474.     short di = 0;
  475.  
  476.     *quoted = 0;
  477.     *paux = NULL;
  478.     while (*str == ' ')
  479.     ++str;
  480.     if (!*str)
  481.     return(NULL);
  482.  
  483.     *ptr = str;
  484.     base = str;
  485.     while (*str) {
  486.     if (immode) {
  487.         buf[di++] = *str++;
  488.         continue;
  489.     }
  490.     if (count == 0) {
  491.         if (*str == ' ')
  492.         break;
  493.         if (*str == '\'' || *str == ')')
  494.         clc = *str;
  495.         if (*str == '`') {
  496.         opc = '`';
  497.         clc = '\'';
  498.         }
  499.         if (*str == '(') {
  500.         opc = '(';
  501.         clc = ')';
  502.         }
  503.     }
  504.     if (*str == opc) {
  505.         ++count;
  506.         if (str == *ptr) {
  507.         *quoted = 1;
  508.         base = ++str;
  509.         continue;
  510.         }
  511.     }
  512.     if (*str == clc) {
  513.         --count;
  514.         if (count == 0 && *quoted)     /*  end of argument     */
  515.         break;
  516.         if (str == *ptr && count < 0) {
  517.         immode = 1;
  518.         *quoted = 1;
  519.         base = ++str;
  520.         continue;
  521.         }
  522.     }
  523.     if (*str == '$') {
  524.         if (strncmp(str, "$scanf", 6) == 0) {
  525.         isaux = 1;
  526.         strcpy(buf + di, String);
  527.         di = strlen(buf);
  528.         str += 6;
  529.         continue;
  530.         }
  531.         if (strncmp(str, "$filename", 9) == 0) {
  532.         isaux = 1;
  533.         strcpy(buf + di, Ep->Name);
  534.         di = strlen(buf);
  535.         str += 9;
  536.         continue;
  537.         }
  538.     }
  539.     if (*str == '^' && (str[1] & 0x1F)) {
  540.         ++str;
  541.         *str &= 0x1F;
  542.         isaux = 1;
  543.     }
  544.     if (*str == '\\' && str[1]) {
  545.         ++str;
  546.         isaux = 1;
  547.     }
  548.     buf[di++] = *str++;
  549.     }
  550.     buf[di++] = 0;
  551.     if (isaux) {
  552.     *paux = malloc(di);
  553.     strcpy(*paux, buf);
  554.     base = *paux;
  555.     }
  556.     if (*str) {             /*  space ended */
  557.     *str = '\0';
  558.     *ptr = str + 1;     /*    next arg    */
  559.     } else {
  560.     *ptr = str;        /*    last arg    */
  561.     }
  562.     return(base);
  563. }
  564.  
  565.  
  566.