home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / editor / tvx_edit.arc / TVX_EDIT.C < prev    next >
C/C++ Source or Header  |  1986-03-17  |  34KB  |  1,311 lines

  1. /* ---------------------------------------------------------------------
  2.     This module contains the main edit routine, which is
  3. different for each editor being emulated.  The code that is unique
  4. to each emulation is confined to the three .ic files, tvx_lex.c, and
  5. this module.  The remainder of the tvx files are the same for all versions.
  6.  
  7.  
  8.    This version of TVX Copyright (c) 1986 by Bruce E. Wampler
  9.  
  10.    Permission is hereby granted for free, unrestricted nonprofit
  11.    use of this software.  Please feel free to modify, distribute,
  12.    and share this software as long as you aren't making any money
  13.    from it.  If you want to use this code in a profit making environment,
  14.    please contact the author for permission.
  15.  
  16. --------------------------------------------------------------------- */
  17.  
  18. #include "tvx_defs.ic"        /* note tv_defs.ic will #include stdio.h */
  19. #include "tvx_glbl.ic"
  20.  
  21.   char clower(),cupper();
  22.  
  23.  
  24. #ifdef TVX_CMDSET        /* works for both tvx_em and tvx0m_em */
  25. /* =============================>>> EDIT   <<<============================= */
  26.   edit()
  27.   { /*    edit - main editing routine */
  28.  
  29.     SLOW int lexval,lexcnt,succ, lastln, itmp;
  30.     SLOW int noteloc[10], ni, lex_def;
  31.     SLOW char lexchr;
  32.  
  33.     static int ins_set[] =        /* allowable commands for insert */
  34.       {
  35.     VINSERT, VOPENLINE, VQUIT, VABORT, VFBEGIN, VGET, VYANK, 0
  36.       };
  37.  
  38.     static int jump_set[] =    /* commands to not reset jump memory */
  39.       {
  40.     VJUMP, VMEMORY, VHELP, VNOTELOC, VPRINTS, 0
  41.       };
  42.     SLOW char fchr;        /* temp char for prefixed commands */
  43.  
  44.     startm();
  45.     remark("Reading file...");
  46.  
  47.     rdpage();            /* read a page into the buffer */
  48.  
  49.     tvclr();            /* clear the screen */
  50.  
  51.     if (curlin >= 1)
  52.     tvtype(curlin,tvlins);    /* type out lines */
  53.  
  54.     tvxy(1,1);            /* and rehome the cursor */
  55.     waserr = FALSE;        /* no errors to erase yet */
  56.  
  57.     if (curlin<1)
  58.     tverr("Buffer empty");
  59. #ifdef SCR_BUF
  60.     ttflush();
  61. #endif
  62.  
  63.     lexval = UNKNOWN;        /* so can remember 1st time through */
  64.     useprint = FALSE;        /* not to printer */
  65.     succ=TRUE;            /* assume success initially */
  66.  
  67.     lastln = 1    ;        /* remember where we were */
  68.     for (ni = 0 ; ni < 10 ; noteloc[ni++] = 1)
  69.     ;            /* init noteloc */
  70.     do
  71.       {
  72.     oldlex = lexval;        /* remember last command */
  73.     if (! succ)
  74.         echof = TRUE;        /* resume echo when error */
  75.     lex_def = lex(&lexval,&lexcnt,&lexchr,succ);    /* get command input */
  76.     if (waserr)
  77.         fixend();
  78.     waserr=FALSE;
  79.     succ=TRUE;
  80.     if (lexval == UNKNOWN)
  81.       {
  82.         cmderr(lexchr);
  83.         succ = FALSE;    /* announce failure to lex */
  84.       }
  85.     else
  86.       {
  87.         if (curlin < 1)    /* make sure legal command for empty buffer */
  88.           {
  89.         if (!inset(lexval,ins_set))
  90.           {
  91.             tverrb("Can't, buffer empty. Insert 1st ");
  92.             succ=FALSE;
  93.             continue;
  94.           }
  95.           }
  96.         if (!inset(lexval,jump_set))
  97.         lastln=curlin;        /* let user look at help w/o changing */
  98.  
  99.         switch (lexval)
  100.         {
  101. case 1:             /* right */
  102.         right(lexcnt);
  103.         break;
  104. case 2:             /* left */
  105.         right(-lexcnt);
  106.         break;
  107. case 3:             /* down line */
  108.         dwnlin(lexcnt);
  109.         break;
  110. case 4:             /* up line */
  111.         dwnlin(-lexcnt);
  112.         break;
  113. case 5:             /* down in column */
  114.         dwncol(lexcnt);
  115.         break;
  116. case 6:             /* up in column */
  117.         dwncol(-lexcnt);
  118.         break;
  119. case 7:             /* delete last character */
  120.         succ = delnxt(-lexcnt);
  121.         break;
  122. case 8:             /* delete next character */
  123.         succ = delnxt(lexcnt);
  124.         break;
  125. case 9:             /* insert */
  126.         succ = insert(lexcnt,lex_def);
  127.         break;
  128. case 10:            /* kill a line */
  129.         killin(lexcnt);
  130.         break;
  131. case 11:            /* kill rest of line */
  132.         krest();
  133.         break;
  134. case 12:            /* kill previous part of line */
  135.         kprev();
  136.         break;
  137. case 13:            /* move to beginning of line */
  138.         beglin();
  139.         break;
  140. case 14:            /* move to end of the line */
  141.         endlin();
  142.         break;
  143. case 15:            /* search for a pattern */
  144.         succ = search(lexcnt,TRUE);
  145.         break;
  146. case 16:            /* search for next part of a pattern */
  147.         succ = snext(lexcnt,TRUE);
  148.         break;
  149. case 17:            /* flip screen */
  150.         dwnlin(min(lexcnt*tvlins,nxtlin-curlin+1));
  151.         break;
  152. case 18:            /* goto top of page */
  153.         toppag();
  154.         break;
  155. case 19:            /* goto to bottom of page */
  156.         botpag();
  157.         break;
  158. case 20:            /* goto real beginning of the file */
  159.         succ = fbeg();
  160.         break;
  161. case 21:            /* verify */
  162.         verify(lexcnt);
  163.         break;
  164. case 22:            /* open new line */
  165.         openln(lexcnt);
  166. #ifdef TVX_EM            /* don't need insert for modeless tvx */
  167.         succ = insert(1,TRUE); /* go into insert mode, insert mode */
  168. #endif
  169.         break;
  170. case 23:            /* delete last thing manipulated */
  171.         succ = rmvlst();
  172.         break;
  173. case 24:            /* save lines in move buffer */
  174.         succ = save(lexcnt,FALSE);
  175.         break;
  176. case 25:            /* get move buffer */
  177.         succ = getsav();
  178.         break;
  179. case 26:            /* read in next page of file */
  180.         wtpage(lexcnt);    /* write out the current page */
  181.         succ = rdpage();    /* read in the next */
  182.         tvclr();
  183.         if (succ || lexcnt < 0)
  184.         verify(1);
  185.         break;
  186. case 27:            /* append external file to save buffer */
  187.         succ = addfil(lexcnt);
  188.         break;
  189. case 28:            /* quit */
  190.         tvclr();
  191.         remark("Exit");
  192.         goto lquit;
  193. case 29:            /* search again */
  194.         succ = search(lexcnt,FALSE); /* FALSE => don't read search string */
  195.         break;
  196. case 30:            /* execute repeat buffer again */
  197.         if (lexcnt != 1)
  198.         echof=FALSE;    /* turn off echo */
  199.         rptcnt[rptuse] = lexcnt > 0 ? lexcnt : (-lexcnt);
  200.         break;
  201. case 31:            /* print memory status, etc. */
  202.         memory();
  203.         break;
  204. case 32:            /* change a parameter */
  205.         if (!grptch(&fchr))
  206.           {
  207.         succ = FALSE;
  208.         break;
  209.           }
  210.         setpar(lexcnt,fchr);
  211.         break;
  212. case 33:            /* remove last and enter insert mode */
  213.         if ((succ = rmvlst()))
  214.         succ = insert(1,TRUE);
  215.         break;
  216. case 34:            /* unkill last line killed */
  217.         succ = unkill();
  218.         break;
  219. case 35:            /* jump over a word */
  220.         wordr(lexcnt);
  221.         break;
  222. case 36:            /* neg jump over word */
  223.         wordr(-lexcnt);
  224.         break;
  225. case 37:            /* append to save buffer */
  226.         succ = save(lexcnt,TRUE);
  227.         break;
  228. case 38:            /* print screen */
  229.         scrprint();
  230.         break;
  231. case 39:            /* show repeat buffer + help*/
  232.         shoset();
  233.         break;
  234. case 40:            /* flip screen half page */
  235.         dwnlin( min((lexcnt*tvlins)/2 , nxtlin-curlin+1) );
  236.         break;
  237. case 41:            /* abort */
  238.         abort();
  239.         break;
  240. case 42:            /* change characters */
  241.         if ((succ = delnxt(lexcnt)))
  242.         succ = insert(1,TRUE);
  243.         break;
  244. case 43:            /* jump back to last location */
  245.         itmp = curlin;
  246.         curlin = lastln;
  247.         curchr = *(lines+curlin)+1;    /* point to the current character */
  248.         verify(1);
  249.         lastln = itmp;
  250.         break;
  251. case 44:            /* tidy up screen */
  252.         succ = neaten(lexcnt);
  253.         break;
  254. case 45:            /* save current location */
  255.         if (lexcnt < 1 || lexcnt > 9)
  256.         lexcnt = 0;
  257.         noteloc[lexcnt] = curlin;
  258.         break;
  259. case 46:            /* return to noted location */
  260.         itmp = curlin;
  261.         if (lexcnt < 1 || lexcnt > 9)
  262.         lexcnt = 0;
  263.         if (noteloc[lexcnt] >= nxtlin)
  264.           {
  265.         tverrb("Line no longer there ");
  266.         noteloc[lexcnt] = curlin;
  267.           }
  268.         else
  269.           {
  270.         curlin = noteloc[lexcnt];
  271.         curchr = *(lines+curlin)+1; /* point to the current character */
  272.         verify(1);
  273.         lastln = itmp;
  274.           }
  275.         break;
  276.  
  277. case 47:
  278.         opsystem();        /* call operating system */
  279.         break;
  280.  
  281. case 48:
  282.         if (lex_def)        /* default 1 passed */
  283.         lexcnt = rptuse + 1;    /* use current repeat loop */
  284.         succ = edit_rpt(lexcnt);    /* edit repeat buffer */
  285.         break;
  286.  
  287. case 49:
  288.         succ = store_rpt(lexcnt);    /* store repeat buffer */
  289.         break;
  290.  
  291. case 50:
  292.         succ = exec_rpt(lexcnt);    /* execute repeat buffer */
  293.         break;
  294.  
  295. case 51:
  296.         succ = ins_pat(lexcnt);
  297.         break;
  298. case 52:
  299.         succ = user_1(lexcnt);    /* user function 1 */
  300.         break;
  301.  
  302. case 53:
  303.         succ = user_2(lexcnt);    /* user function 2 */
  304.         break;
  305. case 54:                /* '~': change case */
  306.         foldcase(lexcnt);
  307.         break;
  308.         }              /* end of switch */
  309.         continue;        /* next iteration of do loop */
  310.       } /* end of else */
  311. #ifdef SCR_BUF
  312.     ttflush();
  313. #endif
  314.       } /* end of do loop */
  315.     while (1);
  316.  
  317. lquit:
  318.     for ( wtpage(1) ; rdpage() ; wtpage(1) )    /* write whole file */
  319.     ;
  320.     tvclr();
  321.   }
  322. #endif
  323.  
  324. #ifdef VI_EM            /* vi emulation */
  325. /* =============================>>> EDIT   <<<============================= */
  326.   edit()
  327.   { /*    edit - main editing routine */
  328.  
  329.     SLOW int lexval,lexcnt,succ, lastln, itmp;
  330.     SLOW int noteloc[10], ni, lex_def;
  331.     SLOW char lexchr;
  332.  
  333.     static int ins_set[] =    /* MUCH more limited than tvx */
  334.       {
  335.     VINSERT, VENDZ, VTVX, VNOOP, 0
  336.       };
  337.  
  338.     static int jump_set[] =    /* commands to not reset jump memory */
  339.       {
  340.     VTVX, VMEMORY, VHELP, VNOTELOC, VNOOP, 0
  341.       };
  342.     SLOW char fchr;        /* temp char for prefixed commands */
  343.     static int dir_up = FALSE;    /* search down by default */
  344.  
  345.     startm();
  346.     remark("Reading file...");
  347.  
  348.     rdpage();            /* read a page into the buffer */
  349.  
  350.     tvclr();            /* clear the screen */
  351.  
  352.     if (curlin >= 1)
  353.     tvtype(curlin,tvlins);    /* type out lines */
  354.  
  355.     tvxy(1,1);            /* and rehome the cursor */
  356.     waserr = FALSE;        /* no errors to erase yet */
  357.  
  358.     if (curlin<1)
  359.     tverr("Buffer empty");
  360. #ifdef SCR_BUF
  361.     ttflush();
  362. #endif
  363.  
  364.     lexval = UNKNOWN;        /* so can remember 1st time through */
  365.     useprint = FALSE;        /* not to printer */
  366.     succ=TRUE;            /* assume success initially */
  367.  
  368.     lastln = 1    ;        /* remember where we were */
  369.     for (ni = 0 ; ni < 10 ; noteloc[ni++] = 1)
  370.     ;            /* init noteloc */
  371.     do
  372.       {
  373.     oldlex = lexval;        /* remember last command */
  374.     if (! succ)
  375.         echof = TRUE;        /* resume echo when error */
  376.     lex_def = lex(&lexval,&lexcnt,&lexchr,succ);    /* get command input */
  377.     if (waserr)
  378.         fixend();
  379.     waserr=FALSE;
  380.     succ=TRUE;
  381.     if (lexval == UNKNOWN)
  382.       {
  383.         cmderr(lexchr);
  384.         succ = FALSE;    /* announce failure to lex */
  385.       }
  386.     else
  387.       {
  388.         if (curlin < 1)    /* make sure legal command for empty buffer */
  389.           {
  390.         if (!inset(lexval,ins_set))
  391.           {
  392.             tverrb("Can't, buffer empty. Insert 1st ");
  393.             succ=FALSE;
  394.             continue;
  395.           }
  396.           }
  397.         if (!inset(lexval,jump_set))
  398.         lastln=curlin;        /* let user look at help w/o changing */
  399.  
  400. /* these all started out in order, but... */
  401.         switch (lexval)
  402.         {
  403. case 1:             /* ^B: screen up */
  404.         dwnlin(min(-lexcnt*tvlins,nxtlin-curlin+1));
  405.         break;
  406. case 2:             /* ^D: half screen */
  407.         dwnlin( min((lexcnt*tvlins)/2 , nxtlin-curlin+1) );
  408.         break;
  409. case 3:             /* ^F: screen down */
  410.         dwnlin(min(lexcnt*tvlins,nxtlin-curlin+1));
  411.         break;
  412. case 4:             /* ^G: memory status */
  413.         memory();
  414.         break;
  415. case 5:             /* ^H: left (must be here to avoid
  416.                     conflict with normal char del */
  417.         right(-lexcnt);
  418.         break;
  419. case 6:             /* ^L: verify screen */
  420.         verify(lexcnt);
  421.         break;
  422. case 7:             /* '=': help */
  423.         shoset();
  424.         break;
  425. case 8:             /* '!' - tidy */
  426.         succ = neaten(lexcnt);
  427.         break;
  428. case 9:             /* '#': execute macro n times */
  429.         succ = exec_rpt(lexcnt);    /* execute repeat buffer */
  430.         break;
  431. case 10:            /* '$': end of current line */
  432.         endlin();
  433.         break;
  434. case 11:            /* '*': insert last found pattern */
  435.         succ = ins_pat(lexcnt);
  436.         break;
  437. case 12:            /* '/': search down */
  438.         dir_up = FALSE;
  439.         succ = search(1,TRUE);    /* searching down*/
  440.         break;
  441. case 13:            /* ':': set parameter, just like tvx */
  442.         tverrb("Use ZZ to exit ");
  443.         break;
  444. case 14:            /* 'J': join lines */
  445.         endlin();
  446.         delnxt(lexcnt);
  447.         succ = insert((int) ' ',FALSE);
  448.         break;
  449. case 15:            /* '?': find upwards */
  450.         dir_up = TRUE;
  451.         succ = search(-1,TRUE);
  452.         break;
  453. case 16:            /* '@': execute current repeat loop */
  454.         if (lexcnt != 1)
  455.         echof=FALSE;    /* turn off echo */
  456.         rptcnt[rptuse] = lexcnt > 0 ? lexcnt : (-lexcnt);
  457.         break;
  458. case 17:            /* 'A': append to end of line {.i} */
  459.         endlin();
  460.         succ = insert(1,TRUE); /* go into insert mode, insert mode */
  461.         break;
  462. case 18:            /* 'C': changes rest of line {"i } */
  463.         krest();        /* kill rest of line */
  464.         succ = insert(1,TRUE); /* enter insert mode */
  465.         break;
  466. case 19:            /* 'D': delete rest of the line {"} */
  467.         krest();        /* kill rest of line */
  468.         break;
  469. case 20:            /* 'G': goes to line number n, or
  470.                     end of buffer if no n */
  471.         if (lex_def)    /* no n supplied */
  472.         botpag();
  473.         else
  474.           {
  475.         toppag();    /* go to top of file */
  476.         dwnlin(lexcnt - 1);    /* go to that line */
  477.           }
  478.         break;
  479. case 21:            /* 'H': Beginning of buffer */
  480.         toppag();        /* go to top of buffer */
  481.         break;
  482.  
  483. case 22:            /* 'I': inserts a beginning of line */
  484.         beglin();
  485.         succ = insert(1,TRUE); /* go into insert mode */
  486.         break;
  487. case 23:            /* 'J': like vi j - down in column */
  488.         dwncol(lexcnt);
  489.         break;
  490. case 24:            /* 'K': like vi k - up in column */
  491.         dwncol(-lexcnt);
  492.         break;
  493. case 25:            /* 'L': bottom line of file */
  494.         botpag();
  495.         beglin();
  496.         break;
  497. case 26:            /* 'M': return to marked location */
  498.         itmp = curlin;
  499.         if (lexcnt < 1 || lexcnt > 9)
  500.         lexcnt = 0;
  501.         if (noteloc[lexcnt] >= nxtlin)
  502.           {
  503.         tverrb("Line no longer there ");
  504.         noteloc[lexcnt] = curlin;
  505.           }
  506.         else
  507.           {
  508.         curlin = noteloc[lexcnt];
  509.         curchr = *(lines+curlin)+1; /* point to the current character */
  510.         verify(1);
  511.         lastln = itmp;
  512.           }
  513.         break;
  514. case 27:            /* 'N': reverse find again */
  515.         succ = search((dir_up ? 1 : -1),FALSE);
  516.              /* FALSE => don't read search string */
  517.         break;
  518. case 28:            /* 'O': open a line above current line */
  519.         beglin();
  520.         openln(lexcnt);
  521.         succ = insert(1,TRUE); /* go into insert mode, insert mode */
  522.         break;
  523. case 29:            /* 'P': put save buffer above current line */
  524.         beglin();
  525.         succ = getsav();
  526.         break;
  527. case 30:            /* 'T': tvx commands */
  528.         if (!grptch(&fchr))
  529.           {
  530.         succ = FALSE;
  531.         break;
  532.           }
  533.         fchr = clower(fchr);    /* lower case */
  534.         if (curlin < 1)    /* make sure legal command for empty buffer */
  535.           {
  536.         if ( fchr != 'b')
  537.           {
  538.             tverrb("Can't, buffer empty. Insert 1st ");
  539.             succ=FALSE;
  540.             break;
  541.           }
  542.           }
  543.         switch (fchr)
  544.         {
  545.         case ':':            /* set parameter */
  546.         if (!grptch(&fchr))
  547.           {
  548.             succ = FALSE;
  549.             break;
  550.           }
  551.         setpar(lexcnt,fchr);
  552.         break;
  553.         case '!':
  554.         opsystem();        /* call operating system */
  555.         break;
  556.         case 'b':            /* goto real beginning of the file */
  557.         succ = fbeg();
  558.         break;
  559.         case 'e':            /* edit repeat buffer */
  560.         if (lex_def)        /* default 1 passed */
  561.             lexcnt = rptuse + 1;    /* use current repeat loop */
  562.         succ = edit_rpt(lexcnt);    /* edit repeat buffer */
  563.         break;
  564.         case 'j':            /* jump back to last location */
  565.         itmp = curlin;
  566.         curlin = lastln;
  567.         curchr = *(lines+curlin)+1; /* point to the current character */
  568.         verify(1);
  569.         lastln = itmp;
  570.         break;
  571.         case 'p':        /* put external file from save buffer */
  572.         succ = addfil(-1);
  573.         break;
  574.         case 'r':            /* restore repeat buffer */
  575.         succ = store_rpt(lexcnt);    /* store repeat buffer */
  576.         break;
  577.         case 's':            /* print screen */
  578.         scrprint();
  579.         break;
  580.         case 'u':            /* "undo" */
  581.         succ = unkill();
  582.         break;
  583.         case 'w':            /* read in next page of file */
  584.         wtpage(lexcnt);    /* write out the current page */
  585.         succ = rdpage();    /* read in the next */
  586.         tvclr();
  587.         if (succ || lexcnt < 0)
  588.             verify(1);
  589.         break;
  590.         case 'y':        /* yank external file to save buffer */
  591.         succ = addfil(1);
  592.         break;
  593.         case '/':        /* search across buffers */
  594.         succ = snext(1,TRUE);
  595.         break;
  596.         case '(':        /* user 1 */
  597.         succ = user_1(lexcnt);    /* user function 1 */
  598.         break;
  599.         default:
  600.         tverrb("Use !,b,e,j,p,r,s,u,w,y, or / with q ");
  601.         break;
  602.         }
  603.         break;
  604. case 31:            /* 'X': delete character before cursor */
  605.         succ = delnxt(-lexcnt);
  606.         break;
  607. case 32:            /* 'Y': append to save buffer */
  608.         succ = save(lexcnt,TRUE);
  609.         break;
  610. case 33:            /* 'Z': exit (ZZ: normal, ZA: abort) */
  611.         if (!grptch(&fchr))
  612.           {
  613.         succ = FALSE;
  614.         break;
  615.           }
  616.         switch (clower(fchr))
  617.         {
  618.         case 'z':        /* normal exit */
  619.         tvclr();
  620.         remark("Exit");
  621.         goto lquit;
  622.         case 'a':        /* abort or terminate exit */
  623.         abort();
  624.         break;
  625.         case 27:        /* escape is no op */
  626.         break;
  627.         default:
  628.         tverrb("Use Z or A with Z");
  629.         break;
  630.         }
  631.         break;
  632. case 34:            /* '^': beginning of line */
  633.         beglin();
  634.         break;
  635. case 35:            /* 'a': append text */
  636.         right(1);
  637.         succ = insert(lexcnt,lex_def);
  638.         break;
  639. case 36:            /* 'b': word left */
  640.         wordr(-lexcnt);
  641.         break;
  642. case 37:            /* 'c': change something */
  643.         if (!grptch(&fchr))
  644.           {
  645.         succ = FALSE;
  646.         break;
  647.           }
  648.         switch (clower(fchr))
  649.         {
  650.         case 'c':        /* change line */
  651.         killin(lexcnt);    /* remove the line */
  652.         openln(1);
  653.         succ = insert(1,TRUE); /* go into insert mode */
  654.         break;
  655.         case ' ':        /* change one character */
  656.         delnxt(lexcnt);
  657.         succ = insert(1,TRUE); /* go into insert mode */
  658.         break;
  659.         case '^':        /* to beginning of line */
  660.         kprev();
  661.         succ = insert(1,TRUE); /* go into insert mode */
  662.         break;
  663.         case '$':        /* to beginning of line */
  664.         krest();
  665.         succ = insert(1,TRUE); /* go into insert mode */
  666.         break;
  667.         case '/':        /* delete last thing, enter insert */
  668.         if ((succ = rmvlst()))
  669.             succ = insert(1,TRUE);
  670.         break;
  671.         case 27:        /* escape is no op */
  672.         break;
  673.         default:
  674.         tverrb("Use c,<sp>,^,$, or / with c ");
  675.         break;
  676.         }
  677.         break;
  678. case 38:            /* 'd': delete d, <sp>, ^, or $ */
  679.         if (!grptch(&fchr))
  680.           {
  681.         succ = FALSE;
  682.         break;
  683.           }
  684.         switch (clower(fchr))
  685.         {
  686.         case 'd':        /* delete line */
  687.         killin(lexcnt);    /* remove the line */
  688.         break;
  689.         case ' ':        /* delete character */
  690.         delnxt(lexcnt);
  691.         break;
  692.         case '0':
  693.         case '^':        /* to beginning of line */
  694.         kprev();
  695.         break;
  696.         case '$':        /* to beginning of line */
  697.         krest();
  698.         break;
  699.         case '/':        /* delete last thing */
  700.         succ = rmvlst();
  701.         break;
  702.         case 27:        /* escape is no op */
  703.         break;
  704.         default:
  705.         tverrb("Use d,<sp>,^,$, or / with d ");
  706.         break;
  707.         }
  708.         break;
  709. case 39:            /* ^U: half screen up */
  710.         dwnlin( min((-lexcnt*tvlins)/2 , nxtlin-curlin+1) );
  711.         break;
  712. case 40:            /* 'i': insert */
  713.         succ = insert(1,lex_def);
  714.         break;
  715. case 41:            /* 'j': down to line beginning */
  716.         dwnlin(lexcnt);
  717.         break;
  718. case 42:            /* 'k': up to line beginning */
  719.         dwnlin(-lexcnt);
  720.         break;
  721. case 43:            /* 'l': right */
  722.         right(lexcnt);
  723.         break;
  724. case 44:            /* 'm': mark location n */
  725.         if (lexcnt < 1 || lexcnt > 9)
  726.         lexcnt = 0;
  727.         noteloc[lexcnt] = curlin;
  728.         break;
  729. case 45:            /* 'n': find next (in last direction) */
  730.         succ = search((dir_up ? -1 : 1),FALSE);
  731.         break;
  732. case 46:            /* 'o': open following line {do} */
  733.         dwnlin(1);
  734.         openln(lexcnt);
  735.         succ = insert(1,TRUE); /* go into insert mode */
  736.         break;
  737. case 47:            /* 'p': put save buffer after cur line */
  738.         dwnlin(1);
  739.         succ = getsav();
  740.         break;
  741. case 48:            /* 'r': replace next char */
  742.         if (!grptch(&fchr))
  743.           {
  744.         succ = FALSE;
  745.         break;
  746.           }
  747.         delnxt(lexcnt);        /* delete count character */
  748.         succ = insert((int)fchr,FALSE);
  749. #ifndef VI_MODS
  750.         right(-1);            /* and back over char replaced */
  751. #endif
  752.         break;
  753. case 49:                /* 's': substitute */
  754.         if ((succ = delnxt(lexcnt)))
  755.         succ = insert(1,TRUE);
  756.         break;
  757. case 50:                /* ESC: no operation */
  758.         break;
  759. case 51:                /* 'w': advance word */
  760.         wordr(lexcnt);
  761.         break;
  762. case 52:                /* 'x': delete char */
  763.         succ = delnxt(lexcnt);
  764.         break;
  765. case 53:                /* 'y': yank to save buffer */
  766.         succ = save(lexcnt,FALSE);
  767.         break;
  768. case 54:                /* '~': change case */
  769.         foldcase(lexcnt);
  770.         break;
  771.         }              /* end of switch */
  772.         continue;        /* next iteration of do loop */
  773.       } /* end of else */
  774. #ifdef SCR_BUF
  775.     ttflush();
  776. #endif
  777.       } /* end of do loop */
  778.     while (1);
  779.  
  780. lquit:
  781.     for ( wtpage(1) ; rdpage() ; wtpage(1) )    /* write whole file */
  782.     ;
  783.     tvclr();
  784.   }
  785. #endif
  786.  
  787. #ifdef EMAX_EM        /* emacs modeless editor emulation */
  788. /* =============================>>> EDIT   <<<============================= */
  789.   edit()
  790.   { /*    edit - main editing routine */
  791.  
  792.     SLOW int lexval,lexcnt,succ, lastln, itmp;
  793.     SLOW int noteloc[10], ni, lex_def;
  794.     SLOW char lexchr;
  795.  
  796.     static int ins_set[] =    /* MUCH more limited than tvx */
  797.       {
  798.     VQUIT, VTVX, VNOOP, VEXTEND, VOPENLINE, VGET, 0
  799.       };
  800.  
  801.     static int jump_set[] =    /* commands to not reset jump memory */
  802.       {
  803.     VTVX, VHELP, VNOOP, 0
  804.       };
  805.  
  806.     static int c_jump_set[] =    /* jump set for ^C */
  807.       {
  808.     7, 10, 13, 'l', 0
  809.       };
  810.  
  811.     SLOW char fchr;        /* temp char for prefixed commands */
  812.  
  813.     startm();
  814.     remark("Reading file...");
  815.  
  816.     rdpage();            /* read a page into the buffer */
  817.  
  818.     tvclr();            /* clear the screen */
  819.  
  820.     if (curlin >= 1)
  821.     tvtype(curlin,tvlins);    /* type out lines */
  822.  
  823.     tvxy(1,1);            /* and rehome the cursor */
  824.     waserr = FALSE;        /* no errors to erase yet */
  825.  
  826.     if (curlin<1)
  827.     tverr("Buffer empty");
  828. #ifdef SCR_BUF
  829.     ttflush();
  830. #endif
  831.  
  832.     lexval = UNKNOWN;        /* so can remember 1st time through */
  833.     useprint = FALSE;        /* not to printer */
  834.     succ=TRUE;            /* assume success initially */
  835.  
  836.     lastln = 1 ;    /* remember where we were */
  837.     for (ni = 0 ; ni < 10 ; noteloc[ni++] = 1)
  838.     ;            /* init noteloc */
  839.     do
  840.       {
  841.     oldlex = lexval;        /* remember last command */
  842.     if (! succ)
  843.         echof = TRUE;        /* resume echo when error */
  844.     lex_def = lex(&lexval,&lexcnt,&lexchr,succ);    /* get command input */
  845.     if (waserr)
  846.         fixend();
  847.     waserr=FALSE;
  848.     succ=TRUE;
  849.     if (lexval == UNKNOWN)
  850.       {
  851.         cmderr(lexchr);
  852.         succ = FALSE;    /* announce failure to lex */
  853.       }
  854.     else
  855.       {
  856.         if (curlin < 1)    /* make sure legal command for empty buffer */
  857.           {
  858.         if (!inset(lexval,ins_set))
  859.           {
  860.             tverrb("Can't, buffer empty. Insert 1st ");
  861.             succ=FALSE;
  862.             continue;
  863.           }
  864.           }
  865.         if (!inset(lexval,jump_set))
  866.         lastln = curlin;    /* let user look at help w/o changing */
  867.  
  868.         switch (lexval)
  869.         {
  870. case 1:             /* ^A: Cursor to start of line */
  871.         beglin();
  872.         break;
  873. case 2:             /* ^B: left */
  874.         right(-lexcnt);
  875.         break;
  876. case 3:             /* ^C: Command (tvx) */
  877.         if (!grptch(&fchr))
  878.           {
  879.         succ = FALSE;
  880.         break;
  881.           }
  882.         fchr = clower(fchr);    /* lower case */
  883.         if (curlin < 1)    /* make sure legal command for empty buffer */
  884.           {
  885.         if ( fchr != 2 && fchr != 'r')
  886.           {
  887.             tverrb("Can't, buffer empty. Insert 1st ");
  888.             succ=FALSE;
  889.             break;
  890.           }
  891.           }
  892.         if (!inset((int)fchr,c_jump_set))
  893.         lastln = curlin;    /* reset jump loc if not special */
  894.  
  895.         switch (fchr)
  896.         {
  897.         case 1:            /* ^A: append to save buffer */
  898.         lexval = VSAPPEND;
  899.         succ = save(lexcnt,TRUE);
  900.         break;
  901.         case 2:            /* ^B: goto real begin of the file */
  902.         succ = fbeg();
  903.         break;
  904.         case 5:            /* ^E: edit repeat buffer */
  905.         if (lex_def)        /* default 1 passed */
  906.             lexcnt = rptuse + 1;    /* use current repeat loop */
  907.         succ = edit_rpt(lexcnt);    /* edit repeat buffer */
  908.         break;
  909.         case 6:            /* ^F: fill (tidy) */
  910.         succ = neaten(lexcnt);
  911.         break;
  912.         case 7:            /* ^G: no op */
  913.         break;
  914.         case 8:            /* ^H: half screen down */
  915.         dwnlin( min((lexcnt*tvlins)/2 , nxtlin-curlin+1) );
  916.         break;
  917.         case 10:            /* ^J: jump back to last location */
  918.         itmp = curlin;
  919.         curlin = lastln;
  920.         curchr = *(lines+curlin)+1;    /* point to the current char */
  921.         verify(1);
  922.         lastln = itmp;
  923.         break;
  924.         case 11:            /* ^K: kill last thing */
  925.         succ = rmvlst();
  926.         break;
  927.         case 13:            /* ^M: Mark current loc */
  928.         if (lexcnt < 1 || lexcnt > 9)
  929.             lexcnt = 0;
  930.         noteloc[lexcnt] = curlin;
  931.         break;
  932.         case 14:            /* ^N: move to next line */
  933.         dwnlin(lexcnt);
  934.         break;
  935.         case 16:            /* ^P: beginning of prev line */
  936.         dwnlin(-lexcnt);
  937.         break;
  938.         case 18:            /* ^R: restore repeat buffer */
  939.         succ = store_rpt(lexcnt);    /* store repeat buffer */
  940.         break;
  941.         case 23:            /* ^W: write buffer */
  942.         wtpage(lexcnt);    /* write out the current page */
  943.         succ = rdpage();    /* read in the next */
  944.         tvclr();
  945.         if (succ || lexcnt < 0)
  946.             verify(1);
  947.         break;
  948.         case '(':        /* user 1 */
  949.         succ = user_1(lexcnt);    /* user function 1 */
  950.         break;
  951.         case '~':            /* ~: change case */
  952.         foldcase(lexcnt);
  953.         break;
  954.         case '*':            /* * insert found pattern */
  955.         succ = ins_pat(lexcnt);
  956.         break;
  957.         case ';':            /* ;: search again */
  958.         lexval = VSAGAIN;
  959.         succ = search(1,FALSE);
  960.         break;
  961.         case 'g':            /* goto line number n */
  962.         toppag();    /* go to top of file */
  963.         dwnlin(lexcnt - 1);    /* go to that line */
  964.         break;
  965.         case 'h':            /* H: half screen up */
  966.         dwnlin( min((-lexcnt*tvlins)/2 , nxtlin-curlin+1) );
  967.         break;
  968.         case 'i':
  969.         succ = insert(lexcnt,lex_def);
  970.         break;
  971.         case 'l':            /* print screen */
  972.         scrprint();
  973.         break;
  974.         case 'm':            /* m: return to marked loc */
  975.         itmp = curlin;
  976.         if (lexcnt < 1 || lexcnt > 9)
  977.             lexcnt = 0;
  978.         if (noteloc[lexcnt] >= nxtlin)
  979.           {
  980.             tverrb("Line no longer there ");
  981.             noteloc[lexcnt] = curlin;
  982.           }
  983.         else
  984.           {
  985.             curlin = noteloc[lexcnt];
  986.             curchr = *(lines+curlin)+1; /* point to the current char */
  987.             verify(1);
  988.             lastln = itmp;
  989.           }
  990.         break;
  991.         case 'p':            /* p: put line ins save buffer */
  992.         lexval = VSAVE;
  993.         succ = save(lexcnt,FALSE);
  994.         break;
  995.         case 'r':        /* read external file to save buffer */
  996.         succ = addfil(1);
  997.         break;
  998.         case 's':        /* search across buffers */
  999.         lexval = VNEXT;
  1000.         succ = snext(1,TRUE);
  1001.         break;
  1002.         case 'u':            /* "undo" */
  1003.         succ = unkill();
  1004.         break;
  1005.         case 'v':            /* v: set value */
  1006.          if (!grptch(&fchr))
  1007.           {
  1008.             succ = FALSE;
  1009.             break;
  1010.           }
  1011.         setpar(lexcnt,fchr);
  1012.         break;
  1013.         case 'w':        /* write save buffer to file*/
  1014.         succ = addfil(-1);
  1015.         break;
  1016.         default:
  1017.         tverrb("Not valid command for ^C prefix ");
  1018.         break;
  1019.         }
  1020.         break;
  1021. case 4:             /* ^D: Delete next char */
  1022.         succ = delnxt(lexcnt);
  1023.         break;
  1024. case 5:             /* ^E: End of line */
  1025.         endlin();
  1026.         break;
  1027. case 6:             /* ^F: right (forward) */
  1028.         right(lexcnt);
  1029.         break;
  1030. case 7:             /* ^G: noop */
  1031.         break;
  1032. case 8:             /* ^H: delete backwards */
  1033.         succ = delnxt(-lexcnt);
  1034.         break;
  1035. case 9:             /* ^K: kill line */
  1036.         if (lex_def)    /* no n supplied */
  1037.           {
  1038.         if (*(buff+curchr) == ENDLINE)    /* + new line if there */
  1039.             delnxt(1);
  1040.         else
  1041.             krest();    /* delete rest of the line, or newline */
  1042.           }
  1043.         else if (lexcnt == 0)    /* to beginning if 0 */
  1044.         kprev();
  1045.         else
  1046.         killin(lexcnt);
  1047.         break;
  1048. case 10:            /* ^L: verify */
  1049.         verify(1);
  1050.         break;
  1051. case 11:            /* ^N: next line (down in col) */
  1052.         dwncol(lexcnt);
  1053.         break;
  1054. case 12:            /* ^O: open line */
  1055.         openln(lexcnt);
  1056.         break;
  1057. case 13:            /* ^P: previous line (up in col) */
  1058.         dwncol(-lexcnt);
  1059.         break;
  1060. case 14:            /* ^R: reverse search */
  1061.         succ = search(-1,TRUE);
  1062.         break;
  1063. case 15:            /* ^S: normal search */
  1064.         succ = search(1,TRUE);
  1065.         break;
  1066. case 16:            /* ^V: forward pages */
  1067.         dwnlin(min(lexcnt*tvlins,nxtlin-curlin+1));
  1068.         break;
  1069. case 17:            /* ^X: extended command */
  1070.         if (!grptch(&fchr))
  1071.           {
  1072.         succ = FALSE;
  1073.         break;
  1074.           }
  1075.         fchr = clower(fchr);    /* lower case */
  1076.         if (curlin < 1)    /* make sure legal command for empty buffer */
  1077.           {
  1078.         if ( fchr != 3)
  1079.           {
  1080.             tverrb("Can't, buffer empty. Insert 1st ");
  1081.             succ=FALSE;
  1082.             break;
  1083.           }
  1084.           }
  1085.         switch (fchr)
  1086.         {
  1087.         case 2:
  1088.         memory();
  1089.         break;
  1090.         case 3:            /* ^C: abort */
  1091.         abort();
  1092.         break;
  1093.         case 'e':            /* execute repeat loop */
  1094.         if (lexcnt != 1)
  1095.             echof=FALSE;    /* turn off echo */
  1096.         rptcnt[rptuse] = lexcnt > 0 ? lexcnt : (-lexcnt);
  1097.         break;
  1098.         default:
  1099.         tverrb("Not valid command for ^X prefix ");
  1100.         break;
  1101.         }
  1102.     
  1103.         break;
  1104. case 18:            /* ^Y: Yank back save buffer */
  1105.         succ = getsav();
  1106.         break;
  1107. case 19:            /* ^Z: save and exit */
  1108.         tvclr();
  1109.         remark("Save and exit");
  1110.         goto lquit;
  1111. case 20:            /* !: call os */
  1112.         opsystem();        /* call operating system */
  1113.         break;
  1114.  
  1115. /*    these have been prefixed by escape */
  1116. case 21:            /* #: execute repeat loop again */
  1117.         succ = exec_rpt(lexcnt);    /* execute repeat buffer */
  1118.         break;
  1119. case 22:            /* >: end of buffer */
  1120.         botpag();
  1121.         break;
  1122. case 23:            /* <: top of buffer */
  1123.         toppag();
  1124.         break;
  1125. case 24:            /* b: backward words */
  1126.         wordr(-lexcnt);
  1127.         break;
  1128. case 25:            /* f: forward words */
  1129.         wordr(lexcnt);
  1130.         break;
  1131. case 26:            /* v: backward pages */
  1132.         dwnlin(min(-lexcnt*tvlins,nxtlin-curlin+1));
  1133.         break;
  1134. case 27:            /* ?: help */
  1135.         shoset();
  1136.         break;
  1137.         }              /* end of switch */
  1138.         continue;        /* next iteration of do loop */
  1139.       } /* end of else */
  1140. #ifdef SCR_BUF
  1141.     ttflush();
  1142. #endif
  1143.       } /* end of do loop */
  1144.     while (1);
  1145.  
  1146. lquit:
  1147.     for ( wtpage(1) ; rdpage() ; wtpage(1) )    /* write whole file */
  1148.     ;
  1149.     tvclr();
  1150.   }
  1151. #endif
  1152.  
  1153. /* =============================>>> DWNCOL <<<============================= */
  1154.   dwncol(cnt)
  1155.   int cnt;
  1156.   { /* dwncol - move down in column */
  1157.  
  1158.     SLOW int curcol,l,oldef,needns;
  1159.  
  1160.     needns = FALSE;
  1161.     if (leftmg > 1)        /* handle right virtual screen different */
  1162.       {
  1163.     oldef=echof;
  1164.     needns = TRUE;
  1165.     echof = FALSE;
  1166.       }
  1167.  
  1168.     if (oldlex==VDOWNCOL || oldlex==VUPCOL)    /* several in a row? */
  1169.     curcol=oldcol;        /* pick up old value */
  1170.     else
  1171.       {
  1172.     curcol = curchr - *(lines+curlin);    /* calculate the current column */
  1173.     oldcol = curcol;
  1174.       }
  1175.     dwnlin(cnt);        /* go down given lines */
  1176.     if (curlin>=1 && curlin<nxtlin && curcol>1)    /* not at ends? */
  1177.       {
  1178.     l = strlen(buff + ((*(lines+curlin)) + 1) );
  1179.     right(min(curcol-1,l));
  1180.       }
  1181.  
  1182.     if (needns)            /* needed new screen */
  1183.       {
  1184.     echof=oldef;
  1185.     newscr();
  1186.       }
  1187.   }
  1188.  
  1189. /* =============================>>> RMVLST <<<============================= */
  1190.   int rmvlst()
  1191.   {  /* rmvlst - delete the previous thing found or manipulated
  1192.     length of oldlen is set by insert, find, and save
  1193.     may also use savlen if set by save */
  1194.  
  1195.     SLOW int oldech;
  1196. #ifdef TVX_CMDSET
  1197.     static int rmv_set[] =
  1198.       {
  1199.     VSEARCH, VNEXT, VSAVE, VGET, VSAGAIN, VSAPPEND,
  1200.     VMVWORD, VMVBWORD, 0
  1201.       };
  1202. #endif
  1203. #ifdef VI_EM
  1204.     static int rmv_set[] =
  1205.       {
  1206.     VSEARCH, VSAVE, VGET, VSAGAIN, VSAPPEND, VPUT,
  1207.     VMVWORD, VMVBWORD, VRSEARCH, VRSAGAIN, 0
  1208.       };
  1209. #endif
  1210. #ifdef EMAX_EM
  1211.     static int rmv_set[] =
  1212.       {
  1213.     VSEARCH, VNEXT, VSAVE, VGET, VSAGAIN, VSAPPEND,
  1214.     VMVWORD, VMVBWORD, VRSEARCH, 0
  1215.       };
  1216. #endif
  1217.  
  1218.     if (!inset(oldlex,rmv_set))
  1219.     return (FALSE);
  1220.  
  1221.     if (savlen > 0)
  1222.       {
  1223.     if (curlin == nxtlin-1 && slastl != 0)
  1224.       {
  1225.         --savlen;    /* reduce the count */
  1226.         if (savlen > 0)
  1227.           {
  1228.         oldech = echof;
  1229.         echof = FALSE;
  1230.         killin(-savlen);    /* kill off previous lines */
  1231.         echof = oldech;
  1232.           }
  1233.         killin(1);        /* kill the last line */
  1234.       }
  1235.     else
  1236.         killin(-savlen);    /* kill off savlen lines */
  1237.       }
  1238.     else if (oldlen != 0)
  1239.       {
  1240.     if (! delnxt(-oldlen))
  1241.         return (FALSE);
  1242.       }
  1243.     oldlen = 0;            /* don't allow multiple deletes! */
  1244.     savlen = (-1);
  1245.     return (TRUE);
  1246.   }
  1247.  
  1248. /* =============================>>> SAVE   <<<============================= */
  1249.   int save(cnt,app)
  1250.   int cnt,app;
  1251.   { /* save - save cnt lines in save buffer */
  1252.  
  1253.     SLOW int l,lend;
  1254.     SLOW BUFFINDEX from;
  1255.  
  1256.     if (curlin == nxtlin-1 && slastl!=0)
  1257.       {
  1258.     tverrb("Can't save last line twice! ");
  1259.     return (FALSE);
  1260.       }
  1261.     if (cnt < 0)
  1262.     return (FALSE);
  1263.  
  1264.     oldlen = 0;            /* use savlin instead */
  1265.  
  1266.     if ((oldlex != VSAVE && !app) || cnt == 0)
  1267.       {             /* if new save, cnt == 0 and not appending */
  1268.     slastl=0;
  1269.     savlin=0;        /* haven't saved anything */
  1270.     savlen=0;
  1271.     nxtsav=mxbuff;    /* start saving at end */
  1272.     if (cnt == 0)
  1273.       {
  1274.         return (TRUE);
  1275.       }
  1276.       }
  1277.  
  1278.     if (oldlex != VSAPPEND && app)    /* need to reset count for append */
  1279.     savlen=0;
  1280.  
  1281.     lend=min(curlin+cnt-1 ,nxtlin-1);
  1282.     for (l=curlin; l <= lend ; ++l)
  1283.       {
  1284.     if (nxtsav-nxtchr < ALMOSTOUT)    /* make space if need and can */
  1285.         if (!gbgcol() || (nxtsav-nxtchr) < ALMOSTOUT)
  1286.           {
  1287.         tverrb("No save room ");
  1288.         return (FALSE);
  1289.           }
  1290.  
  1291.     from = *(lines+l)+1;        /* first character of the line */
  1292.     do
  1293.       {
  1294.         *(buff+nxtsav--) = *(buff+from++);
  1295.       }
  1296.     while (*(buff+from-1)!=ENDLINE);
  1297.     ++savlin;        /* keep track of the length */
  1298.     ++savlen;        /* savlen for rmvlst */
  1299.     if (curlin==nxtlin-1)    /* don't save last line twice! */
  1300.       {
  1301.         slastl=1;
  1302.         break;
  1303.       }
  1304.     dwnlin(1);    /* move to next line on screen for + only */
  1305.       }
  1306. #ifdef SCR_BUF
  1307.     ttflush();
  1308. #endif
  1309.     return (TRUE);
  1310.   }
  1311.