home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d166 / stevie.lha / Stevie / source / edit.c < prev    next >
C/C++ Source or Header  |  1988-11-22  |  9KB  |  428 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!watcgl!grwalter 
  7.  */
  8.  
  9. #include "stevie.h"
  10.  
  11. /*
  12.  * This flag is used to make auto-indent work right on lines where only a
  13.  * <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
  14.  * reset when any other editting is done on the line. If an <ESC> or <RETURN>
  15.  * is received, and did_ai is TRUE, the line is truncated. 
  16.  */
  17. bool_t          did_ai = FALSE;
  18.  
  19. void
  20. edit()
  21. {
  22.     char            c;
  23.     bool_t          literal_next_flag = FALSE;
  24.  
  25.     Prenum = 0;
  26.  
  27.     /* position the display and the cursor at the top of the file. */
  28.     *Topchar = *Filemem;
  29.     *Curschar = *Filemem;
  30.     Cursrow = Curscol = 0;
  31.  
  32.     for (;;) {
  33.  
  34.     if (!RedrawingDisabled) {
  35.         cursupdate();    /* Figure out where the cursor is based on
  36.                  * Curschar. */
  37.         if (MustRedrawLine)
  38.         redrawline();
  39.         if (MustRedrawScreen)
  40.         updateRealscreen();
  41.  
  42.         windgoto(Cursrow, Curscol);
  43.     }
  44.     c = vgetc();
  45.  
  46.     if (State == NORMAL) {
  47.         /* We're in the normal (non-insert) mode. */
  48.  
  49.         /* Pick up any leading digits and compute 'Prenum' */
  50.         if ((Prenum > 0 && isdigit(c)) || (isdigit(c) && c != '0')) {
  51.         Prenum = Prenum * 10 + (c - '0');
  52.         continue;
  53.         }
  54.         /* execute the command */
  55.         normal(c);
  56.         Prenum = 0;
  57.  
  58.     } else {
  59.         if (c == CTRL('V') && !literal_next_flag) {
  60.         literal_next_flag = TRUE;
  61.         outchar('^');
  62.         continue;
  63.         }
  64.         if (literal_next_flag) {
  65.         literal_next_flag = FALSE;
  66.         outchar('\b');
  67.         if (c != NL) {
  68.             did_ai = FALSE;
  69.             insertchar(c);
  70.             continue;
  71.         }
  72.         }
  73.         switch (c) {    /* We're in insert mode */
  74.  
  75.           case CR:
  76.           case NL:
  77.         *Insbuffptr++ = NL;
  78.         *Insbuffptr = NUL;
  79.         if (!opencmd(FORWARD, TRUE))
  80.             goto doESCkey;    /* out of memory */
  81.  
  82.         if (!RedrawingDisabled)
  83.             windgoto(Cursrow, Curscol);
  84.         break;
  85.  
  86.           case ESC:    /* an escape ends input mode */
  87.     doESCkey:
  88.         set_want_col = TRUE;
  89.  
  90.         /* Don't end up on a '\n' if you can help it. */
  91.         if (gchar(Curschar) == NUL && Curschar->index != 0)
  92.             dec(Curschar);
  93.  
  94.         /*
  95.          * The cursor should end up on the last inserted character.
  96.          * This is an attempt to match the real 'vi', but it may not
  97.          * be quite right yet. 
  98.          */
  99.         if (Curschar->index != 0 && !endofline(Curschar))
  100.             dec(Curschar);
  101.  
  102.         State = NORMAL;
  103.         msg("");
  104.  
  105.         if (!UndoInProgress) {
  106.             int             n;
  107.             char           *p;
  108.  
  109.             if (last_command == 'o')
  110.             AppendToUndobuff(UNDO_SHIFTJ_STR);
  111.  
  112.             if (Insbuff != Insbuffptr) {
  113.             if (last_command == 'O')
  114.                 AppendToUndobuff("0");
  115.             AppendToRedobuff(Insbuff);
  116.             AppendToUndoUndobuff(Insbuff);
  117.             n = 0;
  118.             for (p = Insbuff; p < Insbuffptr; p++) {
  119.                 if (*p == NL) {
  120.                 if (n) {
  121.                     AppendNumberToUndobuff(n);
  122.                     AppendToUndobuff("dl");
  123.                     n = 0;
  124.                 }
  125.                 AppendToUndobuff(UNDO_SHIFTJ_STR);
  126.                 } else
  127.                 n++;
  128.             }
  129.             if (n) {
  130.                 AppendNumberToUndobuff(n);
  131.                 AppendToUndobuff("dl");
  132.             }
  133.             }
  134.             if (last_command == 'c') {
  135.             AppendToUndobuff(mkstr(last_command_char));
  136.             AppendToUndobuff(Yankbuff);
  137.             AppendToUndobuff(ESC_STR);
  138.             }
  139.             AppendToRedobuff(ESC_STR);
  140.             AppendToUndoUndobuff(ESC_STR);
  141.             if (last_command == 'O')
  142.             AppendToUndobuff(UNDO_SHIFTJ_STR);
  143.         }
  144.         break;
  145.  
  146.           case CTRL('D'):
  147.         /*
  148.          * Control-D is treated as a backspace in insert mode to make
  149.          * auto-indent easier. This isn't completely compatible with
  150.          * vi, but it's a lot easier than doing it exactly right, and
  151.          * the difference isn't very noticeable. 
  152.          */
  153.           case BS:
  154.         /* can't backup past starting point */
  155.         if (Curschar->linep == Insstart->linep &&
  156.             Curschar->index <= Insstart->index) {
  157.             beep();
  158.             break;
  159.         }
  160.         /* can't backup to a previous line */
  161.         if (Curschar->linep != Insstart->linep &&
  162.             Curschar->index <= 0) {
  163.             beep();
  164.             break;
  165.         }
  166.         did_ai = FALSE;
  167.         dec(Curschar);
  168.         delchar(TRUE, FALSE);
  169.         Insbuffptr--;
  170.         *Insbuffptr = NUL;
  171.         cursupdate();
  172.         updateline();
  173.         break;
  174.  
  175.           default:
  176.         did_ai = FALSE;
  177.         insertchar(c);
  178.         break;
  179.         }
  180.     }
  181.     }
  182. }
  183.  
  184. /*
  185.  * Special characters in this context are those that need processing other
  186.  * than the simple insertion that can be performed here. This includes ESC
  187.  * which terminates the insert, and CR/NL which need special processing to
  188.  * open up a new line. This routine tries to optimize insertions performed by
  189.  * the "redo" command, so it needs to know when it should stop and defer
  190.  * processing to the "normal" mechanism. 
  191.  */
  192. #define    ISSPECIAL(c)    ((c) == NL || (c) == CR || (c) == ESC)
  193.  
  194. void
  195. insertchar(c)
  196.     char            c;
  197. {
  198.     if (anyinput()) {        /* If there's any pending input, grab it all
  199.                  * at once. */
  200.     char           *p;
  201.  
  202.     p = Insbuffptr;
  203.     *Insbuffptr++ = c;
  204.     for (c = vpeekc(); !ISSPECIAL(c) && anyinput(); c = vpeekc()) {
  205.         c = vgetc();
  206.         *Insbuffptr++ = c;
  207.         /*
  208.          * The following kludge avoids overflowing the insert buffer. 
  209.          */
  210.         if (Insbuffptr + 10 >= &Insbuff[INSERT_SIZE]) {
  211.         int             n;
  212.  
  213.         *Insbuffptr = NUL;
  214.         insstr(p);
  215.  
  216.         Insbuffptr = Insbuff;
  217.         p = Insbuffptr;
  218.  
  219.         emsg("Insert buffer overflow - buffers flushed");
  220.         sleep(2);
  221.  
  222.         n = cntllines(Filemem, Curschar);
  223.         AppendPositionToUndobuff(Curschar->index, n);
  224.         AppendPositionToUndoUndobuff(Curschar->index, n);
  225.         if (endofline(Curschar)) {
  226.             AppendToRedobuff("a");
  227.             AppendToUndoUndobuff("a");
  228.         } else {
  229.             AppendToRedobuff("i");
  230.             AppendToUndoUndobuff("i");
  231.         }
  232.         }
  233.     }
  234.     *Insbuffptr = NUL;
  235.     insstr(p);
  236.     } else {
  237.     inschar(c);
  238.     *Insbuffptr++ = c;
  239.  
  240.     /*
  241.      * The following kludge avoids overflowing the insert buffer. 
  242.      */
  243.     if (Insbuffptr + 10 >= &Insbuff[INSERT_SIZE]) {
  244.         int             n;
  245.  
  246.         Insbuffptr = Insbuff;
  247.  
  248.         emsg("Insert buffer overflow - buffers flushed");
  249.         sleep(2);
  250.  
  251.         n = cntllines(Filemem, Curschar);
  252.         AppendPositionToUndobuff(Curschar->index, n);
  253.         AppendPositionToUndoUndobuff(Curschar->index, n);
  254.         if (endofline(Curschar)) {
  255.         AppendToRedobuff("a");
  256.         AppendToUndoUndobuff("a");
  257.         } else {
  258.         AppendToRedobuff("i");
  259.         AppendToUndoUndobuff("i");
  260.         }
  261.     }
  262.     *Insbuffptr = NUL;
  263.     }
  264.  
  265.     updateline();
  266. }
  267.  
  268. void
  269. getout(r)
  270.     int             r;
  271. {
  272.     windgoto(Rows - 1, 0);
  273.     putchar('\r');
  274.     putchar('\n');
  275.     windexit(r);
  276. }
  277.  
  278. void
  279. scrolldown(nlines)
  280.     int             nlines;
  281. {
  282.     LPTR           *p;
  283.     int             done = 0;    /* total # of physical lines done */
  284.  
  285.     /* Scroll up 'nlines' lines. */
  286.     while (nlines--) {
  287.     if ((p = prevline(Topchar)) == NULL)
  288.         break;
  289.     done += plines(p);
  290.     *Topchar = *p;
  291.     if (Curschar->linep == Botchar->linep->prev)
  292.         *Curschar = *prevline(Curschar);
  293.     }
  294.     s_ins(0, done);
  295. }
  296.  
  297. void
  298. scrollup(nlines)
  299.     int             nlines;
  300. {
  301.     LPTR           *p;
  302.     int             done = 0;    /* total # of physical lines done */
  303.     int             pl;        /* # of plines for the current line */
  304.  
  305.     /* Scroll down 'nlines' lines. */
  306.     while (nlines--) {
  307.     pl = plines(Topchar);
  308.     if ((p = nextline(Topchar)) == NULL)
  309.         break;
  310.     done += pl;
  311.     if (Curschar->linep == Topchar->linep)
  312.         *Curschar = *p;
  313.     *Topchar = *p;
  314.  
  315.     }
  316.     s_del(0, done);
  317. }
  318.  
  319. /*
  320.  * oneright oneleft onedown oneup 
  321.  *
  322.  * Move one char {right,left,down,up}.  Return TRUE when sucessful, FALSE when
  323.  * we hit a boundary (of a line, or the file). 
  324.  */
  325.  
  326. bool_t
  327. oneright()
  328. {
  329.     set_want_col = TRUE;
  330.  
  331.     switch (inc(Curschar)) {
  332.  
  333.       case 0:
  334.     return TRUE;
  335.  
  336.       case 1:
  337.     dec(Curschar);        /* crossed a line, so back up */
  338.     /* FALLTHROUGH */
  339.       case -1:
  340.     return FALSE;
  341.     }
  342.  
  343.     return FALSE;        /* PARANOIA: should never reach here */
  344. }
  345.  
  346. bool_t
  347. oneleft()
  348. {
  349.     set_want_col = TRUE;
  350.  
  351.     switch (dec(Curschar)) {
  352.  
  353.       case 0:
  354.     return TRUE;
  355.  
  356.       case 1:
  357.     inc(Curschar);        /* crossed a line, so back up */
  358.     /* FALLTHROUGH */
  359.       case -1:
  360.     return FALSE;
  361.     }
  362.  
  363.     return FALSE;        /* PARANOIA: should never reach here */
  364. }
  365.  
  366. void
  367. beginline(flag)
  368.     bool_t          flag;
  369. {
  370.     while (oneleft());
  371.     if (flag) {
  372.     while (isspace(gchar(Curschar)) && oneright());
  373.     }
  374.     set_want_col = TRUE;
  375. }
  376.  
  377. bool_t
  378. oneup(n)
  379. {
  380.     LPTR            p, *np;
  381.     int             k;
  382.  
  383.     p = *Curschar;
  384.     for (k = 0; k < n; k++) {
  385.     /* Look for the previous line */
  386.     if ((np = prevline(&p)) == NULL) {
  387.         /* If we've at least backed up a little .. */
  388.         if (k > 0)
  389.         break;        /* to update the cursor, etc. */
  390.         else
  391.         return FALSE;
  392.     }
  393.     p = *np;
  394.     }
  395.     *Curschar = p;
  396.  
  397.     cursupdate();        /* make sure Topchar is valid */
  398.  
  399.     /* try to advance to the column we want to be at */
  400.     *Curschar = *coladvance(&p, Curswant);
  401.     return TRUE;
  402. }
  403.  
  404. bool_t
  405. onedown(n)
  406. {
  407.     LPTR            p, *np;
  408.     int             k;
  409.  
  410.     p = *Curschar;
  411.     for (k = 0; k < n; k++) {
  412.     /* Look for the next line */
  413.     if ((np = nextline(&p)) == NULL) {
  414.         if (k > 0)
  415.         break;
  416.         else
  417.         return FALSE;
  418.     }
  419.     p = *np;
  420.     }
  421.  
  422.     cursupdate();        /* make sure Topchar is valid */
  423.  
  424.     /* try to advance to the column we want to be at */
  425.     *Curschar = *coladvance(&p, Curswant);
  426.     return TRUE;
  427. }
  428.