home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / util / edit / vim / src / edit.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  32KB  |  1,296 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.  * edit.c: functions for insert mode
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #include "proto.h"
  16. #include "param.h"
  17. #include "ops.h"    /* for operator */
  18.  
  19. extern char_u *get_inserted();
  20. static void start_arrow __ARGS((void));
  21. static void stop_arrow __ARGS((void));
  22. static void stop_insert __ARGS((void));
  23. static int echeck_abbr __ARGS((int));
  24.  
  25. int arrow_used;                /* Normally FALSE, set to TRUE after hitting
  26.                              * cursor key in insert mode. Used by vgetorpeek()
  27.                              * to decide when to call u_sync() */
  28. int restart_edit = 0;        /* call edit when next command finished */
  29. static char_u    *last_insert = NULL;
  30.                             /* the text of the previous insert */
  31. static int        last_insert_skip;
  32.                             /* number of chars in front of the previous insert */
  33. static int        new_insert_skip;
  34.                             /* number of chars in front of the current insert */
  35.  
  36.     void
  37. edit(count)
  38.     long count;
  39. {
  40.     int             c;
  41.     int             cc;
  42.     char_u        *ptr;
  43.     char_u        *saved_line = NULL;        /* saved line for replace mode */
  44.     linenr_t     saved_lnum = 0;        /* lnum of saved line */
  45.     int             saved_char = NUL;        /* char replaced by NL */
  46.     linenr_t     lnum;
  47.     int          temp = 0;
  48.     int             mode;
  49.     int             nextc = 0;
  50.     int             lastc = 0;
  51.     colnr_t         mincol;
  52.     static linenr_t o_lnum = 0;
  53.     static int     o_eol = FALSE;
  54. #ifdef WEBB_KEYWORD_COMPL
  55.     FPOS         complete_pos;
  56.     FPOS         first_match;
  57.     char_u         *complete_pat = NULL;
  58.     char_u         *completion_str = NULL;
  59.     char_u         *last_completion_str = NULL;
  60.     char_u         *tmp_ptr;
  61.     int             previous_c = 0;
  62.     int             complete_col = 0;            /* init for gcc */
  63.     int             complete_direction;
  64.     int             complete_any_word = 0;        /* true -> ^N/^P hit with no prefix
  65.                                              * init for gcc */
  66.     int             done;
  67.     int             found_error = FALSE;
  68.     char_u         backup_char = 0;            /* init for gcc */
  69.  
  70.     c = NUL;
  71. #endif /* WEBB_KEYWORD_COMPL */
  72.  
  73.     if (restart_edit)
  74.     {
  75.         arrow_used = TRUE;
  76.         restart_edit = 0;
  77.         /*
  78.          * If the cursor was after the end-of-line before the CTRL-O
  79.          * and it is now at the end-of-line, put it after the end-of-line
  80.          * (this is not correct in very rare cases).
  81.          */
  82.         if (o_eol && curwin->w_cursor.lnum == o_lnum &&
  83.                 *((ptr = ml_get(curwin->w_cursor.lnum)) + curwin->w_cursor.col) != NUL &&
  84.                 *(ptr + curwin->w_cursor.col + 1) == NUL)
  85.             ++curwin->w_cursor.col;
  86.     }
  87.     else
  88.     {
  89.         arrow_used = FALSE;
  90.         o_eol = FALSE;
  91.     }
  92.  
  93. #ifdef DIGRAPHS
  94.     dodigraph(-1);                    /* clear digraphs */
  95. #endif
  96.  
  97. /*
  98.  * Get the current length of the redo buffer, those characters have to be
  99.  * skipped if we want to get to the inserted characters.
  100.  */
  101.  
  102.     ptr = get_inserted();
  103.     new_insert_skip = STRLEN(ptr);
  104.     free(ptr);
  105.  
  106.     old_indent = 0;
  107.  
  108.     for (;;)
  109.     {
  110.         if (arrow_used)        /* don't repeat insert when arrow key used */
  111.             count = 0;
  112.  
  113.         if (!arrow_used)
  114.             curwin->w_set_curswant = TRUE;    /* set curwin->w_curswant for next K_DARROW or K_UARROW */
  115.         cursupdate();        /* Figure out where the cursor is based on curwin->w_cursor. */
  116.         showruler(0);
  117.         setcursor();
  118. #ifdef WEBB_KEYWORD_COMPL
  119.         previous_c = c;
  120. #endif /* WEBB_KEYWORD_COMPL */
  121.         if (nextc)            /* character remaining from CTRL-V */
  122.         {
  123.             c = nextc;
  124.             nextc = 0;
  125.         }
  126.         else
  127.         {
  128.             c = vgetc();
  129.             if (c == Ctrl('C'))
  130.                 got_int = FALSE;
  131.         }
  132. #ifdef WEBB_KEYWORD_COMPL
  133.         if (previous_c == Ctrl('N') || previous_c == Ctrl('P'))
  134.         {
  135.             /* Show error message from attempted keyword completion (probably
  136.              * 'Pattern not found') until another key is hit, then go back to
  137.              * showing what mode we are in.
  138.              */
  139.             showmode();
  140.             if (c != Ctrl('N') && c != Ctrl('P'))
  141.             {
  142.                 /* Get here when we have finished typing a sequence of ^N and
  143.                  * ^P. Free up memory that was used, and make sure we can redo
  144.                  * the insert.
  145.                  */
  146.                 if (completion_str != NULL)
  147.                     AppendToRedobuff(completion_str);
  148.                 free(complete_pat);
  149.                 free(completion_str);
  150.                 free(last_completion_str);
  151.                 complete_pat = completion_str = last_completion_str = NULL;
  152.             }
  153.         }
  154. #endif /* WEBB_KEYWORD_COMPL */
  155.         if (c != Ctrl('D'))            /* remember to detect ^^D and 0^D */
  156.             lastc = c;
  157.  
  158. /*
  159.  * In replace mode a backspace puts the original text back.
  160.  * We save the current line to be able to do that.
  161.  * If characters are appended to the line, they will be deleted.
  162.  * If we start a new line (with CR) the saved line will be empty, thus
  163.  * the characters will be deleted.
  164.  * If we backspace over the new line, that line will be saved.
  165.  */
  166.         if (State == REPLACE && saved_lnum != curwin->w_cursor.lnum)
  167.         {
  168.             free(saved_line);
  169.             saved_line = strsave(ml_get(curwin->w_cursor.lnum));
  170.             saved_lnum = curwin->w_cursor.lnum;
  171.         }
  172.  
  173. #ifdef DIGRAPHS
  174.         c = dodigraph(c);
  175. #endif /* DIGRAPHS */
  176.  
  177.         if (c == Ctrl('V'))
  178.         {
  179.             screen_start();
  180.             screen_outchar('^', curwin->w_row, curwin->w_col);
  181.             AppendToRedobuff((char_u *)"\026");    /* CTRL-V */
  182.             cursupdate();
  183.             setcursor();
  184.  
  185.             c = get_literal(&nextc);
  186.  
  187.             insertchar(c);
  188.             continue;
  189.         }
  190.         switch (c)        /* handle character in insert mode */
  191.         {
  192.               case Ctrl('O'):        /* execute one command */
  193.                 if (echeck_abbr(Ctrl('O') + 0x100))
  194.                     break;
  195.                   count = 0;
  196.                 if (State == INSERT)
  197.                     restart_edit = 'I';
  198.                 else
  199.                     restart_edit = 'R';
  200.                 o_lnum = curwin->w_cursor.lnum;
  201.                 o_eol = (gchar_cursor() == NUL);
  202.                 goto doESCkey;
  203.  
  204.               case ESC:             /* an escape ends input mode */
  205.                 if (echeck_abbr(ESC + 0x100))
  206.                     break;
  207.                 /*FALLTHROUGH*/
  208.  
  209.               case Ctrl('C'):
  210. doESCkey:
  211.                 if (!arrow_used)
  212.                 {
  213.                     AppendToRedobuff(ESC_STR);
  214.  
  215.                     if (--count > 0)        /* repeat what was typed */
  216.                     {
  217.                             (void)start_redo_ins();
  218.                             continue;
  219.                     }
  220.                     stop_insert();
  221.                 }
  222.                 if (!restart_edit)
  223.                     curwin->w_set_curswant = TRUE;
  224.  
  225.                 /*
  226.                  * The cursor should end up on the last inserted character.
  227.                  */
  228.                 if (curwin->w_cursor.col != 0 && (!restart_edit || gchar_cursor() == NUL) && !p_ri)
  229.                     dec_cursor();
  230.                 if (extraspace)            /* did reverse replace in column 0 */
  231.                 {
  232.                     (void)delchar(FALSE);
  233.                     updateline();
  234.                     extraspace = FALSE;
  235.                 }
  236.                 State = NORMAL;
  237.                     /* inchar() may have deleted the "INSERT" message */
  238.                 if (Recording)
  239.                     showmode();
  240.                 else if (p_smd)
  241.                     MSG("");
  242.                 free(saved_line);
  243.                 old_indent = 0;
  244.                 return;
  245.  
  246.                   /*
  247.                  * Insert the previously inserted text.
  248.                  * Last_insert actually is a copy of the redo buffer, so we
  249.                  * first have to remove the command.
  250.                  * For ^@ the trailing ESC will end the insert.
  251.                  */
  252.               case K_ZERO:
  253.               case Ctrl('A'):
  254.                 stuff_inserted(NUL, 1L, (c == Ctrl('A')));
  255.                 break;
  256.  
  257.                   /*
  258.                  * insert the contents of a register
  259.                  */
  260.               case Ctrl('R'):
  261.                   if (insertbuf(vgetc()) == FAIL)
  262.                     beep();
  263.                 break;
  264.  
  265.               case Ctrl('B'):            /* toggle reverse insert mode */
  266.                   p_ri = !p_ri;
  267.                 showmode();
  268.                 break;
  269.  
  270.                 /*
  271.                  * If the cursor is on an indent, ^T/^D insert/delete one
  272.                  * shiftwidth. Otherwise ^T/^D behave like a TAB/backspace.
  273.                  * This isn't completely compatible with
  274.                  * vi, but the difference isn't very noticeable and now you can
  275.                  * mix ^D/backspace and ^T/TAB without thinking about which one
  276.                  * must be used.
  277.                  */
  278.               case Ctrl('T'):        /* make indent one shiftwidth greater */
  279.               case Ctrl('D'):         /* make indent one shiftwidth smaller */
  280.                 stop_arrow();
  281.                 AppendCharToRedobuff(c);
  282.                 if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
  283.                 {
  284.                     --curwin->w_cursor.col;
  285.                     (void)delchar(FALSE);            /* delete the '^' or '0' */
  286.                     if (lastc == '^')
  287.                         old_indent = get_indent();    /* remember current indent */
  288.  
  289.                         /* determine offset from first non-blank */
  290.                     temp = curwin->w_cursor.col;
  291.                     beginline(TRUE);
  292.                     temp -= curwin->w_cursor.col;
  293.                     set_indent(0, TRUE);    /* remove all indent */
  294.                 }
  295.                 else
  296.                 {
  297. ins_indent:
  298.                         /* determine offset from first non-blank */
  299.                     temp = curwin->w_cursor.col;
  300.                     beginline(TRUE);
  301.                     temp -= curwin->w_cursor.col;
  302.  
  303.                     shift_line(c == Ctrl('D'), TRUE, 1);
  304.  
  305.                         /* try to put cursor on same character */
  306.                     temp += curwin->w_cursor.col;
  307.                 }
  308.                 if (temp <= 0)
  309.                     curwin->w_cursor.col = 0;
  310.                 else
  311.                     curwin->w_cursor.