home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / stevi0s2 / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-09  |  6.7 KB  |  342 lines

  1. /*
  2.  * STevie - ST editor for VI enthusiasts.     ...Tim Thompson...twitch!tjt...
  3.  *
  4.  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  5.  *
  6.  */
  7.  
  8. #include "stevie.h"
  9.  
  10. /*
  11.  * This flag is used to make auto-indent work right on lines where only
  12.  * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  13.  * and reset when any other editting is done on the line. If an <ESC>
  14.  * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
  15.  */
  16. bool_t    did_ai = FALSE;
  17.  
  18. void
  19. edit()
  20. {
  21.     int c;
  22.     char *p, *q;
  23.  
  24.     Prenum = 0;
  25.  
  26.     /* position the display and the cursor at the top of the file. */
  27.     *Topchar = *Filemem;
  28.     *Curschar = *Filemem;
  29.     Cursrow = Curscol = 0;
  30.  
  31.     for ( ;; ) {
  32.  
  33.     /* Figure out where the cursor is based on Curschar. */
  34.     cursupdate();
  35.  
  36.     windgoto(Cursrow,Curscol);
  37.  
  38.     c = vgetc();
  39.  
  40.     if (State == NORMAL) {
  41.  
  42.         /* We're in the normal (non-insert) mode. */
  43.  
  44.         /* Pick up any leading digits and compute 'Prenum' */
  45.         if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
  46.             Prenum = Prenum*10 + (c-'0');
  47.             continue;
  48.         }
  49.         /* execute the command */
  50.         normal(c);
  51.         Prenum = 0;
  52.  
  53.     } else {
  54.  
  55.         switch (c) {    /* We're in insert mode */
  56.  
  57.         case ESC:    /* an escape ends input mode */
  58.  
  59.             set_want_col = TRUE;
  60.  
  61.             /* Don't end up on a '\n' if you can help it. */
  62.             if (gchar(Curschar) == NUL && Curschar->index != 0)
  63.                 dec(Curschar);
  64.  
  65.             /*
  66.              * The cursor should end up on the last inserted
  67.              * character. This is an attempt to match the real
  68.              * 'vi', but it may not be quite right yet.
  69.              */
  70.             if (Curschar->index != 0 && !endofline(Curschar))
  71.                 dec(Curschar);
  72.  
  73.             State = NORMAL;
  74.             msg("");
  75.             *Uncurschar = *Insstart;
  76.             Undelchars = Ninsert;
  77.             /* Undobuff[0] = '\0'; */
  78.             /* construct the Redo buffer */
  79.             p=Redobuff;
  80.             q=Insbuff;
  81.             while ( q < Insptr )
  82.                 *p++ = *q++;
  83.             *p++ = ESC;
  84.             *p = NUL;
  85.             updatescreen();
  86.             break;
  87.  
  88.         case CTRL('D'):
  89.             /*
  90.              * Control-D is treated as a backspace in insert
  91.              * mode to make auto-indent easier. This isn't
  92.              * completely compatible with vi, but it's a lot
  93.              * easier than doing it exactly right, and the
  94.              * difference isn't very noticeable.
  95.              */
  96.         case BS:
  97.             /* can't backup past starting point */
  98.             if (Curschar->linep == Insstart->linep &&
  99.                 Curschar->index <= Insstart->index) {
  100.                 beep();
  101.                 break;
  102.             }
  103.  
  104.             /* can't backup to a previous line */
  105.             if (Curschar->linep != Insstart->linep &&
  106.                 Curschar->index <= 0) {
  107.                 beep();
  108.                 break;
  109.             }
  110.  
  111.             did_ai = FALSE;
  112.             dec(Curschar);
  113.             delchar(TRUE);
  114.             Insptr--;
  115.             Ninsert--;
  116.             cursupdate();
  117.             updateline();
  118.             break;
  119.  
  120.         case CR:
  121.         case NL:
  122.             *Insptr++ = NL;
  123.             Ninsert++;
  124.             opencmd(FORWARD, TRUE);        /* open a new line */
  125.             cursupdate();
  126.             updatescreen();
  127.             break;
  128.  
  129.         default:
  130.             did_ai = FALSE;
  131.             insertchar(c);
  132.             break;
  133.         }
  134.     }
  135.     }
  136. }
  137.  
  138. /*
  139.  * Special characters in this context are those that need processing other
  140.  * than the simple insertion that can be performed here. This includes ESC
  141.  * which terminates the insert, and CR/NL which need special processing to
  142.  * open up a new line. This routine tries to optimize insertions performed
  143.  * by the "redo" command, so it needs to know when it should stop and defer
  144.  * processing to the "normal" mechanism.
  145.  */
  146. #define    ISSPECIAL(c)    ((c) == NL || (c) == CR || (c) == ESC)
  147.  
  148. void
  149. insertchar(c)
  150. int c;
  151. {
  152.     char *p;
  153.  
  154.     if ( ! anyinput() ) {
  155.         inschar(c);
  156.         *Insptr++ = c;
  157.         Ninsert++;
  158.         /*
  159.          * The following kludge avoids overflowing the statically
  160.          * allocated insert buffer. Just dump the user back into
  161.          * command mode, and print a message.
  162.          */
  163.         if (Insptr+10 >= &Insbuff[1024]) {
  164.             stuffin(mkstr(ESC));
  165.             emsg("No buffer space - returning to command mode");
  166.             sleep(2);
  167.         }
  168.     }
  169.     else {
  170.         /* If there's any pending input, grab it all at once. */
  171.         p = Insptr;
  172.         *Insptr++ = c;
  173.         Ninsert++;
  174.         for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
  175.             c = vgetc();
  176.             *Insptr++ = c;
  177.             Ninsert++;
  178.         }
  179.         *Insptr = '\0';
  180.         insstr(p);
  181.     }
  182.     updateline();
  183. }
  184.  
  185. void
  186. getout()
  187. {
  188.     windgoto(Rows-1,0);
  189.     putchar('\r');
  190.     putchar('\n');
  191.     windexit(0);
  192. }
  193.  
  194. void
  195. scrolldown(nlines)
  196. int nlines;
  197. {
  198.     register LPTR    *p;
  199.     register int    done = 0;    /* total # of physical lines done */
  200.  
  201.     /* Scroll up 'nlines' lines. */
  202.     while (nlines--) {
  203.         if ((p = prevline(Topchar)) == NULL)
  204.             break;
  205.         done += plines(p);
  206.         *Topchar = *p;
  207.         if (Curschar->linep == Botchar->linep->prev)
  208.             *Curschar = *prevline(Curschar);
  209.     }
  210.     s_ins(0, done);
  211. }
  212.  
  213. void
  214. scrollup(nlines)
  215. int nlines;
  216. {
  217.     register LPTR    *p;
  218.     register int    done = 0;    /* total # of physical lines done */
  219.     register int    pl;        /* # of plines for the current line */
  220.  
  221.     /* Scroll down 'nlines' lines. */
  222.     while (nlines--) {
  223.         pl = plines(Topchar);
  224.         if ((p = nextline(Topchar)) == NULL)
  225.             break;
  226.         done += pl;
  227.         if (Curschar->linep == Topchar->linep)
  228.             *Curschar = *p;
  229.         *Topchar = *p;
  230.  
  231.     }
  232.     s_del(0, done);
  233. }
  234.  
  235. /*
  236.  * oneright
  237.  * oneleft
  238.  * onedown
  239.  * oneup
  240.  *
  241.  * Move one char {right,left,down,up}.  Return TRUE when
  242.  * sucessful, FALSE when we hit a boundary (of a line, or the file).
  243.  */
  244.  
  245. bool_t
  246. oneright()
  247. {
  248.     set_want_col = TRUE;
  249.  
  250.     switch (inc(Curschar)) {
  251.  
  252.     case 0:
  253.         return TRUE;
  254.  
  255.     case 1:
  256.         dec(Curschar);        /* crossed a line, so back up */
  257.         /* fall through */
  258.     case -1:
  259.         return FALSE;
  260.     }
  261. }
  262.  
  263. bool_t
  264. oneleft()
  265. {
  266.     set_want_col = TRUE;
  267.  
  268.     switch (dec(Curschar)) {
  269.  
  270.     case 0:
  271.         return TRUE;
  272.  
  273.     case 1:
  274.         inc(Curschar);        /* crossed a line, so back up */
  275.         /* fall through */
  276.     case -1:
  277.         return FALSE;
  278.     }
  279. }
  280.  
  281. void
  282. beginline(flag)
  283. bool_t    flag;
  284. {
  285.     while ( oneleft() )
  286.         ;
  287.     if (flag) {
  288.         while (isspace(gchar(Curschar)) && oneright())
  289.             ;
  290.     }
  291.     set_want_col = TRUE;
  292. }
  293.  
  294. bool_t
  295. oneup(n)
  296. {
  297.     LPTR p, *np;
  298.     int k;
  299.  
  300.     p = *Curschar;
  301.     for ( k=0; k<n; k++ ) {
  302.         /* Look for the previous line */
  303.         if ( (np=prevline(&p)) == NULL ) {
  304.             /* If we've at least backed up a little .. */
  305.             if ( k > 0 )
  306.                 break;    /* to update the cursor, etc. */
  307.             else
  308.                 return FALSE;
  309.         }
  310.         p = *np;
  311.     }
  312.     *Curschar = p;
  313.     /* This makes sure Topchar gets updated so the complete line */
  314.     /* is one the screen. */
  315.     cursupdate();
  316.     /* try to advance to the column we want to be at */
  317.     *Curschar = *coladvance(&p, Curswant);
  318.     return TRUE;
  319. }
  320.  
  321. bool_t
  322. onedown(n)
  323. {
  324.     LPTR p, *np;
  325.     int k;
  326.  
  327.     p = *Curschar;
  328.     for ( k=0; k<n; k++ ) {
  329.         /* Look for the next line */
  330.         if ( (np=nextline(&p)) == NULL ) {
  331.             if ( k > 0 )
  332.                 break;
  333.             else
  334.                 return FALSE;
  335.         }
  336.         p = *np;
  337.     }
  338.     /* try to advance to the column we want to be at */
  339.     *Curschar = *coladvance(&p, Curswant);
  340.     return TRUE;
  341. }
  342.