home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_cmds2.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  7KB  |  492 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "ex.h"
  3. #include "ex_argv.h"
  4. #include "ex_temp.h"
  5. #include "ex_tty.h"
  6. #include "ex_vis.h"
  7.  
  8. bool    pflag, nflag;
  9. int    poffset;
  10.  
  11. /*
  12.  * Subroutines for major command loop.
  13.  */
  14.  
  15. /*
  16.  * Is there a single letter indicating a named buffer next?
  17.  */
  18. cmdreg()
  19. {
  20.     register int c = 0;
  21.  
  22.     pastwh();
  23.     if (isalpha(peekchar()))
  24.         c = getchar();
  25.     return (c);
  26. }
  27.  
  28. /*
  29.  * Tell whether the character ends a command
  30.  */
  31. endcmd(ch)
  32.     int ch;
  33. {
  34.     switch (ch) {
  35.     
  36.     case '\n':
  37.     case EOF:
  38.         endline = 1;
  39.         return (1);
  40.     
  41.     case '|':
  42.         endline = 0;
  43.         return (1);
  44.     }
  45.     return (0);
  46. }
  47.  
  48. /*
  49.  * Insist on the end of the command.
  50.  */
  51. eol()
  52. {
  53.  
  54.     if (!skipend())
  55.         error("Extra chars|Extra characters at end of command");
  56.     ignnEOF();
  57. }
  58.  
  59. /*
  60.  * Print out the message in the error message file at str,
  61.  * with i an integer argument to printf.
  62.  */
  63. /*VARARGS2*/
  64. error(str, i)
  65. #ifdef lint
  66.     register char *str;
  67. #else
  68.     register int str;
  69. #endif
  70.     int i;
  71. {
  72.  
  73.     error0();
  74.     merror(str, i);
  75.     error1(str);
  76. }
  77.  
  78. /*
  79.  * Rewind the argument list.
  80.  */
  81. erewind()
  82. {
  83.  
  84.     argc = argc0;
  85.     argv = argv0;
  86.     args = args0;
  87.     if (argc > 1 && !hush) {
  88.         printf(mesg("%d files@to edit"), argc);
  89.         if (inopen)
  90.             putchar(' ');
  91.         else
  92.             putNFL();
  93.     }
  94. }
  95.  
  96. /*
  97.  * Guts of the pre-printing error processing.
  98.  * If in visual and catching errors, then we dont mung up the internals,
  99.  * just fixing up the echo area for the print.
  100.  * Otherwise we reset a number of externals, and discard unused input.
  101.  */
  102. error0()
  103. {
  104.  
  105.     intag = 0;
  106.     if (vcatch) {
  107.         if (splitw == 0)
  108.             fixech();
  109.         if (!SO || !SE)
  110.             dingdong();
  111.         return;
  112.     }
  113.     if (input) {
  114.         input = strend(input) - 1;
  115.         if (*input == '\n')
  116.             setlastchar('\n');
  117.         input = 0;
  118.     }
  119.     setoutt();
  120.     flush();
  121.     resetflav();
  122.     if (laste) {
  123.         laste = 0;
  124.         sync();
  125.     }
  126.     if (!SO || !SE)
  127.         dingdong();
  128.     if (inopen) {
  129.         /*
  130.          * We are coming out of open/visual ungracefully.
  131.          * Restore COLUMNS, undo, and fix tty mode.
  132.          */
  133.         COLUMNS = OCOLUMNS;
  134.         undvis();
  135.         ostop(normf);
  136.         putpad(VE);
  137.         putnl();
  138.     }
  139.     inopen = 0;
  140.     holdcm = 0;
  141. }
  142.  
  143. /*
  144.  * Post error printing processing.
  145.  * Close the i/o file if left open.
  146.  * If catching in visual then throw to the visual catch,
  147.  * else if a child after a fork, then exit.
  148.  * Otherwise, in the normal command mode error case,
  149.  * finish state reset, and throw to top.
  150.  */
  151. error1(str)
  152.     char *str;
  153. {
  154.  
  155.     if (io > 0) {
  156.         close(io);
  157.         io = -1;
  158.     }
  159.     if (vcatch && !die) {
  160.         inglobal = 0;
  161.         inopen = 1;
  162.         vcatch = 0;
  163.         fixol();
  164.         longjmp(vreslab);
  165.     }
  166.     if (str)
  167.         putNFL();
  168.     if (die)
  169.         exit(1);
  170.     lseek(0, 0L, 2);
  171.     if (inglobal)
  172.         setlastchar('\n');
  173.     inglobal = 0;
  174.     globp = 0;
  175.     while (lastchar() != '\n' && lastchar() != EOF)
  176.         ignchar();
  177.     ungetchar(0);
  178.     endline = 1;
  179.     reset();
  180. }
  181.  
  182. fixol()
  183. {
  184.     if (Outchar != vputchar) {
  185.         flush();
  186.         if (state == ONEOPEN || state == HARDOPEN)
  187.             outline = destline = 0;
  188.         Outchar = vputchar;
  189.         vcontin(1);
  190.     } else {
  191.         if (destcol)
  192.             vclreol();
  193.         vclean();
  194.     }
  195. }
  196.  
  197. /*
  198.  * Does an ! character follow in the command stream?
  199.  */
  200. exclam()
  201. {
  202.  
  203.     if (peekchar() == '!') {
  204.         ignchar();
  205.         return (1);
  206.     }
  207.     return (0);
  208. }
  209.  
  210. /*
  211.  * Make an argument list for e.g. next.
  212.  */
  213. makargs()
  214. {
  215.  
  216.     glob(&frob);
  217.     argc0 = frob.argc0;
  218.     argv0 = frob.argv;
  219.     args0 = argv0[0];
  220.     erewind();
  221. }
  222.  
  223. /*
  224.  * Advance to next file in argument list.
  225.  */
  226. next()
  227. {
  228.  
  229.     if (argc == 0)
  230.         error("No more files@to edit");
  231.     morargc = argc;
  232.     if (savedfile[0])
  233.         CP(altfile, savedfile);
  234.     CP(savedfile, args);
  235.     argc--;
  236.     args = argv ? *++argv : strend(args) + 1;
  237. }
  238.  
  239. /*
  240.  * Eat trailing flags and offsets after a command,
  241.  * saving for possible later post-command prints.
  242.  */
  243. newline()
  244. {
  245.     register int c;
  246.  
  247.     resetflav();
  248.     for (;;) {
  249.         c = getchar();
  250.         switch (c) {
  251.  
  252.         case '^':
  253.         case '-':
  254.             poffset--;
  255.             break;
  256.  
  257.         case '+':
  258.             poffset++;
  259.             break;
  260.  
  261.         case 'l':
  262.             listf++;
  263.             break;
  264.  
  265.         case '#':
  266.             nflag++;
  267.             break;
  268.  
  269.         case 'p':
  270.             listf = 0;
  271.             break;
  272.  
  273.         case ' ':
  274.         case '\t':
  275.             continue;
  276.  
  277.         default:
  278.             if (!endcmd(c))
  279.                 serror("Extra chars|Extra characters at end of \"%s\" command", Command);
  280.             if (c == EOF)
  281.                 ungetchar(c);
  282.             setflav();
  283.             return;
  284.         }
  285.         pflag++;
  286.     }
  287. }
  288.  
  289. /*
  290.  * Before quit or respec of arg list, check that there are
  291.  * no more files in the arg list.
  292.  */
  293. nomore()
  294. {
  295.  
  296.     if (argc == 0 || morargc == argc)
  297.         return;
  298.     morargc = argc;
  299.     merror("%d more file", argc);
  300.     serror("%s@to edit", plural((long) argc));
  301. }
  302.  
  303. /*
  304.  * Before edit of new file check that either an ! follows
  305.  * or the file has not been changed.
  306.  */
  307. quickly()
  308. {
  309.  
  310.     if (exclam())
  311.         return (1);
  312.     if (chng) {
  313. /*
  314.         chng = 0;
  315. */
  316.         xchng = 0;
  317.         error("No write@since last change (%s! overrides)", Command);
  318.     }
  319.     return (0);
  320. }
  321.  
  322. /*
  323.  * Reset the flavor of the output to print mode with no numbering.
  324.  */
  325. resetflav()
  326. {
  327.  
  328.     if (inopen)
  329.         return;
  330.     listf = 0;
  331.     nflag = 0;
  332.     pflag = 0;
  333.     poffset = 0;
  334.     setflav();
  335. }
  336.  
  337. /*
  338.  * Print an error message with a %s type argument to printf.
  339.  * Message text comes from error message file.
  340.  */
  341. serror(str, cp)
  342. #ifdef lint
  343.     register char *str;
  344. #else
  345.     register int str;
  346. #endif
  347.     char *cp;
  348. {
  349.  
  350.     error0();
  351.     smerror(str, cp);
  352.     error1(str);
  353. }
  354.  
  355. /*
  356.  * Set the flavor of the output based on the flags given
  357.  * and the number and list options to either number or not number lines
  358.  * and either use normally decoded (ARPAnet standard) characters or list mode,
  359.  * where end of lines are marked and tabs print as ^I.
  360.  */
  361. setflav()
  362. {
  363.  
  364.     if (inopen)
  365.         return;
  366.     setnumb(nflag || value(NUMBER));
  367.     setlist(listf || value(LIST));
  368.     setoutt();
  369. }
  370.  
  371. /*
  372.  * Skip white space and tell whether command ends then.
  373.  */
  374. skipend()
  375. {
  376.  
  377.     pastwh();
  378.     return (endcmd(peekchar()));
  379. }
  380.  
  381. /*
  382.  * Set the command name for non-word commands.
  383.  */
  384. tailspec(c)
  385.     int c;
  386. {
  387.     static char foocmd[2];
  388.  
  389.     foocmd[0] = c;
  390.     Command = foocmd;
  391. }
  392.  
  393. /*
  394.  * Try to read off the rest of the command word.
  395.  * If alphabetics follow, then this is not the command we seek.
  396.  */
  397. tail(comm)
  398.     char *comm;
  399. {
  400.  
  401.     tailprim(comm, 1, 0);
  402. }
  403.  
  404. tail2of(comm)
  405.     char *comm;
  406. {
  407.  
  408.     tailprim(comm, 2, 0);
  409. }
  410.  
  411. char    tcommand[20];
  412.  
  413. tailprim(comm, i, notinvis)
  414.     register char *comm;
  415.     int i;
  416.     bool notinvis;
  417. {
  418.     register char *cp;
  419.     register int c;
  420.  
  421.     Command = comm;
  422.     for (cp = tcommand; i > 0; i--)
  423.         *cp++ = *comm++;
  424.     while (*comm && peekchar() == *comm)
  425.         *cp++ = getchar(), comm++;
  426.     c = peekchar();
  427.     if (notinvis || isalpha(c)) {
  428.         /*
  429.          * Of the trailing lp funny buisness, only dl and dp
  430.          * survive the move from ed to ex.
  431.          */
  432.         if (tcommand[0] == 'd' && any(c, "lp"))
  433.             goto ret;
  434.         while (cp < &tcommand[19] && isalpha(peekchar()))
  435.             *cp++ = getchar();
  436.         *cp = 0;
  437.         if (notinvis)
  438.             serror("What?|%s: No such command from open/visual", tcommand);
  439.         else
  440.             serror("What?|%s: Not an editor command", tcommand);
  441.     }
  442. ret:
  443.     *cp = 0;
  444. }
  445.  
  446. /*
  447.  * Continue after a shell escape from open/visual.
  448.  */
  449. vcontin(ask)
  450.     bool ask;
  451. {
  452.  
  453.     if (vcnt > 0)
  454.         vcnt = -vcnt;
  455.     if (inopen) {
  456.         if (state != VISUAL) {
  457. /*
  458.             vtube[WECHO][0] = '*';
  459.             vnfl();
  460. */
  461.             return;
  462.         }
  463.         if (ask) {
  464.             merror("[Hit return to continue] ");
  465.             flush();
  466.         }
  467. #ifdef V6
  468.         vraw();
  469. #endif
  470.         if (ask && getkey() == ':')
  471.             ungetkey(':');
  472.     }
  473. }
  474.  
  475. /*
  476.  * Put out a newline (before a shell escape)
  477.  * if in open/visual.
  478.  */
  479. vnfl()
  480. {
  481.  
  482.     if (inopen) {
  483.         if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
  484.             vclean();
  485.         else
  486.             vmoveitup(1);
  487.         vgoto(WECHO, 0);
  488.         vclrbyte(vtube[WECHO], WCOLS);
  489.         flush();
  490.     }
  491. }
  492.