home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff256.lzh / Stevie / cmdline.c < prev    next >
C/C++ Source or Header  |  1989-10-19  |  16KB  |  819 lines

  1. /*
  2.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  3.  *
  4.  * Code Contributions By : Tim Thompson           twitch!tjt
  5.  *                         Tony Andrews           onecom!wldrdg!tony 
  6.  *                         G. R. (Fred) Walter    watmath!grwalter 
  7.  */
  8.  
  9. #include "stevie.h"
  10.  
  11. static char    *altfile = NULL;    /* alternate file */
  12. static int      altline;    /* line # in alternate file */
  13.  
  14. static char    *nowrtmsg = "No write since last change (use ! to override)";
  15.  
  16. extern char   **files;        /* used for "n" and "rew" */
  17. extern int      curfile;
  18. extern int      numfiles;
  19.  
  20. #ifdef WILD_CARDS
  21. char          **cmd_files = NULL;    /* list of input files */
  22. int             cmd_numfiles = 0;    /* number of input files */
  23. #endif
  24.  
  25. /*
  26.  * The next two variables contain the bounds of any range given in a command.
  27.  * If no range was given, both contain null line pointers. If only a single
  28.  * line was given, u_pos will contain a null line pointer. 
  29.  */
  30. static LPtr     l_pos, u_pos;
  31.  
  32. static bool_t   interactive;    /* TRUE if we're reading a real command line */
  33.  
  34. static bool_t   doecmd();
  35. static void     badcmd();
  36. static void     doshell();
  37. static void     get_range();
  38. static LPtr    *get_line();
  39.  
  40. #ifdef  MEGAMAX
  41. overlay "cmdline"
  42. #endif
  43.  
  44. /*
  45.  * readcmdline() - accept a command line starting with ':', '/', or '?' 
  46.  *
  47.  * readcmdline() accepts and processes colon commands and searches. If
  48.  * 'cmdline' is null, the command line is read here. Otherwise, cmdline
  49.  * points to a complete command line that should be used. This is used in
  50.  * main() to handle initialization commands in the environment variable
  51.  * "EXINIT". 
  52.  */
  53. void
  54. readcmdline(firstc, cmdline)
  55.     char            firstc;    /* either ':', '/', or '?' */
  56.     char           *cmdline;    /* optional command string */
  57. {
  58.     char            c;
  59.     char            buff[CMDBUFFSIZE];
  60.     char            cmdbuf[CMDBUFFSIZE];
  61.     char            argbuf[CMDBUFFSIZE];
  62.     char           *p, *q, *cmd, *arg;
  63.     bool_t          literal_next_flag = FALSE;
  64.  
  65.     /*
  66.      * Clear the range variables. 
  67.      */
  68.     l_pos.linep = (LINE *) NULL;
  69.     u_pos.linep = (LINE *) NULL;
  70.  
  71.     interactive = (cmdline == NULL);
  72.  
  73.     if (interactive)
  74.     gotocmdline(YES, firstc);
  75.     p = buff;
  76.     if (firstc != ':')
  77.     *p++ = firstc;
  78.  
  79.     if (interactive) {
  80.     /* collect the command string, handling '\b' and @ */
  81.     for (;;) {
  82.         c = vgetc();
  83.         if (c == CTRL('V') && !literal_next_flag) {
  84.         literal_next_flag = TRUE;
  85.         outchar('^');
  86.         continue;
  87.         }
  88.         if (c == '\n' || ((c == '\r' || c == ESC) && (!literal_next_flag)))
  89.         break;
  90.         if ((c == '\b') && (!literal_next_flag)) {
  91.         if (p > buff + (firstc != ':')) {
  92.             p--;
  93.             /*
  94.              * this is gross, but it relies only on 'gotocmdline' 
  95.              */
  96.             gotocmdline(YES, firstc == ':' ? ':' : NUL);
  97.             for (q = buff; q < p; q++)
  98.             outstr(chars[*q].ch_str);
  99.         } else {
  100.             msg("");
  101.             return;    /* back to cmd mode */
  102.         }
  103.         continue;
  104.         }
  105.         if ((c == '@') && (!literal_next_flag)) {
  106.         p = buff;
  107.             if (firstc != ':')
  108.             *p++ = firstc;
  109.         gotocmdline(YES, firstc);
  110.         continue;
  111.         }
  112.         if (literal_next_flag) {
  113.         literal_next_flag = FALSE;
  114.         outchar('\b');
  115.         }
  116.         outstr(chars[c].ch_str);
  117.         *p++ = c;
  118.     }
  119.     *p = '\0';
  120.     } else {
  121.     if (strlen(cmdline) > CMDBUFFSIZE - 2)    /* should really do something
  122.                          * better here... */
  123.         return;
  124.     strcpy(p, cmdline);
  125.     }
  126.  
  127.     /* skip any initial white space */
  128.     for (cmd = buff; *cmd != NUL && isspace(*cmd); cmd++);
  129.  
  130.     /* search commands */
  131.     c = *cmd;
  132.     if (c == '/' || c == '?') {
  133.     cmd++;
  134.     /* was the command was '//' or '??' (I.E. repeat last search) */
  135.     if ((*cmd == c) || (*cmd == NUL)) {
  136.         if (c == '/')
  137.         searchagain(FORWARD);
  138.         else
  139.         searchagain(BACKWARD);
  140.         return;
  141.     }
  142.     /* If there is a matching '/' or '?' at the end, toss it */
  143.     p = strchr(cmd, NUL);
  144.     if (*(p - 1) == c && *(p - 2) != '\\')
  145.         *(p - 1) = NUL;
  146.     dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
  147.     return;
  148.     }
  149.     /*
  150.      * Parse a range, if present (and update the cmd pointer). 
  151.      */
  152.     get_range(&cmd);
  153.     if (l_pos.linep != NULL) {
  154.     if (LINEOF(&l_pos) > LINEOF(&u_pos)) {
  155.         emsg("Invalid range");
  156.         return;
  157.     }
  158.     }
  159.     strcpy(cmdbuf, cmd);    /* save the unmodified command */
  160.  
  161.     /* isolate the command and find any argument */
  162.     for (p = cmd; *p != NUL && !isspace(*p); p++);
  163.     if (*p == NUL)
  164.     arg = NULL;
  165.     else {
  166.     *p = NUL;
  167.     for (p++; *p != NUL && isspace(*p); p++);
  168.     if (*p == NUL) {
  169.         arg = NULL;
  170.     } else {
  171.         strcpy(argbuf, p);
  172.         arg = argbuf;
  173.     }
  174.     }
  175.  
  176.     if (strcmp(cmd, "q!") == 0) {
  177.     getout(0);
  178.     }
  179.     if (strcmp(cmd, "q") == 0) {
  180.     if (Changed) {
  181.         emsg(nowrtmsg);
  182.     } else {
  183.         getout(0);
  184.     }
  185.     return;
  186.     }
  187.     if (strcmp(cmd, "w") == 0) {
  188.     if (arg == NULL) {
  189.         if (Filename != NULL) {
  190.         if (!writeit(Filename, &l_pos, &u_pos)) {
  191.             emsg("Problems occured while writing output file");
  192.         }
  193.         } else {
  194.         emsg("No output file");
  195.         }
  196.     } else {
  197.         (void) writeit(arg, &l_pos, &u_pos);
  198.     }
  199.     return;
  200.     }
  201.     if (strcmp(cmd, "wq") == 0) {
  202.     if (Filename != NULL) {
  203.         if (writeit(Filename, (LPtr *) NULL, (LPtr *) NULL)) {
  204.         getout(0);
  205.         }
  206.     } else {
  207.         emsg("No output file");
  208.     }
  209.     return;
  210.     }
  211.     if (strcmp(cmd, "x") == 0) {
  212.     if (Changed) {
  213.         if (Filename != NULL) {
  214.         if (!writeit(Filename, (LPtr *) NULL, (LPtr *) NULL)) {
  215.             emsg("Problems occured while writing output file");
  216.             return;
  217.         }
  218.         } else {
  219.         emsg("No output file");
  220.         return;
  221.         }
  222.     }
  223.     getout(0);
  224.     }
  225.     if (strcmp(cmd, "f") == 0 && arg == NULL) {
  226.     fileinfo();
  227.     return;
  228.     }
  229.     if (*cmd == 'n') {
  230.     if ((curfile + 1) < numfiles) {
  231.         /*
  232.          * stuff ":e[!] FILE\n" 
  233.          */
  234.         stuffReadbuff(":e");
  235.         if (cmd[1] == '!')
  236.         stuffReadbuff("!");
  237.         stuffReadbuff(" ");
  238.         stuffReadbuff(files[++curfile]);
  239.         stuffReadbuff("\n");
  240.     } else
  241.         emsg("No more files!");
  242.     return;
  243.     }
  244.     if (*cmd == 'p') {
  245.     if (curfile > 0) {
  246.         /*
  247.          * stuff ":e[!] FILE\n" 
  248.          */
  249.         stuffReadbuff(":e");
  250.         if (cmd[1] == '!')
  251.         stuffReadbuff("!");
  252.         stuffReadbuff(" ");
  253.         stuffReadbuff(files[--curfile]);
  254.         stuffReadbuff("\n");
  255.     } else
  256.         emsg("No more files!");
  257.     return;
  258.     }
  259.     if (strncmp(cmd, "rew", 3) == 0) {
  260.     if (numfiles <= 1)    /* nothing to rewind */
  261.         return;
  262.     curfile = 0;
  263.     /*
  264.      * stuff ":e[!] FILE\n" 
  265.      */
  266.     stuffReadbuff(":e");
  267.     if (cmd[3] == '!')
  268.         stuffReadbuff("!");
  269.     stuffReadbuff(" ");
  270.     stuffReadbuff(files[0]);
  271.     stuffReadbuff("\n");
  272.     return;
  273.     }
  274.     if (strcmp(cmd, "e") == 0) {
  275.     if (Changed) {
  276.         emsg(nowrtmsg);
  277.     } else {
  278.         if (strcmp(arg, "%") == 0) {
  279.         (void) doecmd(NULL);
  280.         return;
  281.         }
  282. #ifdef WILD_CARDS
  283.         if (strcmp(arg, "#") != 0) {
  284.         ExpandWildCards(1, &arg, &cmd_numfiles, &cmd_files);
  285.         if (cmd_numfiles == 0) {
  286.             emsg("Can't open file");
  287.             return;
  288.         } else if (cmd_numfiles == 1) {
  289.             arg = cmd_files[0];
  290.         } else {
  291.             emsg("Too many file names");
  292.         }
  293.         }
  294. #endif
  295.         (void) doecmd(arg);
  296.     }
  297.     return;
  298.     }
  299.     if (strcmp(cmd, "e!") == 0) {
  300.     if (strcmp(arg, "%") == 0) {
  301.         if (!doecmd(NULL))
  302.             ResetBuffers();
  303.         return;
  304.     }
  305. #ifdef WILD_CARDS
  306.     if (strcmp(arg, "#") != 0) {
  307.         ExpandWildCards(1, &arg, &cmd_numfiles, &cmd_files);
  308.         if (cmd_numfiles == 0) {
  309.         emsg("Can't open file");
  310.         return;
  311.         } else if (cmd_numfiles == 1) {
  312.         arg = cmd_files[0];
  313.         } else {
  314.         emsg("Too many file names");
  315.         }
  316.     }
  317. #endif
  318.     if (!doecmd(arg))
  319.         ResetBuffers();
  320.     return;
  321.     }
  322.     if (strcmp(cmd, "f") == 0) {
  323.     Filename = strsave(arg);
  324.     filemess("");
  325.     return;
  326.     }
  327.     if (strcmp(cmd, "r") == 0 || strcmp(cmd, ".r") == 0) {
  328.     if (arg == NULL) {
  329.         badcmd();
  330.         return;
  331.     }
  332. #ifdef WILD_CARDS
  333.     if (strcmp(arg, "#") != 0) {
  334.         ExpandWildCards(1, &arg, &cmd_numfiles, &cmd_files);
  335.         if (cmd_numfiles == 0) {
  336.         emsg("Can't open file");
  337.         return;
  338.         } else if (cmd_numfiles == 1) {
  339.         arg = cmd_files[0];
  340.         } else {
  341.         emsg("Too many file names");
  342.         }
  343.     }
  344. #endif
  345.     if (readfile(arg, Curschar, 1)) {
  346.         emsg("Can't open file");
  347.         return;
  348.     }
  349.     ResetBuffers();
  350.     CHANGED;
  351.     return;
  352.     }
  353.     if (strcmp(cmd, ".=") == 0) {
  354.     smsg("line %d", cntllines(Filemem, Curschar));
  355.     return;
  356.     }
  357.     if (strcmp(cmd, "$=") == 0) {
  358.     smsg("%d", cntllines(Filemem, Fileend) - 1);
  359.     return;
  360.     }
  361.     if (strncmp(cmd, "ta", 2) == 0) {
  362.     dotag(arg, cmd[2] == '!');
  363.     return;
  364.     }
  365.     if (strcmp(cmd, "set") == 0) {
  366.     doset(arg, interactive);
  367.     return;
  368.     }
  369.     if (strcmp(cmd, "help") == 0) {
  370.     if (help())
  371.         s_clear();
  372.     return;
  373.     }
  374.     if (strcmp(cmd, "version") == 0) {
  375.     extern char    *Version;
  376.  
  377.     msg(Version);
  378.     return;
  379.     }
  380.     if (strcmp(cmd, "sh") == 0) {
  381.     doshell();
  382.     return;
  383.     }
  384.     if (strncmp(cmd, "d", 1) == 0) {
  385.     LINE           *cp;
  386.     int             n;
  387.  
  388.     if (l_pos.linep == NULL)
  389.         l_pos = *Curschar;
  390.     if (u_pos.linep == NULL)
  391.         u_pos = l_pos;
  392.  
  393.     ResetBuffers();
  394.     n = RowNumber(&l_pos);
  395.     AppendPositionToUndoUndobuff(0, n);
  396.     AppendPositionToUndobuff(0, n);
  397.     if ((Filetop->linep->next == l_pos.linep) &&
  398.         (u_pos.linep->next == Fileend->linep))
  399.         AppendToUndobuff("a");
  400.     else if (u_pos.linep->next == Fileend->linep)
  401.         AppendToUndobuff("o");
  402.     else
  403.         AppendToUndobuff("O");
  404.  
  405.     n = 0;
  406.     cp = l_pos.linep;
  407.     for (; cp != NULL && cp != Fileend->linep; cp = cp->next) {
  408.         AppendToUndobuff(cp->s);
  409.         n++;
  410.         if (cp == u_pos.linep)
  411.         break;
  412.         AppendToUndobuff(NL_STR);
  413.     }
  414.     AppendToUndobuff(ESC_STR);
  415.  
  416.     if (n > 1)
  417.         AppendNumberToUndoUndobuff(n);
  418.     AppendToUndoUndobuff("dd");
  419.  
  420.     *Curschar = l_pos;
  421.     delline(n);
  422.     S_NOT_VALID;
  423.     return;
  424.     }
  425.     if (strncmp(cmd, "s/", 2) == 0) {
  426.     dosub(&l_pos, &u_pos, cmdbuf + 1);
  427.     return;
  428.     }
  429.     if (strncmp(cmd, "g/", 2) == 0) {
  430.     doglob(&l_pos, &u_pos, cmdbuf + 1);
  431.     return;
  432.     }
  433.     if (cmd[0] == '!') {
  434.     if (cmd[1] == '\0') {
  435.         emsg("Incomplete shell escape command");
  436.         return;
  437.     }
  438.     outstr("\r\n");
  439.     flushbuf();
  440. #ifdef BSD
  441.     set_ostate();
  442. #endif
  443. #ifdef UNIX
  444.     set_ostate();
  445. #endif
  446.     (void) system(&cmd[1]);
  447. #ifdef BSD
  448.     set_nstate();
  449. #endif
  450. #ifdef UNIX
  451.     set_nstate();
  452. #endif
  453.     wait_return();
  454.     return;
  455.     }
  456.     /*
  457.      * If we got a line, but no command, then go to the line. 
  458.      */
  459.     if (*cmd == NUL && l_pos.linep != NULL) {
  460.     if (u_pos.linep != NULL)
  461.         *Curschar = u_pos;
  462.     else
  463.         *Curschar = l_pos;
  464.  
  465.     S_CHECK_TOPCHAR_AND_BOTCHAR;
  466.  
  467.     return;
  468.     }
  469.     badcmd();
  470. }
  471.  
  472. /*
  473.  * get_range - parse a range specifier 
  474.  *
  475.  * Ranges are of the form: 
  476.  *
  477.  * addr[,addr] 
  478.  *
  479.  * where 'addr' is: 
  480.  *
  481.  * %          (entire file)
  482.  * $  [+-NUM]
  483.  * 'x [+-NUM] (where x denotes a currently defined mark)
  484.  * .  [+-NUM]
  485.  * NUM 
  486.  *
  487.  * The pointer *cp is updated to point to the first character following the
  488.  * range spec. If an initial address is found, but no second, the upper bound
  489.  * is equal to the lower. 
  490.  */
  491. static void
  492. get_range(cp)
  493.     char          **cp;
  494. {
  495.     LPtr           *l;
  496.     char           *p;
  497.  
  498.     if (**cp == '%') {
  499.     l_pos.index = 0;
  500.     l_pos.linep = Filetop->linep->next;
  501.     u_pos.index = 0;
  502.     u_pos.linep = Fileend->linep->prev;
  503.     (*cp)++;
  504.     return;
  505.     }
  506.     if ((l = get_line(cp)) == NULL)
  507.     return;
  508.  
  509.     l_pos = *l;
  510.  
  511.     for (p = *cp; *p != NUL && isspace(*p); p++);
  512.  
  513.     *cp = p;
  514.  
  515.     if (*p != ',') {        /* is there another line spec ? */
  516.     u_pos = l_pos;
  517.     return;
  518.     }
  519.     *cp = ++p;
  520.  
  521.     if ((l = get_line(cp)) == NULL) {
  522.     u_pos = l_pos;
  523.     return;
  524.     }
  525.     u_pos = *l;
  526. }
  527.  
  528. static LPtr    *
  529. get_line(cp)
  530.     char          **cp;
  531. {
  532.     static LPtr     pos;
  533.     LPtr           *lp;
  534.     char           *p, c;
  535.     int             lnum;
  536.  
  537.     pos.index = 0;        /* shouldn't matter... check back later */
  538.  
  539.     p = *cp;
  540.     /*
  541.      * Determine the basic form, if present. 
  542.      */
  543.     switch (c = *p++) {
  544.  
  545.       case '$':
  546.     pos.linep = Fileend->linep->prev;
  547.     break;
  548.  
  549.       case '.':
  550.     pos.linep = Curschar->linep;
  551.     break;
  552.  
  553.       case '\'':
  554.     if ((lp = getmark(*p++)) == NULL) {
  555.         emsg("Unknown mark");
  556.         return (LPtr *) NULL;
  557.     }
  558.     pos = *lp;
  559.     break;
  560.  
  561.       case '0':
  562.       case '1':
  563.       case '2':
  564.       case '3':
  565.       case '4':
  566.       case '5':
  567.       case '6':
  568.       case '7':
  569.       case '8':
  570.       case '9':
  571.     for (lnum = c - '0'; isdigit(*p); p++)
  572.         lnum = (lnum * 10) + (*p - '0');
  573.  
  574.     if (lnum == 0)
  575.         lnum = 1;
  576.  
  577.     pos = *gotoline(lnum);
  578.     break;
  579.  
  580.       default:
  581.     return (LPtr *) NULL;
  582.     }
  583.  
  584.     while (*p != NUL && isspace(*p))
  585.     p++;
  586.  
  587.     if (*p == '-' || *p == '+') {
  588.     bool_t          neg = (*p++ == '-');
  589.  
  590.     for (lnum = 0; isdigit(*p); p++)
  591.         lnum = (lnum * 10) + (*p - '0');
  592.  
  593.     if (neg)
  594.         lnum = -lnum;
  595.  
  596.     pos = *gotoline(cntllines(Filemem, &pos) + lnum);
  597.     }
  598.     *cp = p;
  599.     return &pos;
  600. }
  601.  
  602. static void
  603. badcmd()
  604. {
  605.     if (interactive)
  606.     emsg("Unrecognized command");
  607. }
  608.  
  609. /*
  610.  * dotag(tag, force) - goto tag 
  611.  */
  612. void
  613. dotag(tag, force)
  614.     char           *tag;
  615.     bool_t          force;
  616. {
  617.     FILE           *tp, *fopen();
  618.     char            lbuf[LSIZE];
  619.     char           *fname, *str;
  620.  
  621.     if ((tp = fopen("tags", "r")) == NULL) {
  622.     emsg("Can't open tags file");
  623.     return;
  624.     }
  625.     while (fgets(lbuf, LSIZE, tp) != NULL) {
  626.     if ((fname = strchr(lbuf, TAB)) == NULL) {
  627.         emsg("Format error in tags file");
  628.         return;
  629.     }
  630.     *fname++ = '\0';
  631.     if ((str = strchr(fname, TAB)) == NULL) {
  632.         emsg("Format error in tags file");
  633.         return;
  634.     }
  635.     *str++ = '\0';
  636.  
  637.     if (strcmp(lbuf, tag) == 0) {
  638.         if (!force && Changed) {
  639.         emsg(nowrtmsg);
  640.         return;
  641.         }
  642.         if (doecmd(fname)) {
  643.         stuffReadbuff(str);    /* str has \n at end */
  644.         stuffReadbuff("\007");    /* CTRL('G') */
  645.         fclose(tp);
  646.         return;
  647.         }
  648.     }
  649.     }
  650.     emsg("tag not found");
  651.     fclose(tp);
  652. }
  653.  
  654. static          bool_t
  655. doecmd(arg)
  656.     char           *arg;
  657. {
  658.     int             line = 1;    /* line # to go to in new file */
  659.  
  660.     if (arg != NULL) {
  661.     /*
  662.      * First detect a ":e" on the current file. This is mainly for ":ta"
  663.      * commands where the destination is within the current file. 
  664.      */
  665.     if (Filename != NULL) {
  666.         if (strcmp(arg, Filename) == 0) {
  667.         if (!Changed) {
  668.                 altfile = Filename;
  669.                 altline = cntllines(Filemem, Curschar);
  670.             return TRUE;
  671.         }
  672.         }
  673.     }
  674.     if (strcmp(arg, "#") == 0) {    /* alternate */
  675.         char           *s = Filename;
  676.  
  677.         if (altfile == NULL) {
  678.         emsg("No alternate file");
  679.         return FALSE;
  680.         }
  681.         if (strcmp(altfile, Filename) == 0) {
  682.         if (!Changed) {
  683.                 line = altline;
  684.                 altline = cntllines(Filemem, Curschar);
  685.             goto DO_THE_STUFF_THING;
  686.         }
  687.         }
  688.         Filename = altfile;
  689.         altfile = s;
  690.         line = altline;
  691.         altline = cntllines(Filemem, Curschar);
  692.     } else {
  693.         altfile = Filename;
  694.         altline = cntllines(Filemem, Curschar);
  695.         Filename = strsave(arg);
  696.     }
  697.     }
  698.     if (Filename == NULL) {
  699.     emsg("No filename");
  700.     return FALSE;
  701.     }
  702.     /* clear mem and read file */
  703.     freeall();
  704.     filealloc();
  705.     UNCHANGED;
  706.  
  707.     if (readfile(Filename, Filemem, 0)) {
  708.     emsg("Can't open file");
  709.     return FALSE;
  710.     }
  711.     *Topchar = *Curschar;
  712.     if (line != 1) {
  713. DO_THE_STUFF_THING:
  714.     stuffnumReadbuff(line);
  715.     stuffReadbuff("G");
  716.     }
  717.     setpcmark();
  718.  
  719.     return TRUE;
  720. }
  721.  
  722. static void
  723. doshell()
  724. {
  725.     char           *sh, *getenv();
  726.  
  727.     sh = getenv("SHELL");
  728.     if (sh == NULL) {
  729.     emsg("Shell variable not set");
  730.     return;
  731.     }
  732.     gotocmdline(YES, NUL);
  733.  
  734.     if (system(sh) < 0) {
  735.     emsg("Exec failed");
  736.     return;
  737.     }
  738.     wait_return();
  739. }
  740.  
  741. void
  742. gotocmdline(clr, firstc)
  743.     bool_t          clr;
  744.     char            firstc;
  745. {
  746.     windgoto(Rows - 1, 0);
  747.     if (clr)
  748.     outstr(T_EL);        /* clear the bottom line */
  749.     if (firstc)
  750.     outchar(firstc);
  751. }
  752.  
  753. /*
  754.  * msg(s) - displays the string 's' on the status line 
  755.  */
  756. void
  757. msg(s)
  758.     char           *s;
  759. {
  760.     gotocmdline(YES, NUL);
  761.     outstr(s);
  762. #ifdef AMIGA
  763.     flushbuf();
  764. #endif
  765. #ifdef BSD
  766.     flushbuf();
  767. #endif
  768. }
  769.  
  770. /* VARARGS */
  771. void
  772. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  773.     char           *s;
  774.     int             a1, a2, a3, a4, a5, a6, a7, a8, a9;
  775. {
  776.     char            sbuf[MAX_COLUMNS + 1];
  777.  
  778.     sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  779.     msg(sbuf);
  780. }
  781.  
  782. /*
  783.  * emsg() - display an error message 
  784.  *
  785.  * Rings the bell, if appropriate, and calls message() to do the real work 
  786.  */
  787. void
  788. emsg(s)
  789.     char           *s;
  790. {
  791.     UndoInProgress = FALSE;
  792.     RedrawingDisabled = FALSE;
  793.  
  794.     if (P(P_EB))
  795.     beep();
  796.     outstr(T_TI);
  797.     msg(s);
  798.     outstr(T_TP);
  799. #ifdef AMIGA
  800.     flushbuf();
  801. #endif
  802. #ifdef BSD
  803.     flushbuf();
  804. #endif
  805. }
  806.  
  807. void
  808. wait_return()
  809. {
  810.     char            c;
  811.  
  812.     outstr("Press RETURN to continue");
  813.     do {
  814.     c = vgetc();
  815.     } while (c != '\r' && c != '\n');
  816.  
  817.     s_clear();
  818. }
  819.