home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / util / edit / vim / src / normal.c < prev    next >
C/C++ Source or Header  |  1994-08-13  |  41KB  |  1,935 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * Contains the main routine for processing characters in command mode.
  11.  * Communicates closely with the code in ops.c to handle the operators.
  12.  */
  13.  
  14. #include "vim.h"
  15. #include "globals.h"
  16. #include "proto.h"
  17. #include "param.h"
  18.  
  19. #undef EXTERN
  20. #undef INIT
  21. #define EXTERN
  22. #define INIT(x) x
  23. #include "ops.h"
  24.  
  25. /*
  26.  * Generally speaking, every command in normal() should either clear any
  27.  * pending operator (with CLEAROP), or set the motion type variable.
  28.  */
  29.  
  30. #define CLEAROP (operator = NOP)        /* clear any pending operator */
  31. #define CLEAROPBEEP     clearopbeep()    /* CLEAROP plus a beep() */
  32. #define CHECKCLEAROP    if (checkclearop()) break;
  33. #define CHECKCLEAROPQ    if (checkclearopq()) break;
  34.  
  35. /*
  36.  * If a count is given before the operator, it is saved in opnum.
  37.  */
  38. static linenr_t    opnum = 0;
  39. static linenr_t    Prenum;         /* The (optional) number before a command. */
  40. int                redo_Visual_busy = FALSE;    /* TRUE when redo-ing a visual */
  41.  
  42. static void        prep_redo __ARGS((long, int, int, int));
  43. static int        checkclearop __ARGS((void));
  44. static int        checkclearopq __ARGS((void));
  45. static void        clearopbeep __ARGS((void));
  46. static void        premsg __ARGS((int, int));
  47.  
  48. extern int        restart_edit;    /* this is in edit.c */
  49.  
  50. /*
  51.  * normal
  52.  *
  53.  * Execute a command in normal mode.
  54.  *
  55.  * This is basically a big switch with the cases arranged in rough categories
  56.  * in the following order:
  57.  *
  58.  *      0. Macros (q, @)
  59.  *      1. Screen positioning commands (^U, ^D, ^F, ^B, ^E, ^Y, z)
  60.  *      2. Control commands (:, <help>, ^L, ^G, ^^, ZZ, *, ^], ^T)
  61.  *      3. Cursor motions (G, H, M, L, l, K_RARROW,  , h, K_LARROW, ^H, k, K_UARROW, ^P, +, CR, LF, j, K_DARROW, ^N, _, |, B, b, W, w, E, e, $, ^, 0)
  62.  *      4. Searches (?, /, n, N, T, t, F, f, ,, ;, ], [, %, (, ), {, })
  63.  *      5. Edits (., u, K_UNDO, ^R, U, r, J, p, P, ^A, ^S)
  64.  *      6. Inserts (A, a, I, i, o, O, R)
  65.  *      7. Operators (~, d, c, y, >, <, !, =, Q)
  66.  *      8. Abbreviations (x, X, D, C, s, S, Y, &)
  67.  *      9. Marks (m, ', `, ^O, ^I)
  68.  *     10. Buffer setting (")
  69.  *     11. Visual (v, V, ^V)
  70.  *   12. Suspend (^Z)
  71.  *   13. Window commands (^W)
  72.  *   14. extended commands (starting with 'g')
  73.  */
  74.  
  75.     void
  76. normal()
  77. {
  78.     register int    c;
  79.     long             n;
  80.     int                flag = FALSE;
  81.     int                flag2 = FALSE;
  82.     int             type = 0;                /* type of operation */
  83.     int             dir = FORWARD;            /* search direction */
  84.     int                nchar = NUL;
  85.     int                finish_op;
  86.     linenr_t        Prenum1;
  87.     char_u            searchbuff[CMDBUFFSIZE];/* buffer for search string */
  88.     FPOS            *pos = NULL;            /* init for gcc */
  89.     register char_u    *ptr;
  90.     int                command_busy = FALSE;
  91.     static int        didwarn = FALSE;        /* warned for broken inversion */
  92.     int                modified = FALSE;        /* changed current buffer */
  93.     int                ctrl_w = FALSE;            /* got CTRL-W command */
  94.  
  95.         /* the visual area is remembered for reselection */
  96.     static linenr_t    resel_Visual_nlines;        /* number of lines */
  97.     static int        resel_Visual_type = 0;    /* type 'v', 'V' or CTRL-V */
  98.     static colnr_t    resel_Visual_col;        /* number of columns or end column */
  99.         /* the visual area is remembered for redo */
  100.     static linenr_t    redo_Visual_nlines;        /* number of lines */
  101.     static int        redo_Visual_type = 0;    /* type 'v', 'V' or CTRL-V */
  102.     static colnr_t    redo_Visual_col;        /* number of columns or end column */
  103.     static long        redo_Visual_Prenum;        /* Prenum for operator */
  104.  
  105.     Prenum = 0;
  106.     /*
  107.      * If there is an operator pending, then the command we take this time
  108.      * will terminate it. Finish_op tells us to finish the operation before
  109.      * returning this time (unless the operation was cancelled).
  110.      */
  111.     finish_op = (operator != NOP);
  112.  
  113.     if (!finish_op && !yankbuffer)
  114.         opnum = 0;
  115.  
  116.     if (p_sc && (vpeekc() == NUL || KeyTyped == TRUE))
  117.         premsg(NUL, NUL);
  118.     State = NORMAL_BUSY;
  119.     c = vgetc();
  120.  
  121. getcount:
  122.     /* Pick up any leading digits and compute 'Prenum' */
  123.     while ((c >= '1' && c <= '9') || (Prenum != 0 && (c == DEL || c == '0')))
  124.     {
  125.         if (c == DEL)
  126.                 Prenum /= 10;
  127.         else
  128.                 Prenum = Prenum * 10 + (c - '0');
  129.         if (Prenum < 0)            /* got too large! */
  130.             Prenum = 999999999;
  131.         premsg(ctrl_w ? Ctrl('W') : ' ', NUL);
  132.         c = vgetc();
  133.     }
  134.  
  135. /*
  136.  * If we got CTRL-W there may be a/another count
  137.  */
  138.     if (c == Ctrl('W') && !ctrl_w)
  139.     {
  140.         ctrl_w = TRUE;
  141.         opnum = Prenum;                        /* remember first count */
  142.         Prenum = 0;
  143.         State = ONLYKEY;                    /* no mapping for nchar, but keys */
  144.         premsg(c, NUL);
  145.         c = vgetc();                        /* get next character */
  146.         goto getcount;                        /* jump back */
  147.     }
  148.  
  149.     /*
  150.      * If we're in the middle of an operator (including after entering a yank
  151.      * buffer with ") AND we had a count before the
  152.      * operator, then that count overrides the current value of Prenum. What
  153.      * this means effectively, is that commands like "3dw" get turned into
  154.      * "d3w" which makes things fall into place pretty neatly.
  155.      * If you give a count before AND after the operator, they are multiplied.
  156.      */
  157.     if (opnum != 0)
  158.     {
  159.             if (Prenum)
  160.                 Prenum *= opnum;
  161.             else
  162.                 Prenum = opnum;
  163.             opnum = 0;
  164.     }
  165.  
  166.     Prenum1 = (Prenum == 0 ? 1 : Prenum);        /* Prenum often defaults to 1 */
  167.     premsg(c, NUL);
  168.  
  169.     /*
  170.      * get an additional character if we need one
  171.      * for CTRL-W we already got it when looking for a count
  172.      */
  173.     if (ctrl_w)
  174.     {
  175.         nchar = c;
  176.         c = Ctrl('W');
  177.         premsg(c, nchar);
  178.     }
  179.     else if (strchr("@zZtTfF[]mg'`\"", c) || (c == 'q' && !Recording && !Exec_reg) ||
  180.                                         (c == 'r' && !VIsual.lnum))
  181.     {
  182.         State = NOMAPPING;
  183.         nchar = vgetc();        /* no macro mapping for this char */
  184.         premsg(c, nchar);
  185.     }
  186.     if (p_sc)
  187.         flushbuf();        /* flush the premsg() characters onto the screen so we can
  188.                             see them while the command is being executed */
  189.  
  190. /*
  191.  * For commands that don't get another character we can put the State back to
  192.  * NORMAL and check for a window size change.
  193.  */
  194.     if (STRCHR("z:/?", c) == NULL)
  195.         State = NORMAL;
  196.     if (nchar == ESC)
  197.     {
  198.         CLEAROP;
  199.         goto normal_end;
  200.     }
  201.     switch (c)
  202.     {
  203.  
  204. /*
  205.  * 0: Macros
  206.  */
  207.       case 'q':         /* (stop) recording into a named register */
  208.         CHECKCLEAROP;
  209.                         /* command is ignored while executing a register */
  210.         if (!Exec_reg && dorecord(nchar) == FAIL)
  211.             CLEAROPBEEP;
  212.         break;
  213.  
  214.      case '@':            /* execute a named buffer */
  215.         CHECKCLEAROP;
  216.         while (Prenum1--)
  217.         {
  218.             if (doexecbuf(nchar) == FAIL)
  219.             {
  220.                 CLEAROPBEEP;
  221.                 break;
  222.             }
  223.         }
  224.         break;
  225.  
  226. /*
  227.  * 1: Screen positioning commands
  228.  */
  229.       case Ctrl('D'):
  230.         flag = TRUE;
  231.  
  232.       case Ctrl('U'):
  233.         CHECKCLEAROP;
  234.         if (Prenum)
  235.             curwin->w_p_scroll = (Prenum > curwin->w_height) ? curwin->w_height : Prenum;
  236.         n = (curwin->w_p_scroll <= curwin->w_height) ? curwin->w_p_scroll : curwin->w_height;
  237.         if (flag)
  238.         {
  239.                 curwin->w_topline += n;
  240.                 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
  241.                     curwin->w_topline = curbuf->b_ml.ml_line_count;
  242.                 comp_Botline(curwin);        /* compute curwin->w_botline */
  243.                 (void)onedown(n);
  244.         }
  245.         else
  246.         {
  247.                 if (n >= curwin->w_cursor.lnum)
  248.                     n = curwin->w_cursor.lnum - 1;
  249.                 Prenum1 = curwin->w_cursor.lnum - n;
  250.                 scrolldown(n);
  251.                 if (Prenum1 < curwin->w_cursor.lnum)
  252.                     curwin->w_cursor.lnum = Prenum1;
  253.         }
  254.         beginline(TRUE);
  255.         updateScreen(VALID);
  256.         break;
  257.  
  258.       case Ctrl('B'):
  259.       case K_SUARROW:
  260.         dir = BACKWARD;
  261.  
  262.       case Ctrl('F'):
  263.       case K_SDARROW:
  264.         CHECKCLEAROP;
  265.         (void)onepage(dir, Prenum1);
  266.         break;
  267.  
  268.       case Ctrl('E'):
  269.         CHECKCLEAROP;
  270.         scrollup(Prenum1);
  271.                 /* We may have moved to another line -- webb */
  272.         coladvance(curwin->w_curswant);
  273.         updateScreen(VALID);
  274.         break;
  275.  
  276.       case Ctrl('Y'):
  277.         CHECKCLEAROP;
  278.         scrolldown(Prenum1);
  279.                 /* We may have moved to another line -- webb */
  280.         coladvance(curwin->w_curswant);
  281.         updateScreen(VALID);
  282.         break;
  283.  
  284.       case 'z':
  285.         CHECKCLEAROP;
  286.         if (isdigit(nchar))
  287.         {
  288.             /*
  289.              * we misuse some variables to be able to call premsg()
  290.              */
  291.             operator = c;
  292.             opnum = Prenum;
  293.             Prenum = nchar - '0';
  294.             for (;;)
  295.             {
  296.                 premsg(' ', NUL);
  297.                 nchar = vgetc();
  298.                 State = NORMAL;
  299.                 if (nchar == DEL)
  300.                     Prenum /= 10;
  301.                 else if (isdigit(nchar))
  302.                     Prenum = Prenum * 10 + (nchar - '0');
  303.                 else if (nchar == CR)
  304.                 {
  305.                     win_setheight((int)Prenum);
  306.                     break;
  307.                 }
  308.                 else
  309.                 {
  310.                     CLEAROPBEEP;
  311.                     break;
  312.                 }
  313.             }
  314.             operator = NOP;
  315.