home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-29  |  176.2 KB  |  7,497 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * edit.c: functions for Insert mode
  12.  */
  13.  
  14. #include "vim.h"
  15.  
  16. #ifdef FEAT_INS_EXPAND
  17. /*
  18.  * definitions used for CTRL-X submode
  19.  */
  20. #define CTRL_X_WANT_IDENT    0x100
  21.  
  22. #define CTRL_X_NOT_DEFINED_YET    1
  23. #define CTRL_X_SCROLL        2
  24. #define CTRL_X_WHOLE_LINE    3
  25. #define CTRL_X_FILES        4
  26. #define CTRL_X_TAGS        (5 + CTRL_X_WANT_IDENT)
  27. #define CTRL_X_PATH_PATTERNS    (6 + CTRL_X_WANT_IDENT)
  28. #define CTRL_X_PATH_DEFINES    (7 + CTRL_X_WANT_IDENT)
  29. #define CTRL_X_FINISHED        8
  30. #define CTRL_X_DICTIONARY    (9 + CTRL_X_WANT_IDENT)
  31. #define CTRL_X_THESAURUS    (10 + CTRL_X_WANT_IDENT)
  32. #define CTRL_X_CMDLINE        11
  33.  
  34. #define CHECK_KEYS_TIME        30
  35.  
  36. #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
  37.  
  38. static char *ctrl_x_msgs[] =
  39. {
  40.     N_(" Keyword completion (^N/^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */
  41.     N_(" ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"),
  42.     /* Scroll has it's own msgs, in it's place there is the msg for local
  43.      * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL)  -- Acevedo */
  44.     N_(" Keyword Local completion (^N/^P)"),
  45.     N_(" Whole line completion (^L/^N/^P)"),
  46.     N_(" File name completion (^F/^N/^P)"),
  47.     N_(" Tag completion (^]/^N/^P)"),
  48.     N_(" Path pattern completion (^N/^P)"),
  49.     N_(" Definition completion (^D/^N/^P)"),
  50.     NULL,
  51.     N_(" Dictionary completion (^K/^N/^P)"),
  52.     N_(" Thesaurus completion (^T/^N/^P)"),
  53.     N_(" Command-line completion (^V/^N/^P)")
  54. };
  55.  
  56. static char_u e_hitend[] = N_("Hit end of paragraph");
  57.  
  58. /*
  59.  * Structure used to store one match for insert completion.
  60.  */
  61. struct Completion
  62. {
  63.     struct Completion    *next;
  64.     struct Completion    *prev;
  65.     char_u        *str;      /* matched text */
  66.     char_u        *fname;      /* file containing the match */
  67.     int            original; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
  68.     int            number;      /* sequence number */
  69. };
  70.  
  71. /* the original text when the expansion begun */
  72. #define ORIGINAL_TEXT    (1)
  73. #define FREE_FNAME    (2)
  74.  
  75. /*
  76.  * All the current matches are stored in a list.
  77.  * "first_match" points to the start of the list.
  78.  * "curr_match" points to the currently selected entry.
  79.  * "shown_match" is different from curr_match during ins_compl_get_exp().
  80.  */
  81. static struct Completion    *first_match = NULL;
  82. static struct Completion    *curr_match = NULL;
  83. static struct Completion    *shown_match = NULL;
  84.  
  85. static int            started_completion = FALSE;
  86. static int            completion_matches = 0;
  87. static char_u            *complete_pat = NULL;
  88. static int            complete_direction = FORWARD;
  89. static int            shown_direction = FORWARD;
  90. static int            completion_pending = FALSE;
  91. static pos_T            initial_pos;
  92. static colnr_T            complete_col = 0;    /* column where the text starts
  93.                            that is being completed */
  94. static int            save_sm;
  95. static char_u            *original_text = NULL;  /* text before completion */
  96. static int            continue_mode = 0;
  97. static expand_T            complete_xp;
  98.  
  99. static int  ins_compl_add __ARGS((char_u *str, int len, char_u *, int dir, int reuse));
  100. static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir));
  101. static int  ins_compl_make_cyclic __ARGS((void));
  102. static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags, int thesaurus));
  103. static void ins_compl_free __ARGS((void));
  104. static void ins_compl_clear __ARGS((void));
  105. static void ins_compl_prep __ARGS((int c));
  106. static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));
  107. static int  ins_compl_get_exp __ARGS((pos_T *ini, int dir));
  108. static void ins_compl_delete __ARGS((void));
  109. static void ins_compl_insert __ARGS((void));
  110. static int  ins_compl_next __ARGS((int allow_get_expansion));
  111. static int  ins_complete __ARGS((int c));
  112. static int  quote_meta __ARGS((char_u *dest, char_u *str, int len));
  113. #endif /* FEAT_INS_EXPAND */
  114.  
  115. #define BACKSPACE_CHAR            1
  116. #define BACKSPACE_WORD            2
  117. #define BACKSPACE_WORD_NOT_SPACE    3
  118. #define BACKSPACE_LINE            4
  119.  
  120. static void ins_redraw __ARGS((void));
  121. static void ins_ctrl_v __ARGS((void));
  122. static void undisplay_dollar __ARGS((void));
  123. static void insert_special __ARGS((int, int, int));
  124. #ifdef FEAT_COMMENTS
  125. static int  cmplen __ARGS((char_u *s1, char_u *s2));
  126. #endif
  127. static void redo_literal __ARGS((int c));
  128. static void start_arrow __ARGS((pos_T *end_insert_pos));
  129. static void stop_insert __ARGS((pos_T *end_insert_pos));
  130. static int  echeck_abbr __ARGS((int));
  131. static void replace_push_off __ARGS((int c));
  132. static int  replace_pop __ARGS((void));
  133. static void replace_join __ARGS((int off));
  134. static void replace_pop_ins __ARGS((void));
  135. #ifdef FEAT_MBYTE
  136. static void mb_replace_pop_ins __ARGS((int cc));
  137. #endif
  138. static void replace_flush __ARGS((void));
  139. static void replace_do_bs __ARGS((void));
  140. #ifdef FEAT_CINDENT
  141. static int cindent_on __ARGS((void));
  142. #endif
  143. static void ins_reg __ARGS((void));
  144. static void ins_ctrl_g __ARGS((void));
  145. static int  ins_esc __ARGS((long *count, int cmdchar));
  146. #ifdef FEAT_RIGHTLEFT
  147. static void ins_ctrl_ __ARGS((void));
  148. #endif
  149. #ifdef FEAT_VISUAL
  150. static int ins_start_select __ARGS((int c));
  151. #endif
  152. static void ins_shift __ARGS((int c, int lastc));
  153. static void ins_del __ARGS((void));
  154. static int  ins_bs __ARGS((int c, int mode, int *inserted_space_p));
  155. #ifdef FEAT_MOUSE
  156. static void ins_mouse __ARGS((int c));
  157. static void ins_mousescroll __ARGS((int up));
  158. #endif
  159. static void ins_left __ARGS((void));
  160. static void ins_home __ARGS((int c));
  161. static void ins_end __ARGS((int c));
  162. static void ins_s_left __ARGS((void));
  163. static void ins_right __ARGS((void));
  164. static void ins_s_right __ARGS((void));
  165. static void ins_up __ARGS((int startcol));
  166. static void ins_pageup __ARGS((void));
  167. static void ins_down __ARGS((int startcol));
  168. static void ins_pagedown __ARGS((void));
  169. #ifdef FEAT_DND
  170. static void ins_drop __ARGS((void));
  171. #endif
  172. static int  ins_tab __ARGS((void));
  173. static int  ins_eol __ARGS((int c));
  174. #ifdef FEAT_DIGRAPHS
  175. static int  ins_digraph __ARGS((void));
  176. #endif
  177. static int  ins_copychar __ARGS((linenr_T lnum));
  178. #ifdef FEAT_SMARTINDENT
  179. static void ins_try_si __ARGS((int c));
  180. #endif
  181. static colnr_T get_nolist_virtcol __ARGS((void));
  182.  
  183. static colnr_T    Insstart_textlen;    /* length of line when insert started */
  184. static colnr_T    Insstart_blank_vcol;    /* vcol for first inserted blank */
  185.  
  186. static char_u    *last_insert = NULL;    /* the text of the previous insert,
  187.                        K_SPECIAL and CSI are escaped */
  188. static int    last_insert_skip; /* nr of chars in front of previous insert */
  189. static int    new_insert_skip;  /* nr of chars in front of current insert */
  190.  
  191. #ifdef FEAT_CINDENT
  192. static int    can_cindent;        /* may do cindenting on this line */
  193. #endif
  194.  
  195. static int    old_indent = 0;        /* for ^^D command in insert mode */
  196.  
  197. #ifdef FEAT_RIGHTLEFT
  198. int        revins_on;            /* reverse insert mode on */
  199. int        revins_chars;        /* how much to skip after edit */
  200. int        revins_legal;        /* was the last char 'legal'? */
  201. int        revins_scol;        /* start column of revins session */
  202. #endif
  203.  
  204. #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
  205. static short    previous_script = smRoman;
  206. #endif
  207.  
  208. static int    ins_need_undo;        /* call u_save() before inserting a
  209.                        char.  Set when edit() is called.
  210.                        after that arrow_used is used. */
  211.  
  212. /*
  213.  * edit(): Start inserting text.
  214.  *
  215.  * "cmdchar" can be:
  216.  * 'i'    normal insert command
  217.  * 'a'    normal append command
  218.  * 'R'    replace command
  219.  * 'r'    "r<CR>" command: insert one <CR>.  Note: count can be > 1, for redo,
  220.  *    but still only one <CR> is inserted.  The <Esc> is not used for redo.
  221.  * 'g'    "gI" command.
  222.  * 'V'    "gR" command for Virtual Replace mode.
  223.  * 'v'    "gr" command for single character Virtual Replace mode.
  224.  *
  225.  * This function is not called recursively.  For CTRL-O commands, it returns
  226.  * and lets the caller handle the Normal-mode command.
  227.  *
  228.  * Return TRUE if a CTRL-O command caused the return (insert mode pending).
  229.  */
  230.     int
  231. edit(cmdchar, startln, count)
  232.     int        cmdchar;
  233.     int        startln;    /* if set, insert at start of line */
  234.     long    count;
  235. {
  236.     int        c = 0;
  237.     char_u    *ptr;
  238.     int        lastc;
  239.     colnr_T    mincol;
  240.     static linenr_T o_lnum = 0;
  241.     static int    o_eol = FALSE;
  242.     int        i;
  243.     int        did_backspace = TRUE;        /* previous char was backspace */
  244. #ifdef FEAT_CINDENT
  245.     int        line_is_white = FALSE;        /* line is empty before insert */
  246. #endif
  247.     linenr_T    old_topline = 0;        /* topline before insertion */
  248. #ifdef FEAT_DIFF
  249.     int        old_topfill = -1;
  250. #endif
  251.     int        inserted_space = FALSE;     /* just inserted a space */
  252.     int        replaceState = REPLACE;
  253.     int        did_restart_edit = restart_edit;
  254.  
  255.     /* sleep before redrawing, needed for "CTRL-O :" that results in an
  256.      * error message */
  257.     check_for_delay(TRUE);
  258.  
  259. #ifdef HAVE_SANDBOX
  260.     /* Don't allow inserting in the sandbox. */
  261.     if (sandbox != 0)
  262.     {
  263.     EMSG(_(e_sandbox));
  264.     return FALSE;
  265.     }
  266. #endif
  267.  
  268. #ifdef FEAT_INS_EXPAND
  269.     ins_compl_clear();        /* clear stuff for CTRL-X mode */
  270. #endif
  271.  
  272. #ifdef FEAT_MOUSE
  273.     /*
  274.      * When doing a paste with the middle mouse button, Insstart is set to
  275.      * where the paste started.
  276.      */
  277.     if (where_paste_started.lnum != 0)
  278.     Insstart = where_paste_started;
  279.     else
  280. #endif
  281.     {
  282.     Insstart = curwin->w_cursor;
  283.     if (startln)
  284.         Insstart.col = 0;
  285.     }
  286.     Insstart_textlen = linetabsize(ml_get_curline());
  287.     Insstart_blank_vcol = MAXCOL;
  288.     if (!did_ai)
  289.     ai_col = 0;
  290.  
  291.     if (cmdchar != NUL && restart_edit == 0)
  292.     {
  293.     ResetRedobuff();
  294.     AppendNumberToRedobuff(count);
  295. #ifdef FEAT_VREPLACE
  296.     if (cmdchar == 'V' || cmdchar == 'v')
  297.     {
  298.         /* "gR" or "gr" command */
  299.         AppendCharToRedobuff('g');
  300.         AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R');
  301.     }
  302.     else
  303. #endif
  304.     {
  305.         AppendCharToRedobuff(cmdchar);
  306.         if (cmdchar == 'g')            /* "gI" command */
  307.         AppendCharToRedobuff('I');
  308.         else if (cmdchar == 'r')        /* "r<CR>" command */
  309.         count = 1;            /* insert only one <CR> */
  310.     }
  311.     }
  312.  
  313.     if (cmdchar == 'R')
  314.     {
  315. #ifdef FEAT_FKMAP
  316.     if (p_fkmap && p_ri)
  317.     {
  318.         beep_flush();
  319.         EMSG(farsi_text_3);        /* encoded in Farsi */
  320.         State = INSERT;
  321.     }
  322.     else
  323. #endif
  324.     State = REPLACE;
  325.     }
  326. #ifdef FEAT_VREPLACE
  327.     else if (cmdchar == 'V' || cmdchar == 'v')
  328.     {
  329.     State = VREPLACE;
  330.     replaceState = VREPLACE;
  331.     orig_line_count = curbuf->b_ml.ml_line_count;
  332.     vr_lines_changed = 1;
  333.     }
  334. #endif
  335.     else
  336.     State = INSERT;
  337.  
  338. #ifdef FEAT_EX_EXTRA
  339.     stop_insert_mode = FALSE;
  340. #endif
  341.  
  342.     /*
  343.      * Need to recompute the cursor position, it might move when the cursor is
  344.      * on a TAB or special character.
  345.      */
  346.     curs_columns(TRUE);
  347.  
  348.     /*
  349.      * Enable langmap or IME, indicated by 'iminsert'.
  350.      * Note that IME may enabled/disabled without us noticing here, thus the
  351.      * 'iminsert' value may not reflect what is actually used.  It is updated
  352.      * when hitting <Esc>.
  353.      */
  354.     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
  355.     State |= LANGMAP;
  356. #ifdef USE_IM_CONTROL
  357.     im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
  358. #endif
  359.  
  360. #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
  361.     KeyScript(previous_script);
  362. #endif
  363.  
  364. #ifdef FEAT_MOUSE
  365.     setmouse();
  366. #endif
  367. #ifdef FEAT_CMDL_INFO
  368.     clear_showcmd();
  369. #endif
  370. #ifdef FEAT_RIGHTLEFT
  371.     /* there is no reverse replace mode */
  372.     revins_on = (State == INSERT && p_ri);
  373.     if (revins_on)
  374.     undisplay_dollar();
  375.     revins_chars = 0;
  376.     revins_legal = 0;
  377.     revins_scol = -1;
  378. #endif
  379.  
  380.     /*
  381.      * Handle restarting Insert mode.
  382.      * Don't do this for "CTRL-O ." (repeat an insert): we get here with
  383.      * restart_edit non-zero, and something in the stuff buffer.
  384.      */
  385.     if (restart_edit != 0 && stuff_empty())
  386.     {
  387. #ifdef FEAT_MOUSE
  388.     /*
  389.      * After a paste we consider text typed to be part of the insert for
  390.      * the pasted text. You can backspace over the pasted text too.
  391.      */
  392.     if (where_paste_started.lnum)
  393.         arrow_used = FALSE;
  394.     else
  395. #endif
  396.         arrow_used = TRUE;
  397.     restart_edit = 0;
  398.  
  399.     /*
  400.      * If the cursor was after the end-of-line before the CTRL-O and it is
  401.      * now at the end-of-line, put it after the end-of-line (this is not
  402.      * correct in very rare cases).
  403.      * Also do this if curswant is greater than the current virtual
  404.      * column.  Eg after "^O$" or "^O80|".
  405.      */
  406.     validate_virtcol();
  407.     update_curswant();
  408.     if (((o_eol && curwin->w_cursor.lnum == o_lnum)
  409.             || curwin->w_curswant > curwin->w_virtcol)
  410.         && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL)
  411.     {
  412.         if (ptr[1] == NUL)
  413.         ++curwin->w_cursor.col;
  414. #ifdef FEAT_MBYTE
  415.         else if (has_mbyte)
  416.         {
  417.         i = (*mb_ptr2len_check)(ptr);
  418.         if (ptr[i] == NUL)
  419.             curwin->w_cursor.col += i;
  420.         }
  421. #endif
  422.     }
  423.     }
  424.     else
  425.     {
  426.     arrow_used = FALSE;
  427.     o_eol = FALSE;
  428.     }
  429.  
  430.     /* we are in insert mode now, don't need to start it anymore */
  431.     need_start_insertmode = FALSE;
  432.  
  433.     /* Need to save the line for undo before inserting the first char. */
  434.     ins_need_undo = TRUE;
  435.  
  436. #ifdef FEAT_MOUSE
  437.     where_paste_started.lnum = 0;
  438. #endif
  439. #ifdef FEAT_CINDENT
  440.     can_cindent = TRUE;
  441. #endif
  442. #ifdef FEAT_FOLDING
  443.     /* The cursor line is not in a closed fold, unless 'insertmode' is set or
  444.      * restarting. */
  445.     if (!p_im && did_restart_edit == 0)
  446.     foldOpenCursor();
  447. #endif
  448.  
  449.     /*
  450.      * If 'showmode' is set, show the current (insert/replace/..) mode.
  451.      * A warning message for changing a readonly file is given here, before
  452.      * actually changing anything.  It's put after the mode, if any.
  453.      */
  454.     i = 0;
  455.     if (p_smd)
  456.     i = showmode();
  457.  
  458.     if (!p_im && did_restart_edit == 0)
  459.     change_warning(i + 1);
  460.  
  461. #ifdef CURSOR_SHAPE
  462.     ui_cursor_shape();        /* may show different cursor shape */
  463. #endif
  464. #ifdef FEAT_DIGRAPHS
  465.     do_digraph(-1);        /* clear digraphs */
  466. #endif
  467.  
  468. /*
  469.  * Get the current length of the redo buffer, those characters have to be
  470.  * skipped if we want to get to the inserted characters.
  471.  */
  472.     ptr = get_inserted();
  473.     if (ptr == NULL)
  474.     new_insert_skip = 0;
  475.     else
  476.     {
  477.     new_insert_skip = (int)STRLEN(ptr);
  478.     vim_free(ptr);
  479.     }
  480.  
  481.     old_indent = 0;
  482.  
  483.     /*
  484.      * Main loop in Insert mode: repeat until Insert mode is left.
  485.      */
  486.     for (;;)
  487.     {
  488. #ifdef FEAT_RIGHTLEFT
  489.     if (!revins_legal)
  490.         revins_scol = -1;        /* reset on illegal motions */
  491.     else
  492.         revins_legal = 0;
  493. #endif
  494.     if (arrow_used)        /* don't repeat insert when arrow key used */
  495.         count = 0;
  496.  
  497. #ifdef FEAT_EX_EXTRA
  498.     if (stop_insert_mode)
  499.     {
  500.         /* ":stopinsert" used */
  501.         count = 0;
  502.         goto doESCkey;
  503.     }
  504. #endif
  505.  
  506.     /* set curwin->w_curswant for next K_DOWN or K_UP */
  507.     if (!arrow_used)
  508.         curwin->w_set_curswant = TRUE;
  509.  
  510.     /* If there is no typeahead may check for timestamps (e.g., for when a
  511.      * menu invoked a shell command). */
  512.     if (stuff_empty())
  513.     {
  514.         did_check_timestamps = FALSE;
  515.         if (need_check_timestamps)
  516.         check_timestamps(FALSE);
  517.     }
  518.  
  519.     /*
  520.      * When emsg() was called msg_scroll will have been set.
  521.      */
  522.     msg_scroll = FALSE;
  523.  
  524. #ifdef FEAT_FOLDING
  525.     /* Open fold at the cursor line, according to 'foldopen'. */
  526.     if (fdo_flags & FDO_INSERT)
  527.         foldOpenCursor();
  528.     /* Close folds where the cursor isn't, according to 'foldclose' */
  529.     if (!char_avail())
  530.         foldCheckClose();
  531. #endif
  532.  
  533.     /*
  534.      * If we inserted a character at the last position of the last line in
  535.      * the window, scroll the window one line up. This avoids an extra
  536.      * redraw.
  537.      * This is detected when the cursor column is smaller after inserting
  538.      * something.
  539.      * Don't do this when the topline changed already, it has
  540.      * already been adjusted (by insertchar() calling open_line())).
  541.      */
  542.     if (curbuf->b_mod_set
  543.         && curwin->w_p_wrap
  544.         && !did_backspace
  545.         && curwin->w_topline == old_topline
  546. #ifdef FEAT_DIFF
  547.         && curwin->w_topfill == old_topfill
  548. #endif
  549.         )
  550.     {
  551.         mincol = curwin->w_wcol;
  552.         validate_cursor_col();
  553.  
  554.         if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts
  555.             && curwin->w_wrow == W_WINROW(curwin)
  556.                          + curwin->w_height - 1 - p_so
  557.             && (curwin->w_cursor.lnum != curwin->w_topline
  558. #ifdef FEAT_DIFF
  559.             || curwin->w_topfill > 0
  560. #endif
  561.             ))
  562.         {
  563. #ifdef FEAT_DIFF
  564.         if (curwin->w_topfill > 0)
  565.             --curwin->w_topfill;
  566.         else
  567. #endif
  568. #ifdef FEAT_FOLDING
  569.         if (hasFolding(curwin->w_topline, NULL, &old_topline))
  570.             set_topline(curwin, old_topline + 1);
  571.         else
  572. #endif
  573.             set_topline(curwin, curwin->w_topline + 1);
  574.         }
  575.     }
  576.  
  577.     /* May need to adjust w_topline to show the cursor. */
  578.     update_topline();
  579.  
  580.     did_backspace = FALSE;
  581.  
  582.     validate_cursor();        /* may set must_redraw */
  583.  
  584.     /*
  585.      * Redraw the display when no characters are waiting.
  586.      * Also shows mode, ruler and positions cursor.
  587.      */
  588.     ins_redraw();
  589.  
  590. #ifdef FEAT_SCROLLBIND
  591.     if (curwin->w_p_scb)
  592.         do_check_scrollbind(TRUE);
  593. #endif
  594.  
  595.     update_curswant();
  596.     old_topline = curwin->w_topline;
  597. #ifdef FEAT_DIFF
  598.     old_topfill = curwin->w_topfill;
  599. #endif
  600.  
  601. #ifdef USE_ON_FLY_SCROLL
  602.     dont_scroll = FALSE;        /* allow scrolling here */
  603. #endif
  604.  
  605.     /*
  606.      * Get a character for Insert mode.
  607.      */
  608.     lastc = c;            /* remember previous char for CTRL-D */
  609.     c = safe_vgetc();
  610.  
  611. #ifdef FEAT_RIGHTLEFT
  612.     if (p_hkmap && KeyTyped)
  613.         c = hkmap(c);        /* Hebrew mode mapping */
  614. #endif
  615. #ifdef FEAT_FKMAP
  616.     if (p_fkmap && KeyTyped)
  617.         c = fkmap(c);        /* Farsi mode mapping */
  618. #endif
  619.  
  620. #ifdef FEAT_INS_EXPAND
  621.     /* Prepare for or stop CTRL-X mode.  This doesn't do completion, but
  622.      * it does fix up the text when finishing completion. */
  623.     ins_compl_prep(c);
  624. #endif
  625.  
  626.     /* CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to mode
  627.      * selected with 'insertmode'.  */
  628.     if (c == Ctrl_BSL)
  629.     {
  630.         /* may need to redraw when no more chars available now */
  631.         ins_redraw();
  632.         ++no_mapping;
  633.         ++allow_keys;
  634.         c = safe_vgetc();
  635.         --no_mapping;
  636.         --allow_keys;
  637.         if (c != Ctrl_N && c != Ctrl_G)    /* it's something else */
  638.         {
  639.         vungetc(c);
  640.         c = Ctrl_BSL;
  641.         }
  642.         else if (c == Ctrl_G && p_im)
  643.         continue;
  644.         else
  645.         {
  646.         count = 0;
  647.         goto doESCkey;
  648.         }
  649.     }
  650.  
  651. #ifdef FEAT_DIGRAPHS
  652.     c = do_digraph(c);
  653. #endif
  654.  
  655. #ifdef FEAT_INS_EXPAND
  656.     if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE)
  657.         goto docomplete;
  658. #endif
  659.     if (c == Ctrl_V || c == Ctrl_Q)
  660.     {
  661.         ins_ctrl_v();
  662.         c = Ctrl_V;    /* pretend CTRL-V is last typed character */
  663.         continue;
  664.     }
  665.  
  666. #ifdef FEAT_CINDENT
  667.     if (cindent_on()
  668. # ifdef FEAT_INS_EXPAND
  669.         && ctrl_x_mode == 0
  670. # endif
  671.        )
  672.     {
  673.         /* A key name preceded by a bang means this key is not to be
  674.          * inserted.  Skip ahead to the re-indenting below.
  675.          * A key name preceded by a star means that indenting has to be
  676.          * done before inserting the key. */
  677.         line_is_white = inindent(0);
  678.         if (in_cinkeys(c, '!', line_is_white))
  679.         goto force_cindent;
  680.         if (can_cindent && in_cinkeys(c, '*', line_is_white)
  681.                             && stop_arrow() == OK)
  682.         do_c_expr_indent();
  683.     }
  684. #endif
  685.  
  686. #ifdef FEAT_RIGHTLEFT
  687.     if (curwin->w_p_rl)
  688.         switch (c)
  689.         {
  690.         case K_LEFT:    c = K_RIGHT; break;
  691.         case K_S_LEFT:    c = K_S_RIGHT; break;
  692.         case K_C_LEFT:    c = K_C_RIGHT; break;
  693.         case K_RIGHT:    c = K_LEFT; break;
  694.         case K_S_RIGHT: c = K_S_LEFT; break;
  695.         case K_C_RIGHT: c = K_C_LEFT; break;
  696.         }
  697. #endif
  698.  
  699. #ifdef FEAT_VISUAL
  700.     /*
  701.      * If 'keymodel' contains "startsel", may start selection.  If it
  702.      * does, a CTRL-O and c will be stuffed, we need to get these
  703.      * characters.
  704.      */
  705.     if (ins_start_select(c))
  706.         continue;
  707. #endif
  708.  
  709.     /*
  710.      * The big switch to handle a character in insert mode.
  711.      */
  712.     switch (c)
  713.     {
  714.     /* toggle insert/replace mode */
  715.     case K_INS:
  716.     case K_KINS:
  717. #ifdef FEAT_FKMAP
  718.         if (p_fkmap && p_ri)
  719.         {
  720.         beep_flush();
  721.         EMSG(farsi_text_3);    /* encoded in Farsi */
  722.         break;
  723.         }
  724. #endif
  725.         if (State & REPLACE_FLAG)
  726.         State = INSERT | (State & LANGMAP);
  727.         else
  728.         State = replaceState | (State & LANGMAP);
  729.         AppendCharToRedobuff(K_INS);
  730.         showmode();
  731. #ifdef CURSOR_SHAPE
  732.         ui_cursor_shape();        /* may show different cursor shape */
  733. #endif
  734.         break;
  735.  
  736. #ifdef FEAT_INS_EXPAND
  737.     /* Enter CTRL-X mode */
  738.     case Ctrl_X:
  739.         /* CTRL-X after CTRL-V CTRL-X doesn't do anything, so that CTRL-X
  740.          * CTRL-V works like CTRL-N */
  741.         if (ctrl_x_mode != CTRL_X_CMDLINE)
  742.         {
  743.         /* if the next ^X<> won't ADD nothing, then reset
  744.          * continue_status */
  745.         if (continue_status & CONT_N_ADDS)
  746.             continue_status = (continue_status | CONT_INTRPT);
  747.         else
  748.             continue_status = 0;
  749.         /* We're not sure which CTRL-X mode it will be yet */
  750.         ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
  751.         edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
  752.         edit_submode_pre = NULL;
  753.         showmode();
  754.         }
  755.         break;
  756. #endif
  757.  
  758.     /* end of Select mode mapping - ignore */
  759.     case K_SELECT:
  760.         break;
  761.  
  762.     /* suspend when 'insertmode' set */
  763.     case Ctrl_Z:
  764.         if (!p_im)
  765.         goto normalchar;    /* insert CTRL-Z as normal char */
  766.         stuffReadbuff((char_u *)":st\r");
  767.         c = Ctrl_O;
  768.         /*FALLTHROUGH*/
  769.  
  770.     /* execute one command */
  771.     case Ctrl_O:
  772.         if (echeck_abbr(Ctrl_O + ABBR_OFF))
  773.         break;
  774.         count = 0;
  775. #ifdef FEAT_VREPLACE
  776.         if (State & VREPLACE_FLAG)
  777.         restart_edit = 'V';
  778.         else
  779. #endif
  780.         if (State & REPLACE_FLAG)
  781.         restart_edit = 'R';
  782.         else
  783.         restart_edit = 'I';
  784.         o_lnum = curwin->w_cursor.lnum;
  785. #ifdef FEAT_VIRTUALEDIT
  786.         if (virtual_active())
  787.         o_eol = FALSE;        /* cursor always keeps its column */
  788.         else
  789. #endif
  790.         o_eol = (gchar_cursor() == NUL);
  791.         goto doESCkey;
  792.  
  793. #ifdef FEAT_SNIFF
  794.     case K_SNIFF:
  795.         stuffcharReadbuff(K_SNIFF);
  796.         goto doESCkey;
  797. #endif
  798.  
  799.     /* Hitting the help key in insert mode is like <ESC> <Help> */
  800.     case K_HELP:
  801.     case K_F1:
  802.     case K_XF1:
  803.         stuffcharReadbuff(K_HELP);
  804.         if (p_im)
  805.         need_start_insertmode = TRUE;
  806.         goto doESCkey;
  807.  
  808. #ifdef FEAT_NETBEANS_INTG
  809.     case K_F21:
  810.         ++no_mapping;        /* don't map the next key hits */
  811.         i = safe_vgetc();
  812.         --no_mapping;
  813.         netbeans_keycommand(i);
  814.         break;
  815. #endif
  816.  
  817.     /* an escape ends input mode */
  818.     case ESC:
  819.         if (echeck_abbr(ESC + ABBR_OFF))
  820.         break;
  821.         /*FALLTHROUGH*/
  822.  
  823.     case Ctrl_C:
  824. #ifdef FEAT_CMDWIN
  825.         if (c == Ctrl_C && cmdwin_type != 0)
  826.         {
  827.         /* Close the cmdline window. */
  828.         cmdwin_result = K_IGNORE;
  829.         got_int = FALSE; /* don't stop executing autocommands et al. */
  830.         goto doESCkey;
  831.         }
  832. #endif
  833.  
  834. #ifdef UNIX
  835. do_intr:
  836. #endif
  837.         /* when 'insertmode' set, and not halfway a mapping, don't leave
  838.          * Insert mode */
  839.         if (goto_im())
  840.         {
  841.         if (got_int)
  842.         {
  843.             (void)vgetc();        /* flush all buffers */
  844.             got_int = FALSE;
  845.         }
  846.         else
  847.             vim_beep();
  848.         break;
  849.         }
  850. doESCkey:
  851.         /*
  852.          * This is the ONLY return from edit()!
  853.          */
  854.         if (ins_esc(&count, cmdchar))
  855.         return (c == Ctrl_O);
  856.         continue;
  857.  
  858.     /*
  859.      * Insert the previously inserted text.
  860.      * For ^@ the trailing ESC will end the insert, unless there is an
  861.      * error.
  862.      */
  863.     case K_ZERO:
  864.     case NUL:
  865.     case Ctrl_A:
  866.         if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL
  867.                            && c != Ctrl_A && !p_im)
  868.         goto doESCkey;        /* quit insert mode */
  869.         inserted_space = FALSE;
  870.         break;
  871.  
  872.     /* insert the contents of a register */
  873.     case Ctrl_R:
  874.         ins_reg();
  875.         auto_format();
  876.         inserted_space = FALSE;
  877.         break;
  878.  
  879.     case Ctrl_G:
  880.         ins_ctrl_g();
  881.         break;
  882.  
  883.     case Ctrl_HAT:
  884.         if (map_to_exists_mode((char_u *)"", LANGMAP))
  885.         {
  886.         /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
  887.         if (State & LANGMAP)
  888.         {
  889.             curbuf->b_p_iminsert = B_IMODE_NONE;
  890.             State &= ~LANGMAP;
  891.         }
  892.         else
  893.         {
  894.             curbuf->b_p_iminsert = B_IMODE_LMAP;
  895.             State |= LANGMAP;
  896. #ifdef USE_IM_CONTROL
  897.             im_set_active(FALSE);
  898. #endif
  899.         }
  900.         }
  901. #ifdef USE_IM_CONTROL
  902.         else
  903.         {
  904.         /* There are no ":lmap" mappings, toggle IM */
  905.         if (im_get_status())
  906.         {
  907.             curbuf->b_p_iminsert = B_IMODE_NONE;
  908.             im_set_active(FALSE);
  909.         }
  910.         else
  911.         {
  912.             curbuf->b_p_iminsert = B_IMODE_IM;
  913.             State &= ~LANGMAP;
  914.             im_set_active(TRUE);
  915.         }
  916.         }
  917. #endif
  918.         set_iminsert_global();
  919.         showmode();
  920. #ifdef FEAT_GUI
  921.         /* may show different cursor shape or color */
  922.         if (gui.in_use)
  923.         gui_update_cursor(TRUE, FALSE);
  924. #endif
  925. #if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
  926.         /* Show/unshow value of 'keymap' in status lines. */
  927.         status_redraw_curbuf();
  928. #endif
  929.         break;
  930.  
  931. #ifdef FEAT_RIGHTLEFT
  932.     case Ctrl__:
  933.         if (!p_ari)
  934.         goto normalchar;
  935.         ins_ctrl_();
  936.         break;
  937. #endif
  938.  
  939.     /* Make indent one shiftwidth smaller. */
  940.     case Ctrl_D:
  941. #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
  942.         if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
  943.         goto docomplete;
  944. #endif
  945.         /* FALLTHROUGH */
  946.  
  947.     /* Make indent one shiftwidth greater. */
  948.     case Ctrl_T:
  949. # ifdef FEAT_INS_EXPAND
  950.         if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
  951.         {
  952.         if (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)
  953.         {
  954.             ctrl_x_mode = 0;
  955.             msg_attr((char_u *)_("'thesaurus' option is empty"),
  956.                  hl_attr(HLF_E));
  957.             if (emsg_silent == 0)
  958.             {
  959.             vim_beep();
  960.             setcursor();
  961.             out_flush();
  962.             ui_delay(2000L, FALSE);
  963.             }
  964.             break;
  965.         }
  966.         goto docomplete;
  967.         }
  968. # endif
  969.         ins_shift(c, lastc);
  970.         auto_format();
  971.         inserted_space = FALSE;
  972.         break;
  973.  
  974.     /* delete character under the cursor */
  975.     case K_DEL:
  976.     case K_KDEL:
  977.         ins_del();
  978.         auto_format();
  979.         break;
  980.  
  981.     /* delete character before the cursor */
  982.     case K_BS:
  983.     case Ctrl_H:
  984.         did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
  985.         auto_format();
  986.         break;
  987.  
  988.     /* delete word before the cursor */
  989.     case Ctrl_W:
  990.         did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
  991.         auto_format();
  992.         break;
  993.  
  994.     /* delete all inserted text in current line */
  995.     case Ctrl_U:
  996.         did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
  997.         auto_format();
  998.         inserted_space = FALSE;
  999.         break;
  1000.  
  1001. #ifdef FEAT_MOUSE
  1002.     case K_LEFTMOUSE:
  1003.     case K_LEFTMOUSE_NM:
  1004.     case K_LEFTDRAG:
  1005.     case K_LEFTRELEASE:
  1006.     case K_LEFTRELEASE_NM:
  1007.     case K_MIDDLEMOUSE:
  1008.     case K_MIDDLEDRAG:
  1009.     case K_MIDDLERELEASE:
  1010.     case K_RIGHTMOUSE:
  1011.     case K_RIGHTDRAG:
  1012.     case K_RIGHTRELEASE:
  1013.     case K_X1MOUSE:
  1014.     case K_X1DRAG:
  1015.     case K_X1RELEASE:
  1016.     case K_X2MOUSE:
  1017.     case K_X2DRAG:
  1018.     case K_X2RELEASE:
  1019.         ins_mouse(c);
  1020.         break;
  1021.  
  1022.     /* Default action for scroll wheel up: scroll up */
  1023.     case K_MOUSEDOWN:
  1024.         ins_mousescroll(FALSE);
  1025.         break;
  1026.  
  1027.     /* Default action for scroll wheel down: scroll down */
  1028.     case K_MOUSEUP:
  1029.         ins_mousescroll(TRUE);
  1030.         break;
  1031. #endif
  1032.  
  1033.     case K_IGNORE:
  1034.         break;
  1035.  
  1036. #ifdef FEAT_GUI
  1037.     case K_VER_SCROLLBAR:
  1038.         ins_scroll();
  1039.         break;
  1040.  
  1041.     case K_HOR_SCROLLBAR:
  1042.         ins_horscroll();
  1043.         break;
  1044. #endif
  1045.  
  1046.     case K_HOME:
  1047.     case K_KHOME:
  1048.     case K_XHOME:
  1049.     case K_S_HOME:
  1050.     case K_C_HOME:
  1051.         ins_home(c);
  1052.         break;
  1053.  
  1054.     case K_END:
  1055.     case K_KEND:
  1056.     case K_XEND:
  1057.     case K_S_END:
  1058.     case K_C_END:
  1059.         ins_end(c);
  1060.         break;
  1061.  
  1062.     case K_LEFT:
  1063.         ins_left();
  1064.         break;
  1065.  
  1066.     case K_S_LEFT:
  1067.     case K_C_LEFT:
  1068.         ins_s_left();
  1069.         break;
  1070.  
  1071.     case K_RIGHT:
  1072.         ins_right();
  1073.         break;
  1074.  
  1075.     case K_S_RIGHT:
  1076.     case K_C_RIGHT:
  1077.         ins_s_right();
  1078.         break;
  1079.  
  1080.     case K_UP:
  1081.         ins_up(FALSE);
  1082.         break;
  1083.  
  1084.     case K_S_UP:
  1085.     case K_PAGEUP:
  1086.     case K_KPAGEUP:
  1087.         ins_pageup();
  1088.         break;
  1089.  
  1090.     case K_DOWN:
  1091.         ins_down(FALSE);
  1092.         break;
  1093.  
  1094.     case K_S_DOWN:
  1095.     case K_PAGEDOWN:
  1096.     case K_KPAGEDOWN:
  1097.         ins_pagedown();
  1098.         break;
  1099.  
  1100. #ifdef FEAT_DND
  1101.     case K_DROP:
  1102.         ins_drop();
  1103.         break;
  1104. #endif
  1105.  
  1106.     /* When <S-Tab> isn't mapped, use it like a normal TAB */
  1107.     case K_S_TAB:
  1108.         c = TAB;
  1109.         /* FALLTHROUGH */
  1110.  
  1111.     /* TAB or Complete patterns along path */
  1112.     case TAB:
  1113. #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
  1114.         if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
  1115.         goto docomplete;
  1116. #endif
  1117.         inserted_space = FALSE;
  1118.         if (ins_tab())
  1119.         goto normalchar;    /* insert TAB as a normal char */
  1120.         auto_format();
  1121.         break;
  1122.  
  1123.     case K_KENTER:
  1124.         c = CR;
  1125.         /* FALLTHROUGH */
  1126.     case CR:
  1127.     case NL:
  1128. #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  1129.         /* In a quickfix window a <CR> jumps to the error under the
  1130.          * cursor. */
  1131.         if (bt_quickfix(curbuf) && c == CR)
  1132.         {
  1133.         do_cmdline_cmd((char_u *)".cc");
  1134.         break;
  1135.         }
  1136. #endif
  1137. #ifdef FEAT_CMDWIN
  1138.         if (cmdwin_type != 0)
  1139.         {
  1140.         /* Execute the command in the cmdline window. */
  1141.         cmdwin_result = CR;
  1142.         goto doESCkey;
  1143.         }
  1144. #endif
  1145.         if (ins_eol(c) && !p_im)
  1146.         goto doESCkey;        /* out of memory */
  1147.         auto_format();
  1148.         inserted_space = FALSE;
  1149.         break;
  1150.  
  1151. #if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND)
  1152.     case Ctrl_K:
  1153. # ifdef FEAT_INS_EXPAND
  1154.         if (ctrl_x_mode == CTRL_X_DICTIONARY)
  1155.         {
  1156.         if (*curbuf->b_p_dict == NUL && *p_dict == NUL)
  1157.         {
  1158.             ctrl_x_mode = 0;
  1159.             msg_attr((char_u *)_("'dictionary' option is empty"),
  1160.                  hl_attr(HLF_E));
  1161.             if (emsg_silent == 0)
  1162.             {
  1163.             vim_beep();
  1164.             setcursor();
  1165.             out_flush();
  1166.             ui_delay(2000L, FALSE);
  1167.             }
  1168.             break;
  1169.         }
  1170.         goto docomplete;
  1171.         }
  1172. # endif
  1173. # ifdef FEAT_DIGRAPHS
  1174.         c = ins_digraph();
  1175.         if (c == NUL)
  1176.         break;
  1177. # endif
  1178.         goto normalchar;
  1179. #endif /* FEAT_DIGRAPHS || FEAT_INS_EXPAND */
  1180.  
  1181. #ifdef FEAT_INS_EXPAND
  1182.     case Ctrl_RSB:        /* Tag name completion after ^X */
  1183.         if (ctrl_x_mode != CTRL_X_TAGS)
  1184.         goto normalchar;
  1185.         goto docomplete;
  1186.  
  1187.     case Ctrl_F:        /* File name completion after ^X */
  1188.         if (ctrl_x_mode != CTRL_X_FILES)
  1189.         goto normalchar;
  1190.         goto docomplete;
  1191. #endif
  1192.  
  1193.     case Ctrl_L:        /* Whole line completion after ^X */
  1194. #ifdef FEAT_INS_EXPAND
  1195.         if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
  1196. #endif
  1197.         {
  1198.         /* CTRL-L with 'insertmode' set: Leave Insert mode */
  1199.         if (p_im)
  1200.         {
  1201.             if (echeck_abbr(Ctrl_L + ABBR_OFF))
  1202.             break;
  1203.             goto doESCkey;
  1204.         }
  1205.         goto normalchar;
  1206.         }
  1207. #ifdef FEAT_INS_EXPAND
  1208.         /* FALLTHROUGH */
  1209.  
  1210.     /* Do previous/next pattern completion */
  1211.     case Ctrl_P:
  1212.     case Ctrl_N:
  1213.         /* if 'complete' is empty then plain ^P is no longer special,
  1214.          * but it is under other ^X modes */
  1215.         if (*curbuf->b_p_cpt == NUL
  1216.             && ctrl_x_mode != 0
  1217.             && !(continue_status & CONT_LOCAL))
  1218.         goto normalchar;
  1219.  
  1220. docomplete:
  1221.         if (ins_complete(c) == FAIL)
  1222.         continue_status = 0;
  1223.         break;
  1224. #endif /* FEAT_INS_EXPAND */
  1225.  
  1226.     case Ctrl_Y:        /* copy from previous line or scroll down */
  1227.     case Ctrl_E:        /* copy from next line       or scroll up */
  1228. #ifdef FEAT_INS_EXPAND
  1229.         if (ctrl_x_mode == CTRL_X_SCROLL)
  1230.         {
  1231.         if (c == Ctrl_Y)
  1232.             scrolldown_clamp();
  1233.         else
  1234.             scrollup_clamp();
  1235.         redraw_later(VALID);
  1236.         }
  1237.         else
  1238. #endif
  1239.         {
  1240.         c = ins_copychar(curwin->w_cursor.lnum
  1241.                          + (c == Ctrl_Y ? -1 : 1));
  1242.         if (c != NUL)
  1243.         {
  1244.             long    tw_save;
  1245.  
  1246.             /* The character must be taken literally, insert like it
  1247.              * was typed after a CTRL-V, and pretend 'textwidth'
  1248.              * wasn't set.  Digits, 'o' and 'x' are special after a
  1249.              * CTRL-V, don't use it for these. */
  1250.             if (c < 256 && !isalnum(c))
  1251.             AppendToRedobuff((char_u *)CTRL_V_STR);    /* CTRL-V */
  1252.             tw_save = curbuf->b_p_tw;
  1253.             curbuf->b_p_tw = -1;
  1254.             insert_special(c, TRUE, FALSE);
  1255.             curbuf->b_p_tw = tw_save;
  1256. #ifdef FEAT_RIGHTLEFT
  1257.             revins_chars++;
  1258.             revins_legal++;
  1259. #endif
  1260.             c = Ctrl_V;    /* pretend CTRL-V is last character */
  1261.             auto_format();
  1262.         }
  1263.         }
  1264.         break;
  1265.  
  1266.       default:
  1267. #ifdef UNIX
  1268.         if (c == intr_char)        /* special interrupt char */
  1269.         goto do_intr;
  1270. #endif
  1271.  
  1272.         /*
  1273.          * Insert a nomal character.
  1274.          */
  1275. normalchar:
  1276. #ifdef FEAT_SMARTINDENT
  1277.         /* Try to perform smart-indenting. */
  1278.         ins_try_si(c);
  1279. #endif
  1280.  
  1281.         if (c == ' ')
  1282.         {
  1283.         inserted_space = TRUE;
  1284. #ifdef FEAT_CINDENT
  1285.         if (inindent(0))
  1286.             can_cindent = FALSE;
  1287. #endif
  1288.         if (Insstart_blank_vcol == MAXCOL
  1289.             && curwin->w_cursor.lnum == Insstart.lnum)
  1290.             Insstart_blank_vcol = get_nolist_virtcol();
  1291.         }
  1292.  
  1293.         if (vim_iswordc(c) || !echeck_abbr(
  1294. #ifdef FEAT_MBYTE
  1295.             /* Add ABBR_OFF for characters above 0x100, this is
  1296.              * what check_abbr() expects. */
  1297.             (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) :
  1298. #endif
  1299.             c))
  1300.         {
  1301.         insert_special(c, FALSE, FALSE);
  1302. #ifdef FEAT_RIGHTLEFT
  1303.         revins_legal++;
  1304.         revins_chars++;
  1305. #endif
  1306.         }
  1307.  
  1308.         auto_format();
  1309.  
  1310. #ifdef FEAT_FOLDING
  1311.         /* When inserting a character the cursor line must never be in a
  1312.          * closed fold. */
  1313.         foldOpenCursor();
  1314. #endif
  1315.         break;
  1316.     }   /* end of switch (c) */
  1317.  
  1318.     /* If the cursor was moved we didn't just insert a space */
  1319.     if (arrow_used)
  1320.         inserted_space = FALSE;
  1321.  
  1322. #ifdef FEAT_CINDENT
  1323.     if (can_cindent && cindent_on()
  1324. # ifdef FEAT_INS_EXPAND
  1325.         && ctrl_x_mode == 0
  1326. # endif
  1327.        )
  1328.     {
  1329. force_cindent:
  1330.         /*
  1331.          * Indent now if a key was typed that is in 'cinkeys'.
  1332.          */
  1333.         if (in_cinkeys(c, ' ', line_is_white))
  1334.         {
  1335.         if (stop_arrow() == OK)
  1336.             /* re-indent the current line */
  1337.             do_c_expr_indent();
  1338.         }
  1339.     }
  1340. #endif /* FEAT_CINDENT */
  1341.  
  1342.     }    /* for (;;) */
  1343.     /* NOTREACHED */
  1344. }
  1345.  
  1346. /*
  1347.  * Redraw for Insert mode.
  1348.  * This is postponed until getting the next character to make '$' in the 'cpo'
  1349.  * option work correctly.
  1350.  * Only redraw when there are no characters available.  This speeds up
  1351.  * inserting sequences of characters (e.g., for CTRL-R).
  1352.  */
  1353.     static void
  1354. ins_redraw()
  1355. {
  1356.     if (!char_avail())
  1357.     {
  1358.     if (must_redraw)
  1359.         update_screen(0);
  1360.     else if (clear_cmdline || redraw_cmdline)
  1361.         showmode();        /* clear cmdline and show mode */
  1362.     showruler(FALSE);
  1363.     setcursor();
  1364.     emsg_on_display = FALSE;    /* may remove error message now */
  1365.     }
  1366. }
  1367.  
  1368. /*
  1369.  * Handle a CTRL-V or CTRL-Q typed in Insert mode.
  1370.  */
  1371.     static void
  1372. ins_ctrl_v()
  1373. {
  1374.     int        c;
  1375.  
  1376.     /* may need to redraw when no more chars available now */
  1377.     ins_redraw();
  1378.  
  1379.     if (redrawing() && !char_avail())
  1380.     edit_putchar('^', TRUE);
  1381.     AppendToRedobuff((char_u *)CTRL_V_STR);    /* CTRL-V */
  1382.  
  1383. #ifdef FEAT_CMDL_INFO
  1384.     add_to_showcmd_c(Ctrl_V);
  1385. #endif
  1386.  
  1387.     c = get_literal();
  1388. #ifdef FEAT_CMDL_INFO
  1389.     clear_showcmd();
  1390. #endif
  1391.     insert_special(c, FALSE, TRUE);
  1392. #ifdef FEAT_RIGHTLEFT
  1393.     revins_chars++;
  1394.     revins_legal++;
  1395. #endif
  1396. }
  1397.  
  1398. /*
  1399.  * Put a character directly onto the screen.  It's not stored in a buffer.
  1400.  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
  1401.  */
  1402. static int  pc_status;
  1403. #define PC_STATUS_UNSET    0    /* pc_bytes was not set */
  1404. #define PC_STATUS_RIGHT    1    /* right halve of double-wide char */
  1405. #define PC_STATUS_LEFT    2    /* left halve of double-wide char */
  1406. #define PC_STATUS_SET    3    /* pc_bytes was filled */
  1407. #ifdef FEAT_MBYTE
  1408. static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */
  1409. #else
  1410. static char_u pc_bytes[2];        /* saved bytes */
  1411. #endif
  1412. static int  pc_attr;
  1413. static int  pc_row;
  1414. static int  pc_col;
  1415.  
  1416.     void
  1417. edit_putchar(c, highlight)
  1418.     int        c;
  1419.     int        highlight;
  1420. {
  1421.     int        attr;
  1422.  
  1423.     if (ScreenLines != NULL)
  1424.     {
  1425.     update_topline();    /* just in case w_topline isn't valid */
  1426.     validate_cursor();
  1427.     if (highlight)
  1428.         attr = hl_attr(HLF_8);
  1429.     else
  1430.         attr = 0;
  1431.     pc_row = W_WINROW(curwin) + curwin->w_wrow;
  1432.     pc_col = W_WINCOL(curwin);
  1433. #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
  1434.     pc_status = PC_STATUS_UNSET;
  1435. #endif
  1436. #ifdef FEAT_RIGHTLEFT
  1437.     if (curwin->w_p_rl)
  1438.     {
  1439.         pc_col += W_WIDTH(curwin) - 1 - curwin->w_wcol;
  1440. # ifdef FEAT_MBYTE
  1441.         if (has_mbyte)
  1442.         {
  1443.         int fix_col = mb_fix_col(pc_col, pc_row);
  1444.  
  1445.         if (fix_col != pc_col)
  1446.         {
  1447.             screen_putchar(' ', pc_row, fix_col, attr);
  1448.             --curwin->w_wcol;
  1449.             pc_status = PC_STATUS_RIGHT;
  1450.         }
  1451.         }
  1452. # endif
  1453.     }
  1454.     else
  1455. #endif
  1456.     {
  1457.         pc_col += curwin->w_wcol;
  1458. #ifdef FEAT_MBYTE
  1459.         if (mb_lefthalve(pc_row, pc_col))
  1460.         pc_status = PC_STATUS_LEFT;
  1461. #endif
  1462.     }
  1463.  
  1464.     /* save the character to be able to put it back */
  1465. #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
  1466.     if (pc_status == PC_STATUS_UNSET)
  1467. #endif
  1468.     {
  1469.         screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
  1470.         pc_status = PC_STATUS_SET;
  1471.     }
  1472.     screen_putchar(c, pc_row, pc_col, attr);
  1473.     }
  1474. }
  1475.  
  1476. /*
  1477.  * Undo the previous edit_putchar().
  1478.  */
  1479.     void
  1480. edit_unputchar()
  1481. {
  1482.     if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled)
  1483.     {
  1484. #if defined(FEAT_MBYTE)
  1485.     if (pc_status == PC_STATUS_RIGHT)
  1486.         ++curwin->w_wcol;
  1487.     if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT)
  1488.         redrawWinline(curwin->w_cursor.lnum, FALSE);
  1489.     else
  1490. #endif
  1491.         screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
  1492.     }
  1493. }
  1494.  
  1495. /*
  1496.  * Called when p_dollar is set: display a '$' at the end of the changed text
  1497.  * Only works when cursor is in the line that changes.
  1498.  */
  1499.     void
  1500. display_dollar(col)
  1501.     colnr_T    col;
  1502. {
  1503.     colnr_T save_col;
  1504.  
  1505.     if (!redrawing())
  1506.     return;
  1507.  
  1508.     cursor_off();
  1509.     save_col = curwin->w_cursor.col;
  1510.     curwin->w_cursor.col = col;
  1511. #ifdef FEAT_MBYTE
  1512.     if (has_mbyte)
  1513.     {
  1514.     char_u *p;
  1515.  
  1516.     /* If on the last byte of a multi-byte move to the first byte. */
  1517.     p = ml_get_curline();
  1518.     curwin->w_cursor.col -= (*mb_head_off)(p, p + col);
  1519.     }
  1520. #endif
  1521.     curs_columns(FALSE);        /* recompute w_wrow and w_wcol */
  1522.     if (curwin->w_wcol < W_WIDTH(curwin))
  1523.     {
  1524.     edit_putchar('$', FALSE);
  1525.     dollar_vcol = curwin->w_virtcol;
  1526.     }
  1527.     curwin->w_cursor.col = save_col;
  1528. }
  1529.  
  1530. /*
  1531.  * Call this function before moving the cursor from the normal insert position
  1532.  * in insert mode.
  1533.  */
  1534.     static void
  1535. undisplay_dollar()
  1536. {
  1537.     if (dollar_vcol)
  1538.     {
  1539.     dollar_vcol = 0;
  1540.     redrawWinline(curwin->w_cursor.lnum, FALSE);
  1541.     }
  1542. }
  1543.  
  1544. /*
  1545.  * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
  1546.  * Keep the cursor on the same character.
  1547.  * type == INDENT_INC    increase indent (for CTRL-T or <Tab>)
  1548.  * type == INDENT_DEC    decrease indent (for CTRL-D)
  1549.  * type == INDENT_SET    set indent to "amount"
  1550.  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
  1551.  */
  1552.     void
  1553. change_indent(type, amount, round, replaced)
  1554.     int        type;
  1555.     int        amount;
  1556.     int        round;
  1557.     int        replaced;    /* replaced character, put on replace stack */
  1558. {
  1559.     int        vcol;
  1560.     int        last_vcol;
  1561.     int        insstart_less;        /* reduction for Insstart.col */
  1562.     int        new_cursor_col;
  1563.     int        i;
  1564.     char_u    *ptr;
  1565.     int        save_p_list;
  1566.     int        start_col;
  1567.     colnr_T    vc;
  1568. #ifdef FEAT_VREPLACE
  1569.     colnr_T    orig_col = 0;        /* init for GCC */
  1570.     char_u    *new_line, *orig_line = NULL;    /* init for GCC */
  1571.  
  1572.     /* VREPLACE mode needs to know what the line was like before changing */
  1573.     if (State & VREPLACE_FLAG)
  1574.     {
  1575.     orig_line = vim_strsave(ml_get_curline());  /* Deal with NULL below */
  1576.     orig_col = curwin->w_cursor.col;
  1577.     }
  1578. #endif
  1579.  
  1580.     /* for the following tricks we don't want list mode */
  1581.     save_p_list = curwin->w_p_list;
  1582.     curwin->w_p_list = FALSE;
  1583.     vc = getvcol_nolist(&curwin->w_cursor);
  1584.     vcol = vc;
  1585.  
  1586.     /*
  1587.      * For Replace mode we need to fix the replace stack later, which is only
  1588.      * possible when the cursor is in the indent.  Remember the number of
  1589.      * characters before the cursor if it's possible.
  1590.      */
  1591.     start_col = curwin->w_cursor.col;
  1592.  
  1593.     /* determine offset from first non-blank */
  1594.     new_cursor_col = curwin->w_cursor.col;
  1595.     beginline(BL_WHITE);
  1596.     new_cursor_col -= curwin->w_cursor.col;
  1597.  
  1598.     insstart_less = curwin->w_cursor.col;
  1599.  
  1600.     /*
  1601.      * If the cursor is in the indent, compute how many screen columns the
  1602.      * cursor is to the left of the first non-blank.
  1603.      */
  1604.     if (new_cursor_col < 0)
  1605.     vcol = get_indent() - vcol;
  1606.  
  1607.     if (new_cursor_col > 0)        /* can't fix replace stack */
  1608.     start_col = -1;
  1609.  
  1610.     /*
  1611.      * Set the new indent.  The cursor will be put on the first non-blank.
  1612.      */
  1613.     if (type == INDENT_SET)
  1614.     (void)set_indent(amount, SIN_CHANGED);
  1615.     else
  1616.     shift_line(type == INDENT_DEC, round, 1);
  1617.     insstart_less -= curwin->w_cursor.col;
  1618.  
  1619.     /*
  1620.      * Try to put cursor on same character.
  1621.      * If the cursor is at or after the first non-blank in the line,
  1622.      * compute the cursor column relative to the column of the first
  1623.      * non-blank character.
  1624.      * If we are not in insert mode, leave the cursor on the first non-blank.
  1625.      * If the cursor is before the first non-blank, position it relative
  1626.      * to the first non-blank, counted in screen columns.
  1627.      */
  1628.     if (new_cursor_col >= 0)
  1629.     {
  1630.     /*
  1631.      * When changing the indent while the cursor is touching it, reset
  1632.      * Insstart_col to 0.
  1633.      */
  1634.     if (new_cursor_col == 0)
  1635.         insstart_less = MAXCOL;
  1636.     new_cursor_col += curwin->w_cursor.col;
  1637.     }
  1638.     else if (!(State & INSERT))
  1639.     new_cursor_col = curwin->w_cursor.col;
  1640.     else
  1641.     {
  1642.     /*
  1643.      * Compute the screen column where the cursor should be.
  1644.      */
  1645.     vcol = get_indent() - vcol;
  1646.     curwin->w_virtcol = (vcol < 0) ? 0 : vcol;
  1647.  
  1648.     /*
  1649.      * Advance the cursor until we reach the right screen column.
  1650.      */
  1651.     vcol = last_vcol = 0;
  1652.     new_cursor_col = -1;
  1653.     ptr = ml_get_curline();
  1654.     while (vcol <= (int)curwin->w_virtcol)
  1655.     {
  1656.         last_vcol = vcol;
  1657. #ifdef FEAT_MBYTE
  1658.         if (has_mbyte && new_cursor_col >= 0)
  1659.         new_cursor_col += (*mb_ptr2len_check)(ptr + new_cursor_col);
  1660.         else
  1661. #endif
  1662.         ++new_cursor_col;
  1663.         vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol);
  1664.     }
  1665.     vcol = last_vcol;
  1666.  
  1667.     /*
  1668.      * May need to insert spaces to be able to position the cursor on
  1669.      * the right screen column.
  1670.      */
  1671.     if (vcol != (int)curwin->w_virtcol)
  1672.     {
  1673.         curwin->w_cursor.col = new_cursor_col;
  1674.         i = (int)curwin->w_virtcol - vcol;
  1675.         ptr = alloc(i + 1);
  1676.         if (ptr != NULL)
  1677.         {
  1678.         new_cursor_col += i;
  1679.         ptr[i] = NUL;
  1680.         while (--i >= 0)
  1681.             ptr[i] = ' ';
  1682.         ins_str(ptr);
  1683.         vim_free(ptr);
  1684.         }
  1685.     }
  1686.  
  1687.     /*
  1688.      * When changing the indent while the cursor is in it, reset
  1689.      * Insstart_col to 0.
  1690.      */
  1691.     insstart_less = MAXCOL;
  1692.     }
  1693.  
  1694.     curwin->w_p_list = save_p_list;
  1695.  
  1696.     if (new_cursor_col <= 0)
  1697.     curwin->w_cursor.col = 0;
  1698.     else
  1699.     curwin->w_cursor.col = new_cursor_col;
  1700.     curwin->w_set_curswant = TRUE;
  1701.     changed_cline_bef_curs();
  1702.  
  1703.     /*
  1704.      * May have to adjust the start of the insert.
  1705.      */
  1706.     if (State & INSERT)
  1707.     {
  1708.     if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
  1709.     {
  1710.         if ((int)Insstart.col <= insstart_less)
  1711.         Insstart.col = 0;
  1712.         else
  1713.         Insstart.col -= insstart_less;
  1714.     }
  1715.     if ((int)ai_col <= insstart_less)
  1716.         ai_col = 0;
  1717.     else
  1718.         ai_col -= insstart_less;
  1719.     }
  1720.  
  1721.     /*
  1722.      * For REPLACE mode, may have to fix the replace stack, if it's possible.
  1723.      * If the number of characters before the cursor decreased, need to pop a
  1724.      * few characters from the replace stack.
  1725.      * If the number of characters before the cursor increased, need to push a
  1726.      * few NULs onto the replace stack.
  1727.      */
  1728.     if (REPLACE_NORMAL(State) && start_col >= 0)
  1729.     {
  1730.     while (start_col > (int)curwin->w_cursor.col)
  1731.     {
  1732.         replace_join(0);        /* remove a NUL from the replace stack */
  1733.         --start_col;
  1734.     }
  1735.     while (start_col < (int)curwin->w_cursor.col || replaced)
  1736.     {
  1737.         replace_push(NUL);
  1738.         if (replaced)
  1739.         {
  1740.         replace_push(replaced);
  1741.         replaced = NUL;
  1742.         }
  1743.         ++start_col;
  1744.     }
  1745.     }
  1746.  
  1747. #ifdef FEAT_VREPLACE
  1748.     /*
  1749.      * For VREPLACE mode, we also have to fix the replace stack.  In this case
  1750.      * it is always possible because we backspace over the whole line and then
  1751.      * put it back again the way we wanted it.
  1752.      */
  1753.     if (State & VREPLACE_FLAG)
  1754.     {
  1755.     /* If orig_line didn't allocate, just return.  At least we did the job,
  1756.      * even if you can't backspace.
  1757.      */
  1758.     if (orig_line == NULL)
  1759.         return;
  1760.  
  1761.     /* Save new line */
  1762.     new_line = vim_strsave(ml_get_curline());
  1763.     if (new_line == NULL)
  1764.         return;
  1765.  
  1766.     /* We only put back the new line up to the cursor */
  1767.     new_line[curwin->w_cursor.col] = NUL;
  1768.  
  1769.     /* Put back original line */
  1770.     ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
  1771.     curwin->w_cursor.col = orig_col;
  1772.  
  1773.     /* Backspace from cursor to start of line */
  1774.     backspace_until_column(0);
  1775.  
  1776.     /* Insert new stuff into line again */
  1777.     ins_bytes(new_line);
  1778.  
  1779.     vim_free(new_line);
  1780.     }
  1781. #endif
  1782. }
  1783.  
  1784. /*
  1785.  * Truncate the space at the end of a line.  This is to be used only in an
  1786.  * insert mode.  It handles fixing the replace stack for REPLACE and VREPLACE
  1787.  * modes.
  1788.  */
  1789.     void
  1790. truncate_spaces(line)
  1791.     char_u  *line;
  1792. {
  1793.     int        i;
  1794.  
  1795.     /* find start of trailing white space */
  1796.     for (i = (int)STRLEN(line) - 1; i >= 0 && vim_iswhite(line[i]); i--)
  1797.     {
  1798.     if (State & REPLACE_FLAG)
  1799.         replace_join(0);        /* remove a NUL from the replace stack */
  1800.     }
  1801.     line[i + 1] = NUL;
  1802. }
  1803.  
  1804. #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
  1805.     || defined(FEAT_COMMENTS) || defined(PROTO)
  1806. /*
  1807.  * Backspace the cursor until the given column.  Handles REPLACE and VREPLACE
  1808.  * modes correctly.  May also be used when not in insert mode at all.
  1809.  */
  1810.     void
  1811. backspace_until_column(col)
  1812.     int        col;
  1813. {
  1814.     while ((int)curwin->w_cursor.col > col)
  1815.     {
  1816.     curwin->w_cursor.col--;
  1817.     if (State & REPLACE_FLAG)
  1818.         replace_do_bs();
  1819.     else
  1820.         (void)del_char(FALSE);
  1821.     }
  1822. }
  1823. #endif
  1824.  
  1825. #if defined(FEAT_INS_EXPAND) || defined(PROTO)
  1826. /*
  1827.  * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
  1828.  * This depends on the current mode.
  1829.  */
  1830.     int
  1831. vim_is_ctrl_x_key(c)
  1832.     int        c;
  1833. {
  1834.     /* Always allow ^R - let it's results then be checked */
  1835.     if (c == Ctrl_R)
  1836.     return TRUE;
  1837.  
  1838.     switch (ctrl_x_mode)
  1839.     {
  1840.     case 0:            /* Not in any CTRL-X mode */
  1841.         return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
  1842.     case CTRL_X_NOT_DEFINED_YET:
  1843.         return (       c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
  1844.             || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
  1845.             || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
  1846.             || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
  1847.             || c == Ctrl_Q);
  1848.     case CTRL_X_SCROLL:
  1849.         return (c == Ctrl_Y || c == Ctrl_E);
  1850.     case CTRL_X_WHOLE_LINE:
  1851.         return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
  1852.     case CTRL_X_FILES:
  1853.         return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
  1854.     case CTRL_X_DICTIONARY:
  1855.         return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
  1856.     case CTRL_X_THESAURUS:
  1857.         return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
  1858.     case CTRL_X_TAGS:
  1859.         return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
  1860. #ifdef FEAT_FIND_ID
  1861.     case CTRL_X_PATH_PATTERNS:
  1862.         return (c == Ctrl_P || c == Ctrl_N);
  1863.     case CTRL_X_PATH_DEFINES:
  1864.         return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
  1865. #endif
  1866.     case CTRL_X_CMDLINE:
  1867.         return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
  1868.             || c == Ctrl_X);
  1869.     }
  1870.     EMSG(_(e_internal));
  1871.     return FALSE;
  1872. }
  1873.  
  1874. /*
  1875.  * This is like ins_compl_add(), but if ic and inf are set, then the
  1876.  * case of the originally typed text is used, and the case of the completed
  1877.  * text is infered, ie this tries to work out what case you probably wanted
  1878.  * the rest of the word to be in -- webb
  1879.  */
  1880.     int
  1881. ins_compl_add_infercase(str, len, fname, dir, reuse)
  1882.     char_u    *str;
  1883.     int        len;
  1884.     char_u    *fname;
  1885.     int        dir;
  1886.     int        reuse;
  1887. {
  1888.     int        has_lower = FALSE;
  1889.     int        was_letter = FALSE;
  1890.     int        idx;
  1891.  
  1892.     if (p_ic && curbuf->b_p_inf && len < IOSIZE)
  1893.     {
  1894.     /* Infer case of completed part -- webb */
  1895.     /* Use IObuff, str would change text in buffer! */
  1896.     STRNCPY(IObuff, str, len);
  1897.     IObuff[len] = NUL;
  1898.  
  1899.     /* Rule 1: Were any chars converted to lower? */
  1900.     for (idx = 0; idx < completion_length; ++idx)
  1901.     {
  1902.         if (islower(original_text[idx]))
  1903.         {
  1904.         has_lower = TRUE;
  1905.         if (isupper(IObuff[idx]))
  1906.         {
  1907.             /* Rule 1 is satisfied */
  1908.             for (idx = completion_length; idx < len; ++idx)
  1909.             IObuff[idx] = TOLOWER_LOC(IObuff[idx]);
  1910.             break;
  1911.         }
  1912.         }
  1913.     }
  1914.  
  1915.     /*
  1916.      * Rule 2: No lower case, 2nd consecutive letter converted to
  1917.      * upper case.
  1918.      */
  1919.     if (!has_lower)
  1920.     {
  1921.         for (idx = 0; idx < completion_length; ++idx)
  1922.         {
  1923.         if (was_letter && isupper(original_text[idx])
  1924.                               && islower(IObuff[idx]))
  1925.         {
  1926.             /* Rule 2 is satisfied */
  1927.             for (idx = completion_length; idx < len; ++idx)
  1928.             IObuff[idx] = TOUPPER_LOC(IObuff[idx]);
  1929.             break;
  1930.         }
  1931.         was_letter = isalpha(original_text[idx]);
  1932.         }
  1933.     }
  1934.  
  1935.     /* Copy the original case of the part we typed */
  1936.     STRNCPY(IObuff, original_text, completion_length);
  1937.  
  1938.     return ins_compl_add(IObuff, len, fname, dir, reuse);
  1939.     }
  1940.     return ins_compl_add(str, len, fname, dir, reuse);
  1941. }
  1942.  
  1943. /*
  1944.  * Add a match to the list of matches.
  1945.  * If the given string is already in the list of completions, then return
  1946.  * FAIL, otherwise add it to the list and return OK.  If there is an error,
  1947.  * maybe because alloc returns NULL, then RET_ERROR is returned -- webb.
  1948.  */
  1949.     static int
  1950. ins_compl_add(str, len, fname, dir, reuse)
  1951.     char_u    *str;
  1952.     int        len;
  1953.     char_u    *fname;
  1954.     int        dir;
  1955.     int        reuse;
  1956. {
  1957.     struct Completion *match;
  1958.  
  1959.     ui_breakcheck();
  1960.     if (got_int)
  1961.     return RET_ERROR;
  1962.     if (len < 0)
  1963.     len = (int)STRLEN(str);
  1964.  
  1965.     /*
  1966.      * If the same match is already present, don't add it.
  1967.      */
  1968.     if (first_match != NULL)
  1969.     {
  1970.     match = first_match;
  1971.     do
  1972.     {
  1973.         if (    !(match->original & ORIGINAL_TEXT)
  1974.             && STRNCMP(match->str, str, (size_t)len) == 0
  1975.             && match->str[len] == NUL)
  1976.         return FAIL;
  1977.         match = match->next;
  1978.     } while (match != NULL && match != first_match);
  1979.     }
  1980.  
  1981.     /*
  1982.      * Allocate a new match structure.
  1983.      * Copy the values to the new match structure.
  1984.      */
  1985.     match = (struct Completion *)alloc((unsigned)sizeof(struct Completion));
  1986.     if (match == NULL)
  1987.     return RET_ERROR;
  1988.     match->number = -1;
  1989.     if (reuse & ORIGINAL_TEXT)
  1990.     {
  1991.     match->number = 0;
  1992.     match->str = original_text;
  1993.     }
  1994.     else if ((match->str = vim_strnsave(str, len)) == NULL)
  1995.     {
  1996.     vim_free(match);
  1997.     return RET_ERROR;
  1998.     }
  1999.     /* match-fname is:
  2000.      * - curr_match->fname if it is a string equal to fname.
  2001.      * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
  2002.      * - NULL otherwise.    --Acevedo */
  2003.     if (fname && curr_match && curr_match->fname
  2004.           && STRCMP(fname, curr_match->fname) == 0)
  2005.     match->fname = curr_match->fname;
  2006.     else if (fname && (match->fname = vim_strsave(fname)) != NULL)
  2007.     reuse |= FREE_FNAME;
  2008.     else
  2009.     match->fname = NULL;
  2010.     match->original = reuse;
  2011.  
  2012.     /*
  2013.      * Link the new match structure in the list of matches.
  2014.      */
  2015.     if (first_match == NULL)
  2016.     match->next = match->prev = NULL;
  2017.     else if (dir == FORWARD)
  2018.     {
  2019.     match->next = curr_match->next;
  2020.     match->prev = curr_match;
  2021.     }
  2022.     else    /* BACKWARD */
  2023.     {
  2024.     match->next = curr_match;
  2025.     match->prev = curr_match->prev;
  2026.     }
  2027.     if (match->next)
  2028.     match->next->prev = match;
  2029.     if (match->prev)
  2030.     match->prev->next = match;
  2031.     else    /* if there's nothing before, it is the first match */
  2032.     first_match = match;
  2033.     curr_match = match;
  2034.  
  2035.     return OK;
  2036. }
  2037.  
  2038. /*
  2039.  * Add an array of matches to the list of matches.
  2040.  * Frees matches[].
  2041.  */
  2042.     static void
  2043. ins_compl_add_matches(num_matches, matches, dir)
  2044.     int        num_matches;
  2045.     char_u    **matches;
  2046.     int        dir;
  2047. {
  2048.     int        i;
  2049.     int        add_r = OK;
  2050.     int        ldir = dir;
  2051.  
  2052.     for (i = 0; i < num_matches && add_r != RET_ERROR; i++)
  2053.     if ((add_r = ins_compl_add(matches[i], -1, NULL, ldir, 0)) == OK)
  2054.         /* if dir was BACKWARD then honor it just once */
  2055.         ldir = FORWARD;
  2056.     FreeWild(num_matches, matches);
  2057. }
  2058.  
  2059. /* Make the completion list cyclic.
  2060.  * Return the number of matches (excluding the original).
  2061.  */
  2062.     static int
  2063. ins_compl_make_cyclic()
  2064. {
  2065.     struct Completion *match;
  2066.     int        count = 0;
  2067.  
  2068.     if (first_match != NULL)
  2069.     {
  2070.     /*
  2071.      * Find the end of the list.
  2072.      */
  2073.     match = first_match;
  2074.     /* there's always an entry for the original_text, it doesn't count. */
  2075.     while (match->next != NULL && match->next != first_match)
  2076.     {
  2077.         match = match->next;
  2078.         ++count;
  2079.     }
  2080.     match->next = first_match;
  2081.     first_match->prev = match;
  2082.     }
  2083.     return count;
  2084. }
  2085.  
  2086. #define DICT_FIRST    (1)    /* use just first element in "dict" */
  2087. #define DICT_EXACT    (2)    /* "dict" is the exact name of a file */
  2088. /*
  2089.  * Add any identifiers that match the given pattern to the list of
  2090.  * completions.
  2091.  */
  2092.     static void
  2093. ins_compl_dictionaries(dict, pat, dir, flags, thesaurus)
  2094.     char_u    *dict;
  2095.     char_u    *pat;
  2096.     int        dir;
  2097.     int        flags;
  2098.     int        thesaurus;
  2099. {
  2100.     char_u    *ptr;
  2101.     char_u    *buf;
  2102.     FILE    *fp;
  2103.     regmatch_T    regmatch;
  2104.     int        add_r;
  2105.     char_u    **files;
  2106.     int        count;
  2107.     int        i;
  2108.     int        save_p_scs;
  2109.  
  2110.     buf = alloc(LSIZE);
  2111.     /* If 'infercase' is set, don't use 'smartcase' here */
  2112.     save_p_scs = p_scs;
  2113.     if (curbuf->b_p_inf)
  2114.     p_scs = FALSE;
  2115.     regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
  2116.     /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
  2117.     regmatch.rm_ic = ignorecase(pat);
  2118.     while (buf != NULL && regmatch.regprog != NULL && *dict != NUL
  2119.                && !got_int && !completion_interrupted)
  2120.     {
  2121.     /* copy one dictionary file name into buf */
  2122.     if (flags == DICT_EXACT)
  2123.     {
  2124.         count = 1;
  2125.         files = &dict;
  2126.     }
  2127.     else
  2128.     {
  2129.         /* Expand wildcards in the dictionary name, but do not allow
  2130.          * backticks (for security, the 'dict' option may have been set in
  2131.          * a modeline). */
  2132.         copy_option_part(&dict, buf, LSIZE, ",");
  2133.         if (vim_strchr(buf, '`') != NULL
  2134.             || expand_wildcards(1, &buf, &count, &files,
  2135.                              EW_FILE|EW_SILENT) != OK)
  2136.         count = 0;
  2137.     }
  2138.  
  2139.     for (i = 0; i < count && !got_int && !completion_interrupted; i++)
  2140.     {
  2141.         fp = mch_fopen((char *)files[i], "r");  /* open dictionary file */
  2142.         if (flags != DICT_EXACT)
  2143.         {
  2144.         sprintf((char*)IObuff, _("Scanning dictionary: %s"),
  2145.                                 (char *)files[i]);
  2146.         msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  2147.         }
  2148.  
  2149.         if (fp != NULL)
  2150.         {
  2151.         /*
  2152.          * Read dictionary file line by line.
  2153.          * Check each line for a match.
  2154.          */
  2155.         while (!got_int && !completion_interrupted
  2156.                 && !vim_fgets(buf, LSIZE, fp))
  2157.         {
  2158.             ptr = buf;
  2159.             while (vim_regexec(®match, buf, (colnr_T)(ptr - buf)))
  2160.             {
  2161.             ptr = regmatch.startp[0];
  2162.             ptr = find_word_end(ptr);
  2163.             add_r = ins_compl_add_infercase(regmatch.startp[0],
  2164.                           (int)(ptr - regmatch.startp[0]),
  2165.                                 files[i], dir, 0);
  2166.             if (thesaurus)
  2167.             {
  2168.                 char_u *wstart;
  2169.  
  2170.                 /*
  2171.                  * Add the other matches on the line
  2172.                  */
  2173.                 while (!got_int)
  2174.                 {
  2175.                 /* Find start of the next word.  Skip white
  2176.                  * space and punctuation. */
  2177.                 ptr = find_word_start(ptr);
  2178.                 if (*ptr == NUL || *ptr == NL)
  2179.                     break;
  2180.                 wstart = ptr;
  2181.  
  2182.                 /* Find end of the word and add it. */
  2183. #ifdef FEAT_MBYTE
  2184.                 if (has_mbyte)
  2185.                     /* Japanese words may have characters in
  2186.                      * different classes, only separate words
  2187.                      * with single-byte non-word characters. */
  2188.                     while (*ptr != NUL)
  2189.                     {
  2190.                     int l = (*mb_ptr2len_check)(ptr);
  2191.  
  2192.                     if (l < 2 && !vim_iswordc(*ptr))
  2193.                         break;
  2194.                     ptr += l;
  2195.                     }
  2196.                 else
  2197. #endif
  2198.                     ptr = find_word_end(ptr);
  2199.                 add_r = ins_compl_add_infercase(wstart,
  2200.                     (int)(ptr - wstart), files[i], dir, 0);
  2201.                 }
  2202.             }
  2203.             if (add_r == OK)
  2204.                 /* if dir was BACKWARD then honor it just once */
  2205.                 dir = FORWARD;
  2206.             else if (add_r == RET_ERROR)
  2207.                 break;
  2208.             /* avoid expensive call to vim_regexec() when at end
  2209.              * of line */
  2210.             if (*ptr == '\n' || got_int)
  2211.                 break;
  2212.             }
  2213.             line_breakcheck();
  2214.             ins_compl_check_keys();
  2215.         }
  2216.         fclose(fp);
  2217.         }
  2218.     }
  2219.     if (flags != DICT_EXACT)
  2220.         FreeWild(count, files);
  2221.     if (flags)
  2222.         break;
  2223.     }
  2224.     p_scs = save_p_scs;
  2225.     vim_free(regmatch.regprog);
  2226.     vim_free(buf);
  2227. }
  2228.  
  2229. /*
  2230.  * Find the start of the next word.
  2231.  * Returns a pointer to the first char of the word.  Also stops at a NUL.
  2232.  */
  2233.     char_u *
  2234. find_word_start(ptr)
  2235.     char_u    *ptr;
  2236. {
  2237. #ifdef FEAT_MBYTE
  2238.     if (has_mbyte)
  2239.     while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
  2240.         ptr += (*mb_ptr2len_check)(ptr);
  2241.     else
  2242. #endif
  2243.     while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
  2244.         ++ptr;
  2245.     return ptr;
  2246. }
  2247.  
  2248. /*
  2249.  * Find the end of the word.  Assumes it starts inside a word.
  2250.  * Returns a pointer to just after the word.
  2251.  */
  2252.     char_u *
  2253. find_word_end(ptr)
  2254.     char_u    *ptr;
  2255. {
  2256. #ifdef FEAT_MBYTE
  2257.     int        start_class;
  2258.  
  2259.     if (has_mbyte)
  2260.     {
  2261.     start_class = mb_get_class(ptr);
  2262.     if (start_class > 1)
  2263.         while (*ptr != NUL)
  2264.         {
  2265.         ptr += (*mb_ptr2len_check)(ptr);
  2266.         if (mb_get_class(ptr) != start_class)
  2267.             break;
  2268.         }
  2269.     }
  2270.     else
  2271. #endif
  2272.     while (vim_iswordc(*ptr))
  2273.         ++ptr;
  2274.     return ptr;
  2275. }
  2276.  
  2277. /*
  2278.  * Free the list of completions
  2279.  */
  2280.     static void
  2281. ins_compl_free()
  2282. {
  2283.     struct Completion *match;
  2284.  
  2285.     vim_free(complete_pat);
  2286.     complete_pat = NULL;
  2287.  
  2288.     if (first_match == NULL)
  2289.     return;
  2290.     curr_match = first_match;
  2291.     do
  2292.     {
  2293.     match = curr_match;
  2294.     curr_match = curr_match->next;
  2295.     vim_free(match->str);
  2296.     /* several entries may use the same fname, free it just once. */
  2297.     if (match->original & FREE_FNAME)
  2298.         vim_free(match->fname);
  2299.     vim_free(match);
  2300.     } while (curr_match != NULL && curr_match != first_match);
  2301.     first_match = curr_match = NULL;
  2302. }
  2303.  
  2304.     static void
  2305. ins_compl_clear()
  2306. {
  2307.     continue_status = 0;
  2308.     started_completion = FALSE;
  2309.     completion_matches = 0;
  2310.     vim_free(complete_pat);
  2311.     complete_pat = NULL;
  2312.     save_sm = -1;
  2313.     edit_submode_extra = NULL;
  2314. }
  2315.  
  2316. /*
  2317.  * Prepare for Insert mode completion, or stop it.
  2318.  */
  2319.     static void
  2320. ins_compl_prep(c)
  2321.     int        c;
  2322. {
  2323.     char_u    *ptr;
  2324.     char_u    *tmp_ptr;
  2325.     int        temp;
  2326.     int        want_cindent;
  2327.  
  2328.     /* Forget any previous 'special' messages if this is actually
  2329.      * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
  2330.      */
  2331.     if (c != Ctrl_R && vim_is_ctrl_x_key(c))
  2332.     edit_submode_extra = NULL;
  2333.  
  2334.     /* Ignore end of Select mode mapping */
  2335.     if (c == K_SELECT)
  2336.     return;
  2337.  
  2338.     if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
  2339.     {
  2340.     /*
  2341.      * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
  2342.      * it will be yet.  Now we decide.
  2343.      */
  2344.     switch (c)
  2345.     {
  2346.         case Ctrl_E:
  2347.         case Ctrl_Y:
  2348.         ctrl_x_mode = CTRL_X_SCROLL;
  2349.         if (!(State & REPLACE_FLAG))
  2350.             edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
  2351.         else
  2352.             edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
  2353.         edit_submode_pre = NULL;
  2354.         showmode();
  2355.         break;
  2356.         case Ctrl_L:
  2357.         ctrl_x_mode = CTRL_X_WHOLE_LINE;
  2358.         break;
  2359.         case Ctrl_F:
  2360.         ctrl_x_mode = CTRL_X_FILES;
  2361.         break;
  2362.         case Ctrl_K:
  2363.         ctrl_x_mode = CTRL_X_DICTIONARY;
  2364.         break;
  2365.         case Ctrl_R:
  2366.         /* Simply allow ^R to happen without affecting ^X mode */
  2367.         break;
  2368.         case Ctrl_T:
  2369.         ctrl_x_mode = CTRL_X_THESAURUS;
  2370.         break;
  2371.         case Ctrl_RSB:
  2372.         ctrl_x_mode = CTRL_X_TAGS;
  2373.         break;
  2374. #ifdef FEAT_FIND_ID
  2375.         case Ctrl_I:
  2376.         case K_S_TAB:
  2377.         ctrl_x_mode = CTRL_X_PATH_PATTERNS;
  2378.         break;
  2379.         case Ctrl_D:
  2380.         ctrl_x_mode = CTRL_X_PATH_DEFINES;
  2381.         break;
  2382. #endif
  2383.         case Ctrl_V:
  2384.         case Ctrl_Q:
  2385.         ctrl_x_mode = CTRL_X_CMDLINE;
  2386.         break;
  2387.         case Ctrl_P:
  2388.         case Ctrl_N:
  2389.         /* ^X^P means LOCAL expansion if nothing interrupted (eg we
  2390.          * just started ^X mode, or there were enough ^X's to cancel
  2391.          * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
  2392.          * do normal expansion when interrupting a different mode (say
  2393.          * ^X^F^X^P or ^P^X^X^P, see below)
  2394.          * nothing changes if interrupting mode 0, (eg, the flag
  2395.          * doesn't change when going to ADDING mode  -- Acevedo */
  2396.         if (!(continue_status & CONT_INTRPT))
  2397.             continue_status |= CONT_LOCAL;
  2398.         else if (continue_mode != 0)
  2399.             continue_status &= ~CONT_LOCAL;
  2400.         /* FALLTHROUGH */
  2401.         default:
  2402.         /* if we have typed at least 2 ^X's... for modes != 0, we set
  2403.          * continue_status = 0 (eg, as if we had just started ^X mode)
  2404.          * for mode 0, we set continue_mode to an impossible value, in
  2405.          * both cases ^X^X can be used to restart the same mode
  2406.          * (avoiding ADDING mode).   Undocumented feature:
  2407.          * In a mode != 0 ^X^P and ^X^X^P start 'complete' and local
  2408.          * ^P expansions respectively.    In mode 0 an extra ^X is
  2409.          * needed since ^X^P goes to ADDING mode  -- Acevedo */
  2410.         if (c == Ctrl_X)
  2411.         {
  2412.             if (continue_mode != 0)
  2413.             continue_status = 0;
  2414.             else
  2415.             continue_mode = CTRL_X_NOT_DEFINED_YET;
  2416.         }
  2417.         ctrl_x_mode = 0;
  2418.         edit_submode = NULL;
  2419.         showmode();
  2420.         break;
  2421.     }
  2422.     }
  2423.     else if (ctrl_x_mode != 0)
  2424.     {
  2425.     /* We're already in CTRL-X mode, do we stay in it? */
  2426.     if (!vim_is_ctrl_x_key(c))
  2427.     {
  2428.         if (ctrl_x_mode == CTRL_X_SCROLL)
  2429.         ctrl_x_mode = 0;
  2430.         else
  2431.         ctrl_x_mode = CTRL_X_FINISHED;
  2432.         edit_submode = NULL;
  2433.     }
  2434.     showmode();
  2435.     }
  2436.  
  2437.     if (started_completion || ctrl_x_mode == CTRL_X_FINISHED)
  2438.     {
  2439.     /* Show error message from attempted keyword completion (probably
  2440.      * 'Pattern not found') until another key is hit, then go back to
  2441.      * showing what mode we are in.
  2442.      */
  2443.     showmode();
  2444.     if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R)
  2445.         || ctrl_x_mode == CTRL_X_FINISHED)
  2446.     {
  2447.         /* Get here when we have finished typing a sequence of ^N and
  2448.          * ^P or other completion characters in CTRL-X mode.  Free up
  2449.          * memory that was used, and make sure we can redo the insert.
  2450.          */
  2451.         if (curr_match != NULL)
  2452.         {
  2453.         /*
  2454.          * If any of the original typed text has been changed,
  2455.          * eg when ignorecase is set, we must add back-spaces to
  2456.          * the redo buffer.  We add as few as necessary to delete
  2457.          * just the part of the original text that has changed.
  2458.          */
  2459.         ptr = curr_match->str;
  2460.         tmp_ptr = original_text;
  2461.         while (*tmp_ptr && *tmp_ptr == *ptr)
  2462.         {
  2463.             ++tmp_ptr;
  2464.             ++ptr;
  2465.         }
  2466.         for (temp = 0; tmp_ptr[temp]; ++temp)
  2467.             AppendCharToRedobuff(K_BS);
  2468.         AppendToRedobuffLit(ptr);
  2469.         }
  2470.  
  2471. #ifdef FEAT_CINDENT
  2472.         want_cindent = (can_cindent && cindent_on());
  2473. #endif
  2474.         /*
  2475.          * When completing whole lines: fix indent for 'cindent'.
  2476.          * Otherwise, break line if it's too long.
  2477.          */
  2478.         if (continue_mode == CTRL_X_WHOLE_LINE)
  2479.         {
  2480. #ifdef FEAT_CINDENT
  2481.         /* re-indent the current line */
  2482.         if (want_cindent)
  2483.         {
  2484.             do_c_expr_indent();
  2485.             want_cindent = FALSE;    /* don't do it again */
  2486.         }
  2487. #endif
  2488.         }
  2489.         else
  2490.         {
  2491.         /* put the cursor on the last char, for 'tw' formatting */
  2492.         curwin->w_cursor.col--;
  2493.         if (stop_arrow() == OK)
  2494.             insertchar(NUL, 0, -1);
  2495.         curwin->w_cursor.col++;
  2496.         }
  2497.  
  2498.         auto_format();
  2499.  
  2500.         ins_compl_free();
  2501.         started_completion = FALSE;
  2502.         completion_matches = 0;
  2503.         msg_clr_cmdline();        /* necessary for "noshowmode" */
  2504.         ctrl_x_mode = 0;
  2505.         p_sm = save_sm;
  2506.         if (edit_submode != NULL)
  2507.         {
  2508.         edit_submode = NULL;
  2509.         showmode();
  2510.         }
  2511.  
  2512. #ifdef FEAT_CINDENT
  2513.         /*
  2514.          * Indent now if a key was typed that is in 'cinkeys'.
  2515.          */
  2516.         if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
  2517.         do_c_expr_indent();
  2518. #endif
  2519.     }
  2520.     }
  2521.  
  2522.     /* reset continue_* if we left expansion-mode, if we stay they'll be
  2523.      * (re)set properly in ins_complete() */
  2524.     if (!vim_is_ctrl_x_key(c))
  2525.     {
  2526.     continue_status = 0;
  2527.     continue_mode = 0;
  2528.     }
  2529. }
  2530.  
  2531. /*
  2532.  * Loops through the list of windows, loaded-buffers or non-loaded-buffers
  2533.  * (depending on flag) starting from buf and looking for a non-scanned
  2534.  * buffer (other than curbuf).    curbuf is special, if it is called with
  2535.  * buf=curbuf then it has to be the first call for a given flag/expansion.
  2536.  *
  2537.  * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
  2538.  */
  2539.     static buf_T *
  2540. ins_compl_next_buf(buf, flag)
  2541.     buf_T    *buf;
  2542.     int        flag;
  2543. {
  2544. #ifdef FEAT_WINDOWS
  2545.     static win_T *wp;
  2546. #endif
  2547.  
  2548.     if (flag == 'w')        /* just windows */
  2549.     {
  2550. #ifdef FEAT_WINDOWS
  2551.     if (buf == curbuf)    /* first call for this flag/expansion */
  2552.         wp = curwin;
  2553.     while ((wp = wp->w_next != NULL ? wp->w_next : firstwin) != curwin
  2554.         && wp->w_buffer->b_scanned)
  2555.         ;
  2556.     buf = wp->w_buffer;
  2557. #else
  2558.     buf = curbuf;
  2559. #endif
  2560.     }
  2561.     else
  2562.     /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
  2563.      * (unlisted buffers)
  2564.      * When completing whole lines skip unloaded buffers. */
  2565.     while ((buf = buf->b_next != NULL ? buf->b_next : firstbuf) != curbuf
  2566.         && ((flag == 'U'
  2567.             ? buf->b_p_bl
  2568.             : (!buf->b_p_bl
  2569.                 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
  2570.             || buf->b_scanned
  2571.             || (buf->b_ml.ml_mfp == NULL
  2572.             && ctrl_x_mode == CTRL_X_WHOLE_LINE)))
  2573.         ;
  2574.     return buf;
  2575. }
  2576.  
  2577. /*
  2578.  * Get the next expansion(s) for the text starting at the initial curbuf
  2579.  * position "ini" and in the direction dir.
  2580.  * Return the total of matches or -1 if still unknown -- Acevedo
  2581.  */
  2582.     static int
  2583. ins_compl_get_exp(ini, dir)
  2584.     pos_T    *ini;
  2585.     int        dir;
  2586. {
  2587.     static pos_T    first_match_pos;
  2588.     static pos_T    last_match_pos;
  2589.     static char_u    *e_cpt = (char_u *)"";    /* curr. entry in 'complete' */
  2590.     static int        found_all = FALSE;    /* Found all matches. */
  2591.     static buf_T    *ins_buf = NULL;
  2592.  
  2593.     pos_T        *pos;
  2594.     char_u        **matches;
  2595.     int            save_p_scs;
  2596.     int            save_p_ws;
  2597.     int            save_p_ic;
  2598.     int            i;
  2599.     int            num_matches;
  2600.     int            len;
  2601.     int            found_new_match;
  2602.     int            type = ctrl_x_mode;
  2603.     char_u        *ptr;
  2604.     char_u        *tmp_ptr;
  2605.     char_u        *dict = NULL;
  2606.     int            dict_f = 0;
  2607.     struct Completion    *old_match;
  2608.  
  2609.     if (!started_completion)
  2610.     {
  2611.     for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next)
  2612.         ins_buf->b_scanned = 0;
  2613.     found_all = FALSE;
  2614.     ins_buf = curbuf;
  2615.     e_cpt = continue_status & CONT_LOCAL ? (char_u *)"." : curbuf->b_p_cpt;
  2616.     last_match_pos = first_match_pos = *ini;
  2617.     }
  2618.  
  2619.     old_match = curr_match;        /* remember the last current match */
  2620.     pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos;
  2621.     /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
  2622.     for (;;)
  2623.     {
  2624.     found_new_match = FAIL;
  2625.  
  2626.     /* For ^N/^P pick a new entry from e_cpt if started_completion is off,
  2627.      * or if found_all says this entry is done.  For ^X^L only use the
  2628.      * entries from 'complete' that look in loaded buffers. */
  2629.     if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2630.         && (!started_completion || found_all))
  2631.     {
  2632.         found_all = FALSE;
  2633.         while (*e_cpt == ',' || *e_cpt == ' ')
  2634.         e_cpt++;
  2635.         if (*e_cpt == '.' && !curbuf->b_scanned)
  2636.         {
  2637.         ins_buf = curbuf;
  2638.         first_match_pos = *ini;
  2639.         /* So that ^N can match word immediately after cursor */
  2640.         if (ctrl_x_mode == 0)
  2641.             dec(&first_match_pos);
  2642.         last_match_pos = first_match_pos;
  2643.         type = 0;
  2644.         }
  2645.         else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
  2646.          && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
  2647.         {
  2648.         /* Scan a buffer, but not the current one. */
  2649.         if (ins_buf->b_ml.ml_mfp != NULL)   /* loaded buffer */
  2650.         {
  2651.             started_completion = TRUE;
  2652.             first_match_pos.col = last_match_pos.col = 0;
  2653.             first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
  2654.             last_match_pos.lnum = 0;
  2655.             type = 0;
  2656.         }
  2657.         else    /* unloaded buffer, scan like dictionary */
  2658.         {
  2659.             found_all = TRUE;
  2660.             if (ins_buf->b_fname == NULL)
  2661.             continue;
  2662.             type = CTRL_X_DICTIONARY;
  2663.             dict = ins_buf->b_fname;
  2664.             dict_f = DICT_EXACT;
  2665.         }
  2666.         sprintf((char *)IObuff, _("Scanning: %s"),
  2667.             ins_buf->b_fname == NULL
  2668.                 ? buf_spname(ins_buf)
  2669.                 : ins_buf->b_sfname == NULL
  2670.                 ? (char *)ins_buf->b_fname
  2671.                 : (char *)ins_buf->b_sfname);
  2672.         msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  2673.         }
  2674.         else if (*e_cpt == NUL)
  2675.         break;
  2676.         else
  2677.         {
  2678.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2679.             type = -1;
  2680.         else if (*e_cpt == 'k' || *e_cpt == 's')
  2681.         {
  2682.             if (*e_cpt == 'k')
  2683.             type = CTRL_X_DICTIONARY;
  2684.             else
  2685.             type = CTRL_X_THESAURUS;
  2686.             if (*++e_cpt != ',' && *e_cpt != NUL)
  2687.             {
  2688.             dict = e_cpt;
  2689.             dict_f = DICT_FIRST;
  2690.             }
  2691.         }
  2692. #ifdef FEAT_FIND_ID
  2693.         else if (*e_cpt == 'i')
  2694.             type = CTRL_X_PATH_PATTERNS;
  2695.         else if (*e_cpt == 'd')
  2696.             type = CTRL_X_PATH_DEFINES;
  2697. #endif
  2698.         else if (*e_cpt == ']' || *e_cpt == 't')
  2699.         {
  2700.             type = CTRL_X_TAGS;
  2701.             sprintf((char*)IObuff, _("Scanning tags."));
  2702.             msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  2703.         }
  2704.         else
  2705.             type = -1;
  2706.  
  2707.         /* in any case e_cpt is advanced to the next entry */
  2708.         (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
  2709.  
  2710.         found_all = TRUE;
  2711.         if (type == -1)
  2712.             continue;
  2713.         }
  2714.     }
  2715.  
  2716.     switch (type)
  2717.     {
  2718.     case -1:
  2719.         break;
  2720. #ifdef FEAT_FIND_ID
  2721.     case CTRL_X_PATH_PATTERNS:
  2722.     case CTRL_X_PATH_DEFINES:
  2723.         find_pattern_in_path(complete_pat, dir,
  2724.                  (int)STRLEN(complete_pat), FALSE, FALSE,
  2725.                  (type == CTRL_X_PATH_DEFINES
  2726.                   && !(continue_status & CONT_SOL))
  2727.                  ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
  2728.                  (linenr_T)1, (linenr_T)MAXLNUM);
  2729.         break;
  2730. #endif
  2731.  
  2732.     case CTRL_X_DICTIONARY:
  2733.     case CTRL_X_THESAURUS:
  2734.         ins_compl_dictionaries(
  2735.             dict ? dict
  2736.              : (type == CTRL_X_THESAURUS
  2737.                  ? (*curbuf->b_p_tsr == NUL
  2738.                  ? p_tsr
  2739.                  : curbuf->b_p_tsr)
  2740.                  : (*curbuf->b_p_dict == NUL
  2741.                  ? p_dict
  2742.                  : curbuf->b_p_dict)),
  2743.                 complete_pat, dir,
  2744.                  dict ? dict_f : 0, type == CTRL_X_THESAURUS);
  2745.         dict = NULL;
  2746.         break;
  2747.  
  2748.     case CTRL_X_TAGS:
  2749.         /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
  2750.         save_p_ic = p_ic;
  2751.         p_ic = ignorecase(complete_pat);
  2752.  
  2753.         /* Find up to TAG_MANY matches.  Avoids that an enourmous number
  2754.          * of matches is found when complete_pat is empty */
  2755.         if (find_tags(complete_pat, &num_matches, &matches,
  2756.             TAG_REGEXP | TAG_NAMES | TAG_NOIC |
  2757.             TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
  2758.             TAG_MANY) == OK && num_matches > 0)
  2759.         {
  2760.         ins_compl_add_matches(num_matches, matches, dir);
  2761.         }
  2762.         p_ic = save_p_ic;
  2763.         break;
  2764.  
  2765.     case CTRL_X_FILES:
  2766.         if (expand_wildcards(1, &complete_pat, &num_matches, &matches,
  2767.                   EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
  2768.         {
  2769.  
  2770.         /* May change home directory back to "~". */
  2771.         tilde_replace(complete_pat, num_matches, matches);
  2772.         ins_compl_add_matches(num_matches, matches, dir);
  2773.         }
  2774.         break;
  2775.  
  2776.     case CTRL_X_CMDLINE:
  2777.         if (expand_cmdline(&complete_xp, complete_pat,
  2778.             (int)STRLEN(complete_pat),
  2779.                      &num_matches, &matches) == EXPAND_OK)
  2780.         ins_compl_add_matches(num_matches, matches, dir);
  2781.         break;
  2782.  
  2783.     default:    /* normal ^P/^N and ^X^L */
  2784.         /*
  2785.          * If 'infercase' is set, don't use 'smartcase' here
  2786.          */
  2787.         save_p_scs = p_scs;
  2788.         if (ins_buf->b_p_inf)
  2789.         p_scs = FALSE;
  2790.         /*    buffers other than curbuf are scanned from the beginning or the
  2791.          *    end but never from the middle, thus setting nowrapscan in this
  2792.          *    buffers is a good idea, on the other hand, we always set
  2793.          *    wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
  2794.         save_p_ws = p_ws;
  2795.         if (ins_buf != curbuf)
  2796.         p_ws = FALSE;
  2797.         else if (*e_cpt == '.')
  2798.         p_ws = TRUE;
  2799.         for (;;)
  2800.         {
  2801.         int    reuse = 0;
  2802.  
  2803.         /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has
  2804.          * added a word that was at the beginning of the line */
  2805.         if (    ctrl_x_mode == CTRL_X_WHOLE_LINE
  2806.             || (continue_status & CONT_SOL))
  2807.             found_new_match = search_for_exact_line(ins_buf, pos,
  2808.                                 dir, complete_pat);
  2809.         else
  2810.             found_new_match = searchit(NULL, ins_buf, pos, dir,
  2811.                  complete_pat, 1L, SEARCH_KEEP + SEARCH_NFMSG,
  2812.                                      RE_LAST);
  2813.         if (!started_completion)
  2814.         {
  2815.             /* set started_completion even on fail */
  2816.             started_completion = TRUE;
  2817.             first_match_pos = *pos;
  2818.             last_match_pos = *pos;
  2819.         }
  2820.         else if (first_match_pos.lnum == last_match_pos.lnum
  2821.              && first_match_pos.col == last_match_pos.col)
  2822.             found_new_match = FAIL;
  2823.         if (found_new_match == FAIL)
  2824.         {
  2825.             if (ins_buf == curbuf)
  2826.             found_all = TRUE;
  2827.             break;
  2828.         }
  2829.  
  2830.         /* when ADDING, the text before the cursor matches, skip it */
  2831.         if (    (continue_status & CONT_ADDING) && ins_buf == curbuf
  2832.             && ini->lnum == pos->lnum
  2833.             && ini->col  == pos->col)
  2834.             continue;
  2835.         ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
  2836.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2837.         {
  2838.             if (continue_status & CONT_ADDING)
  2839.             {
  2840.             if (pos->lnum >= ins_buf->b_ml.ml_line_count)
  2841.                 continue;
  2842.             ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2843.             if (!p_paste)
  2844.                 ptr = skipwhite(ptr);
  2845.             }
  2846.             len = (int)STRLEN(ptr);
  2847.         }
  2848.         else
  2849.         {
  2850.             tmp_ptr = ptr;
  2851.             if (continue_status & CONT_ADDING)
  2852.             {
  2853.             tmp_ptr += completion_length;
  2854.             /* Skip if already inside a word. */
  2855.             if (vim_iswordp(tmp_ptr))
  2856.                 continue;
  2857.             /* Find start of next word. */
  2858.             tmp_ptr = find_word_start(tmp_ptr);
  2859.             }
  2860.             /* Find end of this word. */
  2861.             tmp_ptr = find_word_end(tmp_ptr);
  2862.             len = (int)(tmp_ptr - ptr);
  2863.  
  2864.             if ((continue_status & CONT_ADDING)
  2865.                           && len == completion_length)
  2866.             {
  2867.             if (pos->lnum < ins_buf->b_ml.ml_line_count)
  2868.             {
  2869.                 /* Try next line, if any. the new word will be
  2870.                  * "join" as if the normal command "J" was used.
  2871.                  * IOSIZE is always greater than
  2872.                  * completion_length, so the next STRNCPY always
  2873.                  * works -- Acevedo */
  2874.                 STRNCPY(IObuff, ptr, len);
  2875.                 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2876.                 tmp_ptr = ptr = skipwhite(ptr);
  2877.                 /* Find start of next word. */
  2878.                 tmp_ptr = find_word_start(tmp_ptr);
  2879.                 /* Find end of next word. */
  2880.                 tmp_ptr = find_word_end(tmp_ptr);
  2881.                 if (tmp_ptr > ptr)
  2882.                 {
  2883.                 if (*ptr != ')' && IObuff[len-1] != TAB)
  2884.                 {
  2885.                     if (IObuff[len-1] != ' ')
  2886.                     IObuff[len++] = ' ';
  2887.                     /* IObuf =~ "\k.* ", thus len >= 2 */
  2888.                     if (p_js
  2889.                     && (IObuff[len-2] == '.'
  2890.                         || (vim_strchr(p_cpo, CPO_JOINSP)
  2891.                                        == NULL
  2892.                         && (IObuff[len-2] == '?'
  2893.                             || IObuff[len-2] == '!'))))
  2894.                     IObuff[len++] = ' ';
  2895.                 }
  2896.                 /* copy as much as posible of the new word */
  2897.                 if (tmp_ptr - ptr >= IOSIZE - len)
  2898.                     tmp_ptr = ptr + IOSIZE - len - 1;
  2899.                 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
  2900.                 len += (int)(tmp_ptr - ptr);
  2901.                 reuse |= CONT_S_IPOS;
  2902.                 }
  2903.                 IObuff[len] = NUL;
  2904.                 ptr = IObuff;
  2905.             }
  2906.             if (len == completion_length)
  2907.                 continue;
  2908.             }
  2909.         }
  2910.         if (ins_compl_add_infercase(ptr, len,
  2911.                 ins_buf == curbuf ?  NULL : ins_buf->b_sfname,
  2912.                               dir, reuse) != FAIL)
  2913.         {
  2914.             found_new_match = OK;
  2915.             break;
  2916.         }
  2917.         }
  2918.         p_scs = save_p_scs;
  2919.         p_ws = save_p_ws;
  2920.     }
  2921.     /* check if curr_match has changed, (e.g. other type of expansion
  2922.      * added somenthing) */
  2923.     if (curr_match != old_match)
  2924.         found_new_match = OK;
  2925.  
  2926.     /* break the loop for specialized modes (use 'complete' just for the
  2927.      * generic ctrl_x_mode == 0) or when we've found a new match */
  2928.     if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
  2929.         || found_new_match != FAIL)
  2930.         break;
  2931.  
  2932.     /* Mark a buffer scanned when it has been scanned completely */
  2933.     if (type == 0 || type == CTRL_X_PATH_PATTERNS)
  2934.         ins_buf->b_scanned = TRUE;
  2935.  
  2936.     started_completion = FALSE;
  2937.     }
  2938.     started_completion = TRUE;
  2939.  
  2940.     if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2941.         && *e_cpt == NUL)        /* Got to end of 'complete' */
  2942.     found_new_match = FAIL;
  2943.  
  2944.     i = -1;        /* total of matches, unknown */
  2945.     if (found_new_match == FAIL
  2946.         || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
  2947.     i = ins_compl_make_cyclic();
  2948.  
  2949.     /* If several matches were added (FORWARD) or the search failed and has
  2950.      * just been made cyclic then we have to move curr_match to the next or
  2951.      * previous entry (if any) -- Acevedo */
  2952.     curr_match = dir == FORWARD ? old_match->next : old_match->prev;
  2953.     if (curr_match == NULL)
  2954.     curr_match = old_match;
  2955.     return i;
  2956. }
  2957.  
  2958. /* Delete the old text being completed. */
  2959.     static void
  2960. ins_compl_delete()
  2961. {
  2962.     int        i;
  2963.  
  2964.     /*
  2965.      * In insert mode: Delete the typed part.
  2966.      * In replace mode: Put the old characters back, if any.
  2967.      */
  2968.     i = complete_col + (continue_status & CONT_ADDING ? completion_length : 0);
  2969.     backspace_until_column(i);
  2970.     changed_cline_bef_curs();
  2971. }
  2972.  
  2973. /* Insert the new text being completed. */
  2974.     static void
  2975. ins_compl_insert()
  2976. {
  2977.     ins_bytes(shown_match->str + curwin->w_cursor.col - complete_col);
  2978. }
  2979.  
  2980. /*
  2981.  * Fill in the next completion in the current direction.
  2982.  * If allow_get_expansion is TRUE, then we may call ins_compl_get_exp() to get
  2983.  * more completions.  If it is FALSE, then we just do nothing when there are
  2984.  * no more completions in a given direction.  The latter case is used when we
  2985.  * are still in the middle of finding completions, to allow browsing through
  2986.  * the ones found so far.
  2987.  * Return the total number of matches, or -1 if still unknown -- webb.
  2988.  *
  2989.  * curr_match is currently being used by ins_compl_get_exp(), so we use
  2990.  * shown_match here.
  2991.  *
  2992.  * Note that this function may be called recursively once only.  First with
  2993.  * allow_get_expansion TRUE, which calls ins_compl_get_exp(), which in turn
  2994.  * calls this function with allow_get_expansion FALSE.
  2995.  */
  2996.     static int
  2997. ins_compl_next(allow_get_expansion)
  2998.     int        allow_get_expansion;
  2999. {
  3000.     int        num_matches = -1;
  3001.     int        i;
  3002.  
  3003.     if (allow_get_expansion)
  3004.     {
  3005.     /* Delete old text to be replaced */
  3006.     ins_compl_delete();
  3007.     }
  3008.     completion_pending = FALSE;
  3009.     if (shown_direction == FORWARD && shown_match->next != NULL)
  3010.     shown_match = shown_match->next;
  3011.     else if (shown_direction == BACKWARD && shown_match->prev != NULL)
  3012.     shown_match = shown_match->prev;
  3013.     else
  3014.     {
  3015.     completion_pending = TRUE;
  3016.     if (allow_get_expansion)
  3017.     {
  3018.         num_matches = ins_compl_get_exp(&initial_pos, complete_direction);
  3019.         if (completion_pending)
  3020.         {
  3021.         if (complete_direction == shown_direction)
  3022.             shown_match = curr_match;
  3023.         }
  3024.     }
  3025.     else
  3026.         return -1;
  3027.     }
  3028.  
  3029.     /* Insert the text of the new completion */
  3030.     ins_compl_insert();
  3031.  
  3032.     if (!allow_get_expansion)
  3033.     {
  3034.     /* Display the current match. */
  3035.     update_screen(0);
  3036.  
  3037.     /* Delete old text to be replaced, since we're still searching and
  3038.      * don't want to match ourselves!  */
  3039.     ins_compl_delete();
  3040.     }
  3041.  
  3042.     /*
  3043.      * Show the file name for the match (if any)
  3044.      * Truncate the file name to avoid a wait for return.
  3045.      */
  3046.     if (shown_match->fname != NULL)
  3047.     {
  3048.     STRCPY(IObuff, "match in file ");
  3049.     i = (vim_strsize(shown_match->fname) + 16) - sc_col;
  3050.     if (i <= 0)
  3051.         i = 0;
  3052.     else
  3053.         STRCAT(IObuff, "<");
  3054.     STRCAT(IObuff, shown_match->fname + i);
  3055.     msg(IObuff);
  3056.     redraw_cmdline = FALSE;        /* don't overwrite! */
  3057.     }
  3058.  
  3059.     return num_matches;
  3060. }
  3061.  
  3062. /*
  3063.  * Call this while finding completions, to check whether the user has hit a key
  3064.  * that should change the currently displayed completion, or exit completion
  3065.  * mode.  Also, when completion_pending is TRUE, show a completion as soon as
  3066.  * possible. -- webb
  3067.  */
  3068.     void
  3069. ins_compl_check_keys()
  3070. {
  3071.     static int    count = 0;
  3072.  
  3073.     int        c;
  3074.  
  3075.     /* Don't check when reading keys from a script.  That would break the test
  3076.      * scripts */
  3077.     if (using_script())
  3078.     return;
  3079.  
  3080.     /* Only do this at regular intervals */
  3081.     if (++count < CHECK_KEYS_TIME)
  3082.     return;
  3083.     count = 0;
  3084.  
  3085.     ++no_mapping;
  3086.     c = vpeekc_any();
  3087.     --no_mapping;
  3088.     if (c != NUL)
  3089.     {
  3090.     if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
  3091.     {
  3092.         c = safe_vgetc();    /* Eat the character */
  3093.         if (c == Ctrl_P || c == Ctrl_L)
  3094.         shown_direction = BACKWARD;
  3095.         else
  3096.         shown_direction = FORWARD;
  3097.         (void)ins_compl_next(FALSE);
  3098.     }
  3099.     else if (c != Ctrl_R)
  3100.         completion_interrupted = TRUE;
  3101.     }
  3102.     if (completion_pending && !got_int)
  3103.     (void)ins_compl_next(FALSE);
  3104. }
  3105.  
  3106. /*
  3107.  * Do Insert mode completion.
  3108.  * Called when character "c" was typed, which has a meaning for completion.
  3109.  * Returns OK if completion was done, FAIL if something failed (out of mem).
  3110.  */
  3111.     static int
  3112. ins_complete(c)
  3113.     int            c;
  3114. {
  3115.     char_u        *line;
  3116.     char_u        *tmp_ptr = NULL;        /* init for gcc */
  3117.     int            temp = 0;
  3118.  
  3119.     if (c == Ctrl_P || c == Ctrl_L)
  3120.     complete_direction = BACKWARD;
  3121.     else
  3122.     complete_direction = FORWARD;
  3123.     if (!started_completion)
  3124.     {
  3125.     /* First time we hit ^N or ^P (in a row, I mean) */
  3126.  
  3127.     /* Turn off 'sm' so we don't show matches with ^X^L */
  3128.     save_sm = p_sm;
  3129.     p_sm = FALSE;
  3130.  
  3131.     did_ai = FALSE;
  3132. #ifdef FEAT_SMARTINDENT
  3133.     did_si = FALSE;
  3134.     can_si = FALSE;
  3135.     can_si_back = FALSE;
  3136. #endif
  3137.     if (stop_arrow() == FAIL)
  3138.         return FAIL;
  3139.  
  3140.     line = ml_get(curwin->w_cursor.lnum);
  3141.     complete_col = curwin->w_cursor.col;
  3142.  
  3143.     /* if this same ctrl_x_mode has been interrupted use the text from
  3144.      * "initial_pos" to the cursor as a pattern to add a new word instead
  3145.      * of expand the one before the cursor, in word-wise if "initial_pos"
  3146.      * is not in the same line as the cursor then fix it (the line has
  3147.      * been split because it was longer than 'tw').  if SOL is set then
  3148.      * skip the previous pattern, a word at the beginning of the line has
  3149.      * been inserted, we'll look for that  -- Acevedo. */
  3150.     if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode)
  3151.     {
  3152.         /*
  3153.          * it is a continued search
  3154.          */
  3155.         continue_status &= ~CONT_INTRPT;    /* remove INTRPT */
  3156.         if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
  3157.                     || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  3158.         {
  3159.         if (initial_pos.lnum != curwin->w_cursor.lnum)
  3160.         {
  3161.             /* line (probably) wrapped, set initial_pos to the first
  3162.              * non_blank in the line, if it is not a wordchar include
  3163.              * it to get a better pattern, but then we don't want the
  3164.              * "\\<" prefix, check it bellow */
  3165.             tmp_ptr = skipwhite(line);
  3166.             initial_pos.col = (colnr_T) (tmp_ptr - line);
  3167.             initial_pos.lnum = curwin->w_cursor.lnum;
  3168.             continue_status &= ~CONT_SOL;    /* clear SOL if present */
  3169.         }
  3170.         else
  3171.         {
  3172.             /* S_IPOS was set when we inserted a word that was at the
  3173.              * beginning of the line, which means that we'll go to SOL
  3174.              * mode but first we need to redefine initial_pos */
  3175.             if (continue_status & CONT_S_IPOS)
  3176.             {
  3177.             continue_status |= CONT_SOL;
  3178.             initial_pos.col = (colnr_T) (skipwhite(line + completion_length +
  3179.                             initial_pos.col) - line);
  3180.             }
  3181.             tmp_ptr = line + initial_pos.col;
  3182.         }
  3183.         temp = curwin->w_cursor.col - (int)(tmp_ptr - line);
  3184.         /* IObuf is used to add a "word from the next line" would we
  3185.          * have enough space?  just being paranoic */
  3186. #define    MIN_SPACE 75
  3187.         if (temp > (IOSIZE - MIN_SPACE))
  3188.         {
  3189.             continue_status &= ~CONT_SOL;
  3190.             temp = (IOSIZE - MIN_SPACE);
  3191.             tmp_ptr = line + curwin->w_cursor.col - temp;
  3192.         }
  3193.         continue_status |= CONT_ADDING | CONT_N_ADDS;
  3194.         if (temp < 1)
  3195.             continue_status &= CONT_LOCAL;
  3196.         }
  3197.         else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3198.         continue_status = CONT_ADDING | CONT_N_ADDS;
  3199.         else
  3200.         continue_status = 0;
  3201.     }
  3202.     else
  3203.         continue_status &= CONT_LOCAL;
  3204.  
  3205.     if (!(continue_status & CONT_ADDING))    /* normal expansion */
  3206.     {
  3207.         continue_mode = ctrl_x_mode;
  3208.         if (ctrl_x_mode != 0)    /* Remove LOCAL if ctrl_x_mode != 0 */
  3209.         continue_status = 0;
  3210.         continue_status |= CONT_N_ADDS;
  3211.         initial_pos = curwin->w_cursor;
  3212.         temp = (int)complete_col;
  3213.         tmp_ptr = line;
  3214.     }
  3215.  
  3216.     /* Work out completion pattern and original text -- webb */
  3217.     if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
  3218.     {
  3219.         if (       (continue_status & CONT_SOL)
  3220.             || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  3221.         {
  3222.         if (!(continue_status & CONT_ADDING))
  3223.         {
  3224.             while (--temp >= 0 && vim_isIDc(line[temp]))
  3225.             ;
  3226.             tmp_ptr += ++temp;
  3227.             temp = complete_col - temp;
  3228.         }
  3229.         if (p_ic)
  3230.             complete_pat = str_foldcase(tmp_ptr, temp);
  3231.         else
  3232.             complete_pat = vim_strnsave(tmp_ptr, temp);
  3233.         if (complete_pat == NULL)
  3234.             return FAIL;
  3235.         }
  3236.         else if (continue_status & CONT_ADDING)
  3237.         {
  3238.         char_u        *prefix = (char_u *)"\\<";
  3239.  
  3240.         /* we need 3 extra chars, 1 for the NUL and
  3241.          * 2 >= strlen(prefix)    -- Acevedo */
  3242.         complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  3243.         if (complete_pat == NULL)
  3244.             return FAIL;
  3245.         if (!vim_iswordp(tmp_ptr)
  3246.             || (tmp_ptr > line
  3247.                 && (
  3248. #ifdef FEAT_MBYTE
  3249.                 vim_iswordp(mb_prevptr(line, tmp_ptr))
  3250. #else
  3251.                 vim_iswordc(*(tmp_ptr - 1))
  3252. #endif
  3253.                 )))
  3254.             prefix = (char_u *)"";
  3255.         STRCPY((char *)complete_pat, prefix);
  3256.         (void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp);
  3257.         }
  3258.         else if (
  3259. #ifdef FEAT_MBYTE
  3260.             --temp < 0 || !vim_iswordp(mb_prevptr(line,
  3261.                                  line + temp + 1))
  3262. #else
  3263.             --temp < 0 || !vim_iswordc(line[temp])
  3264. #endif
  3265.             )
  3266.         {
  3267.         /* Match any word of at least two chars */
  3268.         complete_pat = vim_strsave((char_u *)"\\<\\k\\k");
  3269.         if (complete_pat == NULL)
  3270.             return FAIL;
  3271.         tmp_ptr += complete_col;
  3272.         temp = 0;
  3273.         }
  3274.         else
  3275.         {
  3276. #ifdef FEAT_MBYTE
  3277.         /* Search the point of change class of multibyte character
  3278.          * or not a word single byte character backward.  */
  3279.         if (has_mbyte)
  3280.         {
  3281.             int base_class;
  3282.             int head_off;
  3283.  
  3284.             temp -= (*mb_head_off)(line, line + temp);
  3285.             base_class = mb_get_class(line + temp);
  3286.             while (--temp >= 0)
  3287.             {
  3288.             head_off = (*mb_head_off)(line, line + temp);
  3289.             if (base_class != mb_get_class(line + temp - head_off))
  3290.                 break;
  3291.             temp -= head_off;
  3292.             }
  3293.         }
  3294.         else
  3295. #endif
  3296.             while (--temp >= 0 && vim_iswordc(line[temp]))
  3297.             ;
  3298.         tmp_ptr += ++temp;
  3299.         if ((temp = (int)complete_col - temp) == 1)
  3300.         {
  3301.             /* Only match word with at least two chars -- webb
  3302.              * there's no need to call quote_meta,
  3303.              * alloc(7) is enough  -- Acevedo
  3304.              */
  3305.             complete_pat = alloc(7);
  3306.             if (complete_pat == NULL)
  3307.             return FAIL;
  3308.             STRCPY((char *)complete_pat, "\\<");
  3309.             (void)quote_meta(complete_pat + 2, tmp_ptr, 1);
  3310.             STRCAT((char *)complete_pat, "\\k");
  3311.         }
  3312.         else
  3313.         {
  3314.             complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  3315.             if (complete_pat == NULL)
  3316.             return FAIL;
  3317.             STRCPY((char *)complete_pat, "\\<");
  3318.             (void)quote_meta(complete_pat + 2, tmp_ptr, temp);
  3319.         }
  3320.         }
  3321.     }
  3322.     else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3323.     {
  3324.         tmp_ptr = skipwhite(line);
  3325.         temp = (int)complete_col - (int)(tmp_ptr - line);
  3326.         if (temp < 0)    /* cursor in indent: empty pattern */
  3327.         temp = 0;
  3328.         if (p_ic)
  3329.         complete_pat = str_foldcase(tmp_ptr, temp);
  3330.         else
  3331.         complete_pat = vim_strnsave(tmp_ptr, temp);
  3332.         if (complete_pat == NULL)
  3333.         return FAIL;
  3334.     }
  3335.     else if (ctrl_x_mode == CTRL_X_FILES)
  3336.     {
  3337.         while (--temp >= 0 && vim_isfilec(line[temp]))
  3338.         ;
  3339.         tmp_ptr += ++temp;
  3340.         temp = (int)complete_col - temp;
  3341.         complete_pat = addstar(tmp_ptr, temp, EXPAND_FILES);
  3342.         if (complete_pat == NULL)
  3343.         return FAIL;
  3344.     }
  3345.     else if (ctrl_x_mode == CTRL_X_CMDLINE)
  3346.     {
  3347.         complete_pat = vim_strnsave(line, complete_col);
  3348.         if (complete_pat == NULL)
  3349.         return FAIL;
  3350.         set_cmd_context(&complete_xp, complete_pat,
  3351.                      (int)STRLEN(complete_pat), complete_col);
  3352.         if (complete_xp.xp_context == EXPAND_UNSUCCESSFUL
  3353.             || complete_xp.xp_context == EXPAND_NOTHING)
  3354.         return FAIL;
  3355.         temp = (int)(complete_xp.xp_pattern - complete_pat);
  3356.         tmp_ptr = line + temp;
  3357.         temp = complete_col - temp;
  3358.     }
  3359.     complete_col = (colnr_T) (tmp_ptr - line);
  3360.  
  3361.     if (continue_status & CONT_ADDING)
  3362.     {
  3363.         edit_submode_pre = (char_u *)_(" Adding");
  3364.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3365.         {
  3366.         /* Insert a new line, keep indentation but ignore 'comments' */
  3367. #ifdef FEAT_COMMENTS
  3368.         char_u *old = curbuf->b_p_com;
  3369.  
  3370.         curbuf->b_p_com = (char_u *)"";
  3371. #endif
  3372.         initial_pos.lnum = curwin->w_cursor.lnum;
  3373.         initial_pos.col = complete_col;
  3374.         ins_eol('\r');
  3375. #ifdef FEAT_COMMENTS
  3376.         curbuf->b_p_com = old;
  3377. #endif
  3378.         tmp_ptr = (char_u *)"";
  3379.         temp = 0;
  3380.         complete_col = curwin->w_cursor.col;
  3381.         }
  3382.     }
  3383.     else
  3384.     {
  3385.         edit_submode_pre = NULL;
  3386.         initial_pos.col = complete_col;
  3387.     }
  3388.  
  3389.     if (continue_status & CONT_LOCAL)
  3390.         edit_submode = (char_u *)_(ctrl_x_msgs[2]);
  3391.     else
  3392.         edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
  3393.  
  3394.     completion_length = temp;
  3395.  
  3396.     /* Always add completion for the original text.  Note that
  3397.      * "original_text" itself (not a copy) is added, it will be freed when
  3398.      * the list of matches is freed. */
  3399.     if ((original_text = vim_strnsave(tmp_ptr, temp)) == NULL
  3400.         || ins_compl_add(original_text, -1, NULL, 0, ORIGINAL_TEXT) != OK)
  3401.     {
  3402.         vim_free(complete_pat);
  3403.         complete_pat = NULL;
  3404.         vim_free(original_text);
  3405.         return FAIL;
  3406.     }
  3407.  
  3408.     /* showmode might reset the internal line pointers, so it must
  3409.      * be called before line = ml_get(), or when this address is no
  3410.      * longer needed.  -- Acevedo.
  3411.      */
  3412.     edit_submode_extra = (char_u *)_("-- Searching...");
  3413.     edit_submode_highl = HLF_COUNT;
  3414.     showmode();
  3415.     edit_submode_extra = NULL;
  3416.     out_flush();
  3417.     }
  3418.  
  3419.     shown_match = curr_match;
  3420.     shown_direction = complete_direction;
  3421.  
  3422.     /*
  3423.      * Find next match.
  3424.      */
  3425.     temp = ins_compl_next(TRUE);
  3426.  
  3427.     if (temp > 1)    /* all matches have been found */
  3428.     completion_matches = temp;
  3429.     curr_match = shown_match;
  3430.     complete_direction = shown_direction;
  3431.     completion_interrupted = FALSE;
  3432.  
  3433.     /* eat the ESC to avoid leaving insert mode */
  3434.     if (got_int && !global_busy)
  3435.     {
  3436.     (void)vgetc();
  3437.     got_int = FALSE;
  3438.     }
  3439.  
  3440.     /* we found no match if the list has only the original_text-entry */
  3441.     if (first_match == first_match->next)
  3442.     {
  3443.     edit_submode_extra = (continue_status & CONT_ADDING)
  3444.             && completion_length > 1
  3445.                  ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
  3446.     edit_submode_highl = HLF_E;
  3447.     /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
  3448.      * because we couldn't expand anything at first place, but if we used
  3449.      * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
  3450.      * (such as M in M'exico) if not tried already.  -- Acevedo */
  3451.     if (       completion_length > 1
  3452.         || (continue_status & CONT_ADDING)
  3453.         || (ctrl_x_mode != 0
  3454.             && ctrl_x_mode != CTRL_X_PATH_PATTERNS
  3455.             && ctrl_x_mode != CTRL_X_PATH_DEFINES))
  3456.         continue_status &= ~CONT_N_ADDS;
  3457.     }
  3458.  
  3459.     if (curr_match->original & CONT_S_IPOS)
  3460.     continue_status |= CONT_S_IPOS;
  3461.     else
  3462.     continue_status &= ~CONT_S_IPOS;
  3463.  
  3464.     if (edit_submode_extra == NULL)
  3465.     {
  3466.     if (curr_match->original & ORIGINAL_TEXT)
  3467.     {
  3468.         edit_submode_extra = (char_u *)_("Back at original");
  3469.         edit_submode_highl = HLF_W;
  3470.     }
  3471.     else if (continue_status & CONT_S_IPOS)
  3472.     {
  3473.         edit_submode_extra = (char_u *)_("Word from other line");
  3474.         edit_submode_highl = HLF_COUNT;
  3475.     }
  3476.     else if (curr_match->next == curr_match->prev)
  3477.     {
  3478.         edit_submode_extra = (char_u *)_("The only match");
  3479.         edit_submode_highl = HLF_COUNT;
  3480.     }
  3481.     else
  3482.     {
  3483.         /* Update completion sequence number when needed. */
  3484.         if (curr_match->number == -1)
  3485.         {
  3486.         int            number = 0;
  3487.         struct Completion   *match;
  3488.  
  3489.         if (complete_direction == FORWARD)
  3490.         {
  3491.             /* search backwards for the first valid (!= -1) number.
  3492.              * This should normally succeed already at the first loop
  3493.              * cycle, so it's fast! */
  3494.             for (match = curr_match->prev; match != NULL
  3495.                  && match != first_match; match = match->prev)
  3496.             if (match->number != -1)
  3497.             {
  3498.                 number = match->number;
  3499.                 break;
  3500.             }
  3501.             if (match != NULL)
  3502.             /* go up and assign all numbers which are not assigned
  3503.              * yet */
  3504.             for (match = match->next; match
  3505.                   && match->number == -1; match = match->next)
  3506.                 match->number = ++number;
  3507.         }
  3508.         else /* BACKWARD */
  3509.         {
  3510.             /* search forwards (upwards) for the first valid (!= -1)
  3511.              * number.  This should normally succeed already at the
  3512.              * first loop cycle, so it's fast! */
  3513.             for (match = curr_match->next; match != NULL
  3514.                  && match != first_match; match = match->next)
  3515.             if (match->number != -1)
  3516.             {
  3517.                 number = match->number;
  3518.                 break;
  3519.             }
  3520.             if (match != NULL)
  3521.             /* go down and assign all numbers which are not
  3522.              * assigned yet */
  3523.             for (match = match->prev; match
  3524.                   && match->number == -1; match = match->prev)
  3525.                 match->number = ++number;
  3526.         }
  3527.         }
  3528.  
  3529.         /* The match should always have a sequnce number now, this is just
  3530.          * a safety check. */
  3531.         if (curr_match->number != -1)
  3532.         {
  3533.         /* Space for 10 text chars. + 2x10-digit no.s */
  3534.         static char_u match_ref[31];
  3535.  
  3536.         if (completion_matches > 0)
  3537.             sprintf((char *)IObuff, _("match %d of %d"),
  3538.                       curr_match->number, completion_matches);
  3539.         else
  3540.             sprintf((char *)IObuff, _("match %d"), curr_match->number);
  3541.         STRNCPY(match_ref, IObuff, 30 );
  3542.         match_ref[30] = '\0';
  3543.         edit_submode_extra = match_ref;
  3544.         edit_submode_highl = HLF_R;
  3545.         if (dollar_vcol)
  3546.             curs_columns(FALSE);
  3547.         }
  3548.     }
  3549.     }
  3550.  
  3551.     /* Show a message about what (completion) mode we're in. */
  3552.     showmode();
  3553.     if (edit_submode_extra != NULL)
  3554.     {
  3555.     if (!p_smd)
  3556.         msg_attr(edit_submode_extra,
  3557.             edit_submode_highl < HLF_COUNT
  3558.             ? hl_attr(edit_submode_highl) : 0);
  3559.     }
  3560.     else
  3561.     msg_clr_cmdline();    /* necessary for "noshowmode" */
  3562.  
  3563.     return OK;
  3564. }
  3565.  
  3566. /*
  3567.  * Looks in the first "len" chars. of "src" for search-metachars.
  3568.  * If dest is not NULL the chars. are copied there quoting (with
  3569.  * a backslash) the metachars, and dest would be NUL terminated.
  3570.  * Returns the length (needed) of dest
  3571.  */
  3572.     static int
  3573. quote_meta(dest, src, len)
  3574.     char_u    *dest;
  3575.     char_u    *src;
  3576.     int        len;
  3577. {
  3578.     int    m;
  3579.  
  3580.     for (m = len; --len >= 0; src++)
  3581.     {
  3582.     switch (*src)
  3583.     {
  3584.         case '.':
  3585.         case '*':
  3586.         case '[':
  3587.         if (ctrl_x_mode == CTRL_X_DICTIONARY
  3588.                        || ctrl_x_mode == CTRL_X_THESAURUS)
  3589.             break;
  3590.         case '~':
  3591.         if (!p_magic)    /* quote these only if magic is set */
  3592.             break;
  3593.         case '\\':
  3594.         if (ctrl_x_mode == CTRL_X_DICTIONARY
  3595.                        || ctrl_x_mode == CTRL_X_THESAURUS)
  3596.             break;
  3597.         case '^':        /* currently it's not needed. */
  3598.         case '$':
  3599.         m++;
  3600.         if (dest != NULL)
  3601.             *dest++ = '\\';
  3602.         break;
  3603.     }
  3604.     if (dest != NULL)
  3605.         *dest++ = *src;
  3606. #ifdef FEAT_MBYTE
  3607.     /* Copy remaining bytes of a multibyte character. */
  3608.     if (has_mbyte)
  3609.     {
  3610.         int i, mb_len;
  3611.  
  3612.         mb_len = (*mb_ptr2len_check)(src) - 1;
  3613.         if (mb_len > 0 && len >= mb_len)
  3614.         for (i = 0; i < mb_len; ++i)
  3615.         {
  3616.             --len;
  3617.             ++src;
  3618.             if (dest != NULL)
  3619.             *dest++ = *src;
  3620.         }
  3621.     }
  3622. #endif
  3623.     }
  3624.     if (dest != NULL)
  3625.     *dest = NUL;
  3626.  
  3627.     return m;
  3628. }
  3629. #endif /* FEAT_INS_EXPAND */
  3630.  
  3631. /*
  3632.  * Next character is interpreted literally.
  3633.  * A one, two or three digit decimal number is interpreted as its byte value.
  3634.  * If one or two digits are entered, the next character is given to vungetc().
  3635.  * For Unicode a character > 255 may be returned.
  3636.  */
  3637.     int
  3638. get_literal()
  3639. {
  3640.     int        cc;
  3641.     int        nc;
  3642.     int        i;
  3643.     int        hex = FALSE;
  3644.     int        octal = FALSE;
  3645. #ifdef FEAT_MBYTE
  3646.     int        unicode = 0;
  3647. #endif
  3648.  
  3649.     if (got_int)
  3650.     return Ctrl_C;
  3651.  
  3652. #ifdef FEAT_GUI
  3653.     /*
  3654.      * In GUI there is no point inserting the internal code for a special key.
  3655.      * It is more useful to insert the string "<KEY>" instead.    This would
  3656.      * probably be useful in a text window too, but it would not be
  3657.      * vi-compatible (maybe there should be an option for it?) -- webb
  3658.      */
  3659.     if (gui.in_use)
  3660.     ++allow_keys;
  3661. #endif
  3662. #ifdef USE_ON_FLY_SCROLL
  3663.     dont_scroll = TRUE;        /* disallow scrolling here */
  3664. #endif
  3665.     ++no_mapping;        /* don't map the next key hits */
  3666.     cc = 0;
  3667.     i = 0;
  3668.     for (;;)
  3669.     {
  3670.     do
  3671.         nc = safe_vgetc();
  3672.     while (nc == K_IGNORE || nc == K_VER_SCROLLBAR
  3673.                             || nc == K_HOR_SCROLLBAR);
  3674. #ifdef FEAT_CMDL_INFO
  3675.     if (!(State & CMDLINE)
  3676. # ifdef FEAT_MBYTE
  3677.         && MB_BYTE2LEN_CHECK(nc) == 1
  3678. # endif
  3679.        )
  3680.         add_to_showcmd(nc);
  3681. #endif
  3682.     if (nc == 'x' || nc == 'X')
  3683.         hex = TRUE;
  3684.     else if (nc == 'o' || nc == 'O')
  3685.         octal = TRUE;
  3686. #ifdef FEAT_MBYTE
  3687.     else if (nc == 'u' || nc == 'U')
  3688.         unicode = nc;
  3689. #endif
  3690.     else
  3691.     {
  3692.         if (hex
  3693. #ifdef FEAT_MBYTE
  3694.             || unicode != 0
  3695. #endif
  3696.             )
  3697.         {
  3698.         /* Careful: isxdigit() on Win32 can handle only 0-255 */
  3699.         if (nc < 0 || nc > 255 || (!vim_isdigit(nc) && !isxdigit(nc)))
  3700.             break;
  3701.         cc = cc * 16 + hex2nr(nc);
  3702.         }
  3703.         else if (octal)
  3704.         {
  3705.         if (!vim_isdigit(nc) || (nc > '7'))
  3706.             break;
  3707.         cc = cc * 8 + nc - '0';
  3708.         }
  3709.         else
  3710.         {
  3711.         if (!vim_isdigit(nc))
  3712.             break;
  3713.         cc = cc * 10 + nc - '0';
  3714.         }
  3715.  
  3716.         ++i;
  3717.     }
  3718.  
  3719.     if (cc > 255
  3720. #ifdef FEAT_MBYTE
  3721.         && unicode == 0
  3722. #endif
  3723.         )
  3724.         cc = 255;        /* limit range to 0-255 */
  3725.     nc = 0;
  3726.  
  3727.     if (hex)        /* hex: up to two chars */
  3728.     {
  3729.         if (i >= 2)
  3730.         break;
  3731.     }
  3732. #ifdef FEAT_MBYTE
  3733.     else if (unicode)    /* Unicode: up to four or eight chars */
  3734.     {
  3735.         if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8))
  3736.         break;
  3737.     }
  3738. #endif
  3739.     else if (i >= 3)    /* decimal or octal: up to three chars */
  3740.         break;
  3741.     }
  3742.     if (i == 0)        /* no number entered */
  3743.     {
  3744.     if (nc == K_ZERO)   /* NUL is stored as NL */
  3745.     {
  3746.         cc = '\n';
  3747.         nc = 0;
  3748.     }
  3749.     else
  3750.     {
  3751.         cc = nc;
  3752.         nc = 0;
  3753.     }
  3754.     }
  3755.  
  3756.     if (cc == 0)    /* NUL is stored as NL */
  3757.     cc = '\n';
  3758.  
  3759.     --no_mapping;
  3760. #ifdef FEAT_GUI
  3761.     if (gui.in_use)
  3762.     --allow_keys;
  3763. #endif
  3764.     if (nc)
  3765.     vungetc(nc);
  3766.     got_int = FALSE;        /* CTRL-C typed after CTRL-V is not an interrupt */
  3767.     return cc;
  3768. }
  3769.  
  3770. /*
  3771.  * Insert character, taking care of special keys and mod_mask
  3772.  */
  3773.     static void
  3774. insert_special(c, allow_modmask, ctrlv)
  3775.     int        c;
  3776.     int        allow_modmask;
  3777.     int        ctrlv;        /* c was typed after CTRL-V */
  3778. {
  3779.     char_u  *p;
  3780.     int        len;
  3781.  
  3782.     /*
  3783.      * Special function key, translate into "<Key>". Up to the last '>' is
  3784.      * inserted with ins_str(), so as not to replace characters in replace
  3785.      * mode.
  3786.      * Only use mod_mask for special keys, to avoid things like <S-Space>,
  3787.      * unless 'allow_modmask' is TRUE.
  3788.      */
  3789. #ifdef MACOS
  3790.     /* Command-key never produces a normal key */
  3791.     if (mod_mask & MOD_MASK_CMD)
  3792.     allow_modmask = TRUE;
  3793. #endif
  3794.     if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
  3795.     {
  3796.     p = get_special_key_name(c, mod_mask);
  3797.     len = (int)STRLEN(p);
  3798.     c = p[len - 1];
  3799.     if (len > 2)
  3800.     {
  3801.         if (stop_arrow() == FAIL)
  3802.         return;
  3803.         p[len - 1] = NUL;
  3804.         ins_str(p);
  3805.         AppendToRedobuffLit(p);
  3806.         ctrlv = FALSE;
  3807.     }
  3808.     }
  3809.     if (stop_arrow() == OK)
  3810.     insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1);
  3811. }
  3812.  
  3813. /*
  3814.  * Special characters in this context are those that need processing other
  3815.  * than the simple insertion that can be performed here. This includes ESC
  3816.  * which terminates the insert, and CR/NL which need special processing to
  3817.  * open up a new line. This routine tries to optimize insertions performed by
  3818.  * the "redo", "undo" or "put" commands, so it needs to know when it should
  3819.  * stop and defer processing to the "normal" mechanism.
  3820.  * '0' and '^' are special, because they can be followed by CTRL-D.
  3821.  */
  3822. #ifdef EBCDIC
  3823. # define ISSPECIAL(c)    ((c) < ' ' || (c) == '0' || (c) == '^')
  3824. #else
  3825. # define ISSPECIAL(c)    ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
  3826. #endif
  3827.  
  3828. #ifdef FEAT_MBYTE
  3829. # define WHITECHAR(cc) (vim_iswhite(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
  3830. #else
  3831. # define WHITECHAR(cc) vim_iswhite(cc)
  3832. #endif
  3833.  
  3834.     void
  3835. insertchar(c, flags, second_indent)
  3836.     int        c;            /* character to insert or NUL */
  3837.     int        flags;            /* INSCHAR_FORMAT, etc. */
  3838.     int        second_indent;        /* indent for second line if >= 0 */
  3839. {
  3840.     int        haveto_redraw = FALSE;
  3841.     int        textwidth;
  3842. #ifdef FEAT_COMMENTS
  3843.     colnr_T    leader_len;
  3844.     char_u    *p;
  3845.     int        no_leader = FALSE;
  3846.     int        do_comments = (flags & INSCHAR_DO_COM);
  3847. #endif
  3848.     int        fo_white_par;
  3849.     int        first_line = TRUE;
  3850.     int        fo_ins_blank;
  3851. #ifdef FEAT_MBYTE
  3852.     int        fo_multibyte;
  3853. #endif
  3854.     int        save_char = NUL;
  3855.     int        cc;
  3856.  
  3857.     textwidth = comp_textwidth(flags & INSCHAR_FORMAT);
  3858.     fo_ins_blank = has_format_option(FO_INS_BLANK);
  3859. #ifdef FEAT_MBYTE
  3860.     fo_multibyte = has_format_option(FO_MBYTE_BREAK);
  3861. #endif
  3862.     fo_white_par = has_format_option(FO_WHITE_PAR);
  3863.  
  3864.     /*
  3865.      * Try to break the line in two or more pieces when:
  3866.      * - Always do this if we have been called to do formatting only.
  3867.      * - Always do this when 'formatoptions' has the 'a' flag and the line
  3868.      *   ends in white space.
  3869.      * - Otherwise:
  3870.      *     - Don't do this if inserting a blank
  3871.      *     - Don't do this if an existing character is being replaced, unless
  3872.      *       we're in VREPLACE mode.
  3873.      *     - Do this if the cursor is not on the line where insert started
  3874.      *     or - 'formatoptions' doesn't have 'l' or the line was not too long
  3875.      *           before the insert.
  3876.      *        - 'formatoptions' doesn't have 'b' or a blank was inserted at or
  3877.      *          before 'textwidth'
  3878.      */
  3879.     if (textwidth
  3880.         && ((flags & INSCHAR_FORMAT)
  3881.         || (!vim_iswhite(c)
  3882.             && !((State & REPLACE_FLAG)
  3883. #ifdef FEAT_VREPLACE
  3884.             && !(State & VREPLACE_FLAG)
  3885. #endif
  3886.             && *ml_get_cursor() != NUL)
  3887.             && (curwin->w_cursor.lnum != Insstart.lnum
  3888.             || ((!has_format_option(FO_INS_LONG)
  3889.                 || Insstart_textlen <= (colnr_T)textwidth)
  3890.                 && (!fo_ins_blank
  3891.                 || Insstart_blank_vcol <= (colnr_T)textwidth
  3892.                 ))))))
  3893.     {
  3894.     /*
  3895.      * When 'ai' is off we don't want a space under the cursor to be
  3896.      * deleted.  Replace it with an 'x' temporarily.
  3897.      */
  3898.     if (!curbuf->b_p_ai)
  3899.     {
  3900.         cc = gchar_cursor();
  3901.         if (vim_iswhite(cc))
  3902.         {
  3903.         save_char = cc;
  3904.         pchar_cursor('x');
  3905.         }
  3906.     }
  3907.  
  3908.     /*
  3909.      * Repeat breaking lines, until the current line is not too long.
  3910.      */
  3911.     while (!got_int)
  3912.     {
  3913.         int        startcol;        /* Cursor column at entry */
  3914.         int        wantcol;        /* column at textwidth border */
  3915.         int        foundcol;        /* column for start of spaces */
  3916.         int        end_foundcol = 0;    /* column for start of word */
  3917.         colnr_T    len;
  3918.         colnr_T    virtcol;
  3919. #ifdef FEAT_VREPLACE
  3920.         int        orig_col = 0;
  3921.         char_u    *saved_text = NULL;
  3922. #endif
  3923.         colnr_T    col;
  3924.  
  3925.         virtcol = get_nolist_virtcol();
  3926.         if (virtcol < (colnr_T)textwidth)
  3927.         break;
  3928.  
  3929. #ifdef FEAT_COMMENTS
  3930.         if (no_leader)
  3931.         do_comments = FALSE;
  3932.         else if (!(flags & INSCHAR_FORMAT)
  3933.                        && has_format_option(FO_WRAP_COMS))
  3934.         do_comments = TRUE;
  3935.  
  3936.         /* Don't break until after the comment leader */
  3937.         if (do_comments)
  3938.         leader_len = get_leader_len(ml_get_curline(), NULL, FALSE);
  3939.         else
  3940.         leader_len = 0;
  3941.  
  3942.         /* If the line doesn't start with a comment leader, then don't
  3943.          * start one in a following broken line.  Avoids that a %word
  3944.          * moved to the start of the next line causes all following lines
  3945.          * to start with %. */
  3946.         if (leader_len == 0)
  3947.         no_leader = TRUE;
  3948. #endif
  3949.         if (!(flags & INSCHAR_FORMAT)
  3950. #ifdef FEAT_COMMENTS
  3951.             && leader_len == 0
  3952. #endif
  3953.             && !has_format_option(FO_WRAP))
  3954.  
  3955.         {
  3956.         textwidth = 0;
  3957.         break;
  3958.         }
  3959.         if ((startcol = curwin->w_cursor.col) == 0)
  3960.         break;
  3961.  
  3962.         /* find column of textwidth border */
  3963.         coladvance((colnr_T)textwidth);
  3964.         wantcol = curwin->w_cursor.col;
  3965.  
  3966.         curwin->w_cursor.col = startcol - 1;
  3967. #ifdef FEAT_MBYTE
  3968.         /* Correct cursor for multi-byte character. */
  3969.         if (has_mbyte)
  3970.         mb_adjust_cursor();
  3971. #endif
  3972.         foundcol = 0;
  3973.  
  3974.         /*
  3975.          * Find position to break at.
  3976.          * Stop at first entered white when 'formatoptions' has 'v'
  3977.          */
  3978.         while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
  3979.             || curwin->w_cursor.lnum != Insstart.lnum
  3980.             || curwin->w_cursor.col >= Insstart.col)
  3981.         {
  3982.         cc = gchar_cursor();
  3983.         if (WHITECHAR(cc))
  3984.         {
  3985.             /* remember position of blank just before text */
  3986.             end_foundcol = curwin->w_cursor.col;
  3987.  
  3988.             /* find start of sequence of blanks */
  3989.             while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
  3990.             {
  3991.             dec_cursor();
  3992.             cc = gchar_cursor();
  3993.             }
  3994.             if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
  3995.             break;        /* only spaces in front of text */
  3996. #ifdef FEAT_COMMENTS
  3997.             /* Don't break until after the comment leader */
  3998.             if (curwin->w_cursor.col < leader_len)
  3999.             break;
  4000. #endif
  4001.             if (has_format_option(FO_ONE_LETTER))
  4002.             {
  4003.             /* do not break after one-letter words */
  4004.             if (curwin->w_cursor.col == 0)
  4005.                 break;    /* one-letter word at begin */
  4006.  
  4007.             col = curwin->w_cursor.col;
  4008.             dec_cursor();
  4009.             cc = gchar_cursor();
  4010.  
  4011.             if (WHITECHAR(cc))
  4012.                 continue;    /* one-letter, continue */
  4013.             curwin->w_cursor.col = col;
  4014.             }
  4015. #ifdef FEAT_MBYTE
  4016.             if (has_mbyte)
  4017.             foundcol = curwin->w_cursor.col
  4018.                        + (*mb_ptr2len_check)(ml_get_cursor());
  4019.             else
  4020. #endif
  4021.             foundcol = curwin->w_cursor.col + 1;
  4022.             if (curwin->w_cursor.col < (colnr_T)wantcol)
  4023.             break;
  4024.         }
  4025. #ifdef FEAT_MBYTE
  4026.         else if (cc >= 0x100 && fo_multibyte
  4027.                   && curwin->w_cursor.col <= (colnr_T)wantcol)
  4028.         {
  4029.             /* Break after or before a multi-byte character. */
  4030.             foundcol = curwin->w_cursor.col;
  4031.             if (curwin->w_cursor.col < (colnr_T)wantcol)
  4032.             foundcol += (*mb_char2len)(cc);
  4033.             end_foundcol = foundcol;
  4034.             break;
  4035.         }
  4036. #endif
  4037.         if (curwin->w_cursor.col == 0)
  4038.             break;
  4039.         dec_cursor();
  4040.         }
  4041.  
  4042.         if (foundcol == 0)        /* no spaces, cannot break line */
  4043.         {
  4044.         curwin->w_cursor.col = startcol;
  4045.         break;
  4046.         }
  4047.  
  4048.         /* Going to break the line, remove any "$" now. */
  4049.         undisplay_dollar();
  4050.  
  4051.         /*
  4052.          * Offset between cursor position and line break is used by replace
  4053.          * stack functions.  VREPLACE does not use this, and backspaces
  4054.          * over the text instead.
  4055.          */
  4056. #ifdef FEAT_VREPLACE
  4057.         if (State & VREPLACE_FLAG)
  4058.         orig_col = startcol;    /* Will start backspacing from here */
  4059.         else
  4060. #endif
  4061.         replace_offset = startcol - end_foundcol - 1;
  4062.  
  4063.         /*
  4064.          * adjust startcol for spaces that will be deleted and
  4065.          * characters that will remain on top line
  4066.          */
  4067.         curwin->w_cursor.col = foundcol;
  4068.         while (cc = gchar_cursor(), WHITECHAR(cc))
  4069.         inc_cursor();
  4070.         startcol -= curwin->w_cursor.col;
  4071.         if (startcol < 0)
  4072.         startcol = 0;
  4073.  
  4074. #ifdef FEAT_VREPLACE
  4075.         if (State & VREPLACE_FLAG)
  4076.         {
  4077.         /*
  4078.          * In VREPLACE mode, we will backspace over the text to be
  4079.          * wrapped, so save a copy now to put on the next line.
  4080.          */
  4081.         saved_text = vim_strsave(ml_get_cursor());
  4082.         curwin->w_cursor.col = orig_col;
  4083.         if (saved_text == NULL)
  4084.             break;    /* Can't do it, out of memory */
  4085.         saved_text[startcol] = NUL;
  4086.  
  4087.         /* Backspace over characters that will move to the next line */
  4088.         if (!fo_white_par)
  4089.             backspace_until_column(foundcol);
  4090.         }
  4091.         else
  4092. #endif
  4093.         {
  4094.         /* put cursor after pos. to break line */
  4095.         if (!fo_white_par)
  4096.             curwin->w_cursor.col = foundcol;
  4097.         }
  4098.  
  4099.         /*
  4100.          * Split the line just before the margin.
  4101.          * Only insert/delete lines, but don't really redraw the window.
  4102.          */
  4103.         open_line(FORWARD, OPENLINE_DELSPACES
  4104.             + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
  4105. #ifdef FEAT_COMMENTS
  4106.             + (do_comments ? OPENLINE_DO_COM : 0)
  4107. #endif
  4108.             , old_indent);
  4109.         old_indent = 0;
  4110.  
  4111.         replace_offset = 0;
  4112.         if (first_line)
  4113.         {
  4114.         if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
  4115.             second_indent = get_number_indent(curwin->w_cursor.lnum -1);
  4116.         if (second_indent >= 0)
  4117.         {
  4118. #ifdef FEAT_VREPLACE
  4119.             if (State & VREPLACE_FLAG)
  4120.             change_indent(INDENT_SET, second_indent, FALSE, NUL);
  4121.             else
  4122. #endif
  4123.             (void)set_indent(second_indent, SIN_CHANGED);
  4124.         }
  4125.         first_line = FALSE;
  4126.         }
  4127.  
  4128. #ifdef FEAT_VREPLACE
  4129.         if (State & VREPLACE_FLAG)
  4130.         {
  4131.         /*
  4132.          * In VREPLACE mode we have backspaced over the text to be
  4133.          * moved, now we re-insert it into the new line.
  4134.          */
  4135.         ins_bytes(saved_text);
  4136.         vim_free(saved_text);
  4137.         }
  4138.         else
  4139. #endif
  4140.         {
  4141.         /*
  4142.          * Check if cursor is not past the NUL off the line, cindent
  4143.          * may have added or removed indent.
  4144.          */
  4145.         curwin->w_cursor.col += startcol;
  4146.         len = (colnr_T)STRLEN(ml_get_curline());
  4147.         if (curwin->w_cursor.col > len)
  4148.             curwin->w_cursor.col = len;
  4149.         }
  4150.  
  4151.         haveto_redraw = TRUE;
  4152. #ifdef FEAT_CINDENT
  4153.         can_cindent = TRUE;
  4154. #endif
  4155.         /* moved the cursor, don't autoindent or cindent now */
  4156.         did_ai = FALSE;
  4157. #ifdef FEAT_SMARTINDENT
  4158.         did_si = FALSE;
  4159.         can_si = FALSE;
  4160.         can_si_back = FALSE;
  4161. #endif
  4162.         line_breakcheck();
  4163.     }
  4164.  
  4165.     if (save_char)            /* put back space after cursor */
  4166.         pchar_cursor(save_char);
  4167.  
  4168.     if (c == NUL)            /* formatting only */
  4169.         return;
  4170.     if (haveto_redraw)
  4171.     {
  4172.         update_topline();
  4173.         redraw_curbuf_later(VALID);
  4174.     }
  4175.     }
  4176.     if (c == NUL)        /* only formatting was wanted */
  4177.     return;
  4178.  
  4179. #ifdef FEAT_COMMENTS
  4180.     /* Check whether this character should end a comment. */
  4181.     if (did_ai && (int)c == end_comment_pending)
  4182.     {
  4183.     char_u  *line;
  4184.     char_u    lead_end[COM_MAX_LEN];        /* end-comment string */
  4185.     int    middle_len, end_len;
  4186.     int    i;
  4187.  
  4188.     /*
  4189.      * Need to remove existing (middle) comment leader and insert end
  4190.      * comment leader.  First, check what comment leader we can find.
  4191.      */
  4192.     i = get_leader_len(line = ml_get_curline(), &p, FALSE);
  4193.     if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL)    /* Just checking */
  4194.     {
  4195.         /* Skip middle-comment string */
  4196.         while (*p && p[-1] != ':')    /* find end of middle flags */
  4197.         ++p;
  4198.         middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
  4199.         /* Don't count trailing white space for middle_len */
  4200.         while (middle_len > 0 && vim_iswhite(lead_end[middle_len - 1]))
  4201.         --middle_len;
  4202.  
  4203.         /* Find the end-comment string */
  4204.         while (*p && p[-1] != ':')    /* find end of end flags */
  4205.         ++p;
  4206.         end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
  4207.  
  4208.         /* Skip white space before the cursor */
  4209.         i = curwin->w_cursor.col;
  4210.         while (--i >= 0 && vim_iswhite(line[i]))
  4211.         ;
  4212.         i++;
  4213.  
  4214.         /* Skip to before the middle leader */
  4215.         i -= middle_len;
  4216.  
  4217.         /* Check some expected things before we go on */
  4218.         if (i >= 0 && lead_end[end_len - 1] == end_comment_pending)
  4219.         {
  4220.         /* Backspace over all the stuff we want to replace */
  4221.         backspace_until_column(i);
  4222.  
  4223.         /*
  4224.          * Insert the end-comment string, except for the last
  4225.          * character, which will get inserted as normal later.
  4226.          */
  4227.         ins_bytes_len(lead_end, end_len - 1);
  4228.         }
  4229.     }
  4230.     }
  4231.     end_comment_pending = NUL;
  4232. #endif
  4233.  
  4234.     did_ai = FALSE;
  4235. #ifdef FEAT_SMARTINDENT
  4236.     did_si = FALSE;
  4237.     can_si = FALSE;
  4238.     can_si_back = FALSE;
  4239. #endif
  4240.  
  4241.     /*
  4242.      * If there's any pending input, grab up to INPUT_BUFLEN at once.
  4243.      * This speeds up normal text input considerably.
  4244.      * Don't do this when 'cindent' or 'indentexpr' is set, because we might
  4245.      * need to re-indent at a ':', or any other character (but not what
  4246.      * 'paste' is set)..
  4247.      */
  4248. #ifdef USE_ON_FLY_SCROLL
  4249.     dont_scroll = FALSE;        /* allow scrolling here */
  4250. #endif
  4251.  
  4252.     if (       !ISSPECIAL(c)
  4253. #ifdef FEAT_MBYTE
  4254.         && (!has_mbyte || (*mb_char2len)(c) == 1)
  4255. #endif
  4256.         && vpeekc() != NUL
  4257.         && !(State & REPLACE_FLAG)
  4258. #ifdef FEAT_CINDENT
  4259.         && !cindent_on()
  4260. #endif
  4261. #ifdef FEAT_RIGHTLEFT
  4262.         && !p_ri
  4263. #endif
  4264.            )
  4265.     {
  4266. #define INPUT_BUFLEN 100
  4267.     char_u        buf[INPUT_BUFLEN + 1];
  4268.     int        i;
  4269.     colnr_T        virtcol = 0;
  4270.  
  4271.     buf[0] = c;
  4272.     i = 1;
  4273.     if (textwidth)
  4274.         virtcol = get_nolist_virtcol();
  4275.     /*
  4276.      * Stop the string when:
  4277.      * - no more chars available
  4278.      * - finding a special character (command key)
  4279.      * - buffer is full
  4280.      * - running into the 'textwidth' boundary
  4281.      * - need to check for abbreviation: A non-word char after a word-char
  4282.      */
  4283.     while (       (c = vpeekc()) != NUL
  4284.         && !ISSPECIAL(c)
  4285. #ifdef FEAT_MBYTE
  4286.         && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
  4287. #endif
  4288.         && i < INPUT_BUFLEN
  4289.         && (textwidth == 0
  4290.             || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
  4291.         && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
  4292.     {
  4293. #ifdef FEAT_RIGHTLEFT
  4294.         c = vgetc();
  4295.         if (p_hkmap && KeyTyped)
  4296.         c = hkmap(c);            /* Hebrew mode mapping */
  4297. # ifdef FEAT_FKMAP
  4298.         if (p_fkmap && KeyTyped)
  4299.         c = fkmap(c);            /* Farsi mode mapping */
  4300. # endif
  4301.         buf[i++] = c;
  4302. #else
  4303.         buf[i++] = vgetc();
  4304. #endif
  4305.     }
  4306.  
  4307. #ifdef FEAT_DIGRAPHS
  4308.     do_digraph(-1);            /* clear digraphs */
  4309.     do_digraph(buf[i-1]);        /* may be the start of a digraph */
  4310. #endif
  4311.     buf[i] = NUL;
  4312.     ins_str(buf);
  4313.     if (flags & INSCHAR_CTRLV)
  4314.     {
  4315.         redo_literal(*buf);
  4316.         i = 1;
  4317.     }
  4318.     else
  4319.         i = 0;
  4320.     if (buf[i] != NUL)
  4321.         AppendToRedobuffLit(buf + i);
  4322.     }
  4323.     else
  4324.     {
  4325. #ifdef FEAT_MBYTE
  4326.     if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
  4327.     {
  4328.         char_u    buf[MB_MAXBYTES + 1];
  4329.  
  4330.         (*mb_char2bytes)(c, buf);
  4331.         buf[cc] = NUL;
  4332.         ins_char_bytes(buf, cc);
  4333.         AppendCharToRedobuff(c);
  4334.     }
  4335.     else
  4336. #endif
  4337.     {
  4338.         ins_char(c);
  4339.         if (flags & INSCHAR_CTRLV)
  4340.         redo_literal(c);
  4341.         else
  4342.         AppendCharToRedobuff(c);
  4343.     }
  4344.     }
  4345. }
  4346.  
  4347. /*
  4348.  * Called after inserting or deleting text: When 'formatoptions' includes the
  4349.  * 'a' flag format from the current line until the end of the paragraph.
  4350.  * Keep the cursor at the same position relative to the text.
  4351.  * The caller must have saved the cursor line for undo, following ones will be
  4352.  * saved here.
  4353.  */
  4354.     void
  4355. auto_format()
  4356. {
  4357.     pos_T    pos;
  4358.     colnr_T    len;
  4359.     char_u    *old, *pold;
  4360.     char_u    *new, *pnew;
  4361.  
  4362.     if (!has_format_option(FO_AUTO))
  4363.     return;
  4364.  
  4365.     pos = curwin->w_cursor;
  4366.     old = ml_get_curline();
  4367.  
  4368.     /* Don't format in Insert mode when the cursor is on a trailing blank, the
  4369.      * user might insert normal text next.  Also skip formatting when "1" is
  4370.      * in 'formatoptions' and there is a single character before the cursor.
  4371.      * Otherwise the line would be broken and when typing another non-white
  4372.      * next they are not joined back together. */
  4373.     if (*old != NUL && pos.col == STRLEN(old))
  4374.     {
  4375.     dec_cursor();
  4376.     if (!WHITECHAR(gchar_cursor())
  4377.         && curwin->w_cursor.col > 0
  4378.         && has_format_option(FO_ONE_LETTER))
  4379.         dec_cursor();
  4380.     if (WHITECHAR(gchar_cursor()))
  4381.     {
  4382.         curwin->w_cursor = pos;
  4383.         return;
  4384.     }
  4385.     curwin->w_cursor = pos;
  4386.     }
  4387.  
  4388. #ifdef FEAT_COMMENTS
  4389.     /* With the 'c' flag in 'formatoptions' and 't' missing: only format
  4390.      * comments. */
  4391.     if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
  4392.                      && get_leader_len(old, NULL, FALSE) == 0)
  4393.     return;
  4394. #endif
  4395.  
  4396.     old = vim_strsave(old);
  4397.     format_lines((linenr_T)-1);
  4398.  
  4399.     /* Advance to the same text position again.  This is tricky, indents
  4400.      * may have changed and comment leaders may have been inserted. */
  4401.     curwin->w_cursor.lnum = pos.lnum;
  4402.     curwin->w_cursor.col = 0;
  4403.     pold = old;
  4404.     while (1)
  4405.     {
  4406.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  4407.     {
  4408.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  4409.         curwin->w_cursor.col = MAXCOL;
  4410.         break;
  4411.     }
  4412.     /* Make "pold" and "pnew" point to the start of the line, ignoring
  4413.      * indent and comment leader. */
  4414.     pold = skipwhite(pold);
  4415.     new = ml_get_curline();
  4416.     pnew = skipwhite(new);
  4417. #ifdef FEAT_COMMENTS
  4418.     len = get_leader_len(new, NULL, FALSE);
  4419.     if (len > 0)
  4420.     {
  4421.         char_u    *p;
  4422.  
  4423.         /* Skip the leader if the old text matches after it, ignoring
  4424.          * white space.  Keep in mind that the leader may appear in
  4425.          * the text! */
  4426.         p = skipwhite(new + len);
  4427.         if (cmplen(pold, pnew) < cmplen(pold, p))
  4428.         pnew = p;
  4429.     }
  4430. #endif
  4431.  
  4432.     len = (colnr_T)STRLEN(pnew);
  4433.     if ((pold - old) + len >= pos.col)
  4434.     {
  4435.         curwin->w_cursor.col = pos.col - (pold - old) + (pnew - new);
  4436.         break;
  4437.     }
  4438.     /* Cursor wraps to next line */
  4439.     ++curwin->w_cursor.lnum;
  4440.     pold += len;
  4441.     }
  4442.     check_cursor();
  4443.     vim_free(old);
  4444. }
  4445.  
  4446. #ifdef FEAT_COMMENTS
  4447. /*
  4448.  * Return the number of bytes for which strings "s1" and "s2" are equal.
  4449.  */
  4450.     static int
  4451. cmplen(s1, s2)
  4452.     char_u    *s1;
  4453.     char_u    *s2;
  4454. {
  4455.     char_u    *p1 = s1, *p2 = s2;
  4456.  
  4457.     while (*p1 == *p2 && *p1 != NUL)
  4458.     {
  4459.     ++p1;
  4460.     ++p2;
  4461.     }
  4462.     return (int)(p1 - s1);
  4463. }
  4464. #endif
  4465.  
  4466. /*
  4467.  * Find out textwidth to be used for formatting:
  4468.  *    if 'textwidth' option is set, use it
  4469.  *    else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin'
  4470.  *    if invalid value, use 0.
  4471.  *    Set default to window width (maximum 79) for "Q" command.
  4472.  */
  4473.     int
  4474. comp_textwidth(ff)
  4475.     int        ff;    /* force formatting (for "Q" command) */
  4476. {
  4477.     int        textwidth;
  4478.  
  4479.     textwidth = curbuf->b_p_tw;
  4480.     if (textwidth == 0 && curbuf->b_p_wm)
  4481.     textwidth = W_WIDTH(curwin) - curbuf->b_p_wm;
  4482.     if (textwidth < 0)
  4483.     textwidth = 0;
  4484.     if (ff && textwidth == 0)
  4485.     {
  4486.     textwidth = W_WIDTH(curwin) - 1;
  4487.     if (textwidth > 79)
  4488.         textwidth = 79;
  4489.     }
  4490.     return textwidth;
  4491. }
  4492.  
  4493. /*
  4494.  * Put a character in the redo buffer, for when just after a CTRL-V.
  4495.  */
  4496.     static void
  4497. redo_literal(c)
  4498.     int        c;
  4499. {
  4500.     char_u    buf[10];
  4501.  
  4502.     /* Only digits need special treatment.  Translate them into a string of
  4503.      * three digits. */
  4504.     if (vim_isdigit(c))
  4505.     {
  4506.     sprintf((char *)buf, "%03d", c);
  4507.     AppendToRedobuff(buf);
  4508.     }
  4509.     else
  4510.     AppendCharToRedobuff(c);
  4511. }
  4512.  
  4513. /*
  4514.  * start_arrow() is called when an arrow key is used in insert mode.
  4515.  * It resembles hitting the <ESC> key.
  4516.  */
  4517.     static void
  4518. start_arrow(end_insert_pos)
  4519.     pos_T    *end_insert_pos;
  4520. {
  4521.     if (!arrow_used)        /* something has been inserted */
  4522.     {
  4523.     AppendToRedobuff(ESC_STR);
  4524.     arrow_used = TRUE;    /* this means we stopped the current insert */
  4525.     stop_insert(end_insert_pos);
  4526.     }
  4527. }
  4528.  
  4529. /*
  4530.  * stop_arrow() is called before a change is made in insert mode.
  4531.  * If an arrow key has been used, start a new insertion.
  4532.  * Returns FAIL if undo is impossible, shouldn't insert then.
  4533.  */
  4534.     int
  4535. stop_arrow()
  4536. {
  4537.     if (arrow_used)
  4538.     {
  4539.     if (u_save_cursor() == OK)
  4540.     {
  4541.         arrow_used = FALSE;
  4542.         ins_need_undo = FALSE;
  4543.     }
  4544.     Insstart = curwin->w_cursor;    /* new insertion starts here */
  4545.     Insstart_textlen = linetabsize(ml_get_curline());
  4546.     ai_col = 0;
  4547. #ifdef FEAT_VREPLACE
  4548.     if (State & VREPLACE_FLAG)
  4549.     {
  4550.         orig_line_count = curbuf->b_ml.ml_line_count;
  4551.         vr_lines_changed = 1;
  4552.     }
  4553. #endif
  4554.     ResetRedobuff();
  4555.     AppendToRedobuff((char_u *)"1i");   /* pretend we start an insertion */
  4556.     }
  4557.     else if (ins_need_undo)
  4558.     {
  4559.     if (u_save_cursor() == OK)
  4560.         ins_need_undo = FALSE;
  4561.     }
  4562.  
  4563. #ifdef FEAT_FOLDING
  4564.     /* Always open fold at the cursor line when inserting something. */
  4565.     foldOpenCursor();
  4566. #endif
  4567.  
  4568.     return (arrow_used || ins_need_undo ? FAIL : OK);
  4569. }
  4570.  
  4571. /*
  4572.  * do a few things to stop inserting
  4573.  */
  4574.     static void
  4575. stop_insert(end_insert_pos)
  4576.     pos_T    *end_insert_pos;    /* where insert ended */
  4577. {
  4578.     int        cc;
  4579.  
  4580.     stop_redo_ins();
  4581.     replace_flush();        /* abandon replace stack */
  4582.  
  4583.     /*
  4584.      * save the inserted text for later redo with ^@
  4585.      */
  4586.     vim_free(last_insert);
  4587.     last_insert = get_inserted();
  4588.     last_insert_skip = new_insert_skip;
  4589.  
  4590.     /*
  4591.      * If we just did an auto-indent, remove the white space from the end of
  4592.      * the line, and put the cursor back.
  4593.      */
  4594.     if (did_ai && !arrow_used)
  4595.     {
  4596.     if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
  4597.         --curwin->w_cursor.col;
  4598.     while (cc = gchar_cursor(), vim_iswhite(cc))
  4599.         (void)del_char(TRUE);
  4600.     if (cc != NUL)
  4601.         ++curwin->w_cursor.col;    /* put cursor back on the NUL */
  4602.  
  4603. #ifdef FEAT_VISUAL
  4604.     /* <C-S-Right> may have started Visual mode, adjust the position for
  4605.      * deleted characters. */
  4606.     if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum)
  4607.     {
  4608.         cc = STRLEN(ml_get_curline());
  4609.         if (VIsual.col > (colnr_T)cc)
  4610.         {
  4611.         VIsual.col = cc;
  4612. # ifdef FEAT_VIRTUALEDIT
  4613.         VIsual.coladd = 0;
  4614. # endif
  4615.         }
  4616.     }
  4617. #endif
  4618.     }
  4619.     did_ai = FALSE;
  4620. #ifdef FEAT_SMARTINDENT
  4621.     did_si = FALSE;
  4622.     can_si = FALSE;
  4623.     can_si_back = FALSE;
  4624. #endif
  4625.  
  4626.     /* set '[ and '] to the inserted text */
  4627.     curbuf->b_op_start = Insstart;
  4628.     curbuf->b_op_end = *end_insert_pos;
  4629. }
  4630.  
  4631. /*
  4632.  * Set the last inserted text to a single character.
  4633.  * Used for the replace command.
  4634.  */
  4635.     void
  4636. set_last_insert(c)
  4637.     int        c;
  4638. {
  4639.     char_u    *s;
  4640.  
  4641.     vim_free(last_insert);
  4642. #ifdef FEAT_MBYTE
  4643.     last_insert = alloc(MB_MAXBYTES * 3 + 5);
  4644. #else
  4645.     last_insert = alloc(6);
  4646. #endif
  4647.     if (last_insert != NULL)
  4648.     {
  4649.     s = last_insert;
  4650.     /* Use the CTRL-V only when entering a special char */
  4651.     if (c < ' ' || c == DEL)
  4652.         *s++ = Ctrl_V;
  4653.     s = add_char2buf(c, s);
  4654.     *s++ = ESC;
  4655.     *s++ = NUL;
  4656.     last_insert_skip = 0;
  4657.     }
  4658. }
  4659.  
  4660. /*
  4661.  * Add character "c" to buffer "s".  Escape the special meaning of K_SPECIAL
  4662.  * and CSI.  Handle multi-byte characters.
  4663.  * Returns a pointer to after the added bytes.
  4664.  */
  4665.     char_u *
  4666. add_char2buf(c, s)
  4667.     int        c;
  4668.     char_u    *s;
  4669. {
  4670. #ifdef FEAT_MBYTE
  4671.     char_u    temp[MB_MAXBYTES];
  4672.     int        i;
  4673.     int        len;
  4674.  
  4675.     len = (*mb_char2bytes)(c, temp);
  4676.     for (i = 0; i < len; ++i)
  4677.     {
  4678.     c = temp[i];
  4679. #endif
  4680.     /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */
  4681.     if (c == K_SPECIAL)
  4682.     {
  4683.         *s++ = K_SPECIAL;
  4684.         *s++ = KS_SPECIAL;
  4685.         *s++ = KE_FILLER;
  4686.     }
  4687. #ifdef FEAT_GUI
  4688.     else if (c == CSI)
  4689.     {
  4690.         *s++ = CSI;
  4691.         *s++ = KS_EXTRA;
  4692.         *s++ = (int)KE_CSI;
  4693.     }
  4694. #endif
  4695.     else
  4696.         *s++ = c;
  4697. #ifdef FEAT_MBYTE
  4698.     }
  4699. #endif
  4700.     return s;
  4701. }
  4702.  
  4703. /*
  4704.  * move cursor to start of line
  4705.  * if flags & BL_WHITE    move to first non-white
  4706.  * if flags & BL_SOL    move to first non-white if startofline is set,
  4707.  *                otherwise keep "curswant" column
  4708.  * if flags & BL_FIX    don't leave the cursor on a NUL.
  4709.  */
  4710.     void
  4711. beginline(flags)
  4712.     int        flags;
  4713. {
  4714.     if ((flags & BL_SOL) && !p_sol)
  4715.     coladvance(curwin->w_curswant);
  4716.     else
  4717.     {
  4718.     curwin->w_cursor.col = 0;
  4719. #ifdef FEAT_VIRTUALEDIT
  4720.     curwin->w_cursor.coladd = 0;
  4721. #endif
  4722.  
  4723.     if (flags & (BL_WHITE | BL_SOL))
  4724.     {
  4725.         char_u  *ptr;
  4726.  
  4727.         for (ptr = ml_get_curline(); vim_iswhite(*ptr)
  4728.                    && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
  4729.         ++curwin->w_cursor.col;
  4730.     }
  4731.     curwin->w_set_curswant = TRUE;
  4732.     }
  4733. }
  4734.  
  4735. /*
  4736.  * oneright oneleft cursor_down cursor_up
  4737.  *
  4738.  * Move one char {right,left,down,up}.
  4739.  * Doesn't move onto the NUL past the end of the line.
  4740.  * Return OK when successful, FAIL when we hit a line of file boundary.
  4741.  */
  4742.  
  4743.     int
  4744. oneright()
  4745. {
  4746.     char_u    *ptr;
  4747. #ifdef FEAT_MBYTE
  4748.     int        l;
  4749. #endif
  4750.  
  4751. #ifdef FEAT_VIRTUALEDIT
  4752.     if (virtual_active())
  4753.     {
  4754.     /* Adjust for multi-wide char (excluding TAB) */
  4755.     ptr = ml_get_cursor();
  4756.     coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(
  4757. #ifdef FEAT_MBYTE
  4758.                 (*mb_ptr2char)(ptr)
  4759. #else
  4760.                 *ptr
  4761. #endif
  4762.                 ))
  4763.             ? ptr2cells(ptr) : 1));
  4764.     curwin->w_set_curswant = TRUE;
  4765.     return OK;
  4766.     }
  4767. #endif
  4768.  
  4769.     ptr = ml_get_cursor();
  4770. #ifdef FEAT_MBYTE
  4771.     if (has_mbyte && (l = (*mb_ptr2len_check)(ptr)) > 1)
  4772.     {
  4773.     /* The character under the cursor is a multi-byte character, move
  4774.      * several bytes right, but don't end up on the NUL. */
  4775.     if (ptr[l] == NUL)
  4776.         return FAIL;
  4777.     curwin->w_cursor.col += l;
  4778.     }
  4779.     else
  4780. #endif
  4781.     {
  4782.     if (*ptr++ == NUL || *ptr == NUL)
  4783.         return FAIL;
  4784.     ++curwin->w_cursor.col;
  4785.     }
  4786.  
  4787.     curwin->w_set_curswant = TRUE;
  4788.     return OK;
  4789. }
  4790.  
  4791.     int
  4792. oneleft()
  4793. {
  4794. #ifdef FEAT_VIRTUALEDIT
  4795.     if (virtual_active())
  4796.     {
  4797.     int width;
  4798.     int v = getviscol();
  4799.  
  4800.     if (v == 0)
  4801.         return FAIL;
  4802.  
  4803. # ifdef FEAT_LINEBREAK
  4804.     /* We might get stuck on 'showbreak', skip over it. */
  4805.     width = 1;
  4806.     for (;;)
  4807.     {
  4808.         coladvance(v - width);
  4809.         /* getviscol() is slow, skip it when 'showbreak' is empty and
  4810.          * there are no multi-byte characters */
  4811.         if ((*p_sbr == NUL
  4812. #  ifdef FEAT_MBYTE
  4813.             && !has_mbyte
  4814. #  endif
  4815.             ) || getviscol() < v)
  4816.         break;
  4817.         ++width;
  4818.     }
  4819. # else
  4820.     coladvance(v - 1);
  4821. # endif
  4822.  
  4823.     if (curwin->w_cursor.coladd == 1)
  4824.     {
  4825.         char_u *ptr;
  4826.  
  4827.         /* Adjust for multi-wide char (not a TAB) */
  4828.         ptr = ml_get_cursor();
  4829.         if (*ptr != TAB && vim_isprintc(
  4830. #  ifdef FEAT_MBYTE
  4831.                 (*mb_ptr2char)(ptr)
  4832. #  else
  4833.                 *ptr
  4834. #  endif
  4835.                 ) && ptr2cells(ptr) > 1)
  4836.         curwin->w_cursor.coladd = 0;
  4837.     }
  4838.  
  4839.     curwin->w_set_curswant = TRUE;
  4840.     return OK;
  4841.     }
  4842. #endif
  4843.  
  4844.     if (curwin->w_cursor.col == 0)
  4845.     return FAIL;
  4846.  
  4847.     curwin->w_set_curswant = TRUE;
  4848.     --curwin->w_cursor.col;
  4849.  
  4850. #ifdef FEAT_MBYTE
  4851.     /* if the character on the left of the current cursor is a multi-byte
  4852.      * character, move to its first byte */
  4853.     if (has_mbyte)
  4854.     mb_adjust_cursor();
  4855. #endif
  4856.     return OK;
  4857. }
  4858.  
  4859.     int
  4860. cursor_up(n, upd_topline)
  4861.     long    n;
  4862.     int        upd_topline;        /* When TRUE: update topline */
  4863. {
  4864.     linenr_T    lnum;
  4865.  
  4866.     if (n > 0)
  4867.     {
  4868.     lnum = curwin->w_cursor.lnum;
  4869.     if (lnum <= 1)
  4870.         return FAIL;
  4871.     if (n >= lnum)
  4872.         lnum = 1;
  4873.     else
  4874. #ifdef FEAT_FOLDING
  4875.         if (hasAnyFolding(curwin))
  4876.     {
  4877.         /*
  4878.          * Count each sequence of folded lines as one logical line.
  4879.          */
  4880.         /* go to the the start of the current fold */
  4881.         (void)hasFolding(lnum, &lnum, NULL);
  4882.  
  4883.         while (n--)
  4884.         {
  4885.         /* move up one line */
  4886.         --lnum;
  4887.         if (lnum <= 1)
  4888.             break;
  4889.         /* If we entered a fold, move to the beginning, unless in
  4890.          * Insert mode or when 'foldopen' contains "all": it will open
  4891.          * in a moment. */
  4892.         if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL)))
  4893.             (void)hasFolding(lnum, &lnum, NULL);
  4894.         }
  4895.         if (lnum < 1)
  4896.         lnum = 1;
  4897.     }
  4898.     else
  4899. #endif
  4900.         lnum -= n;
  4901.     curwin->w_cursor.lnum = lnum;
  4902.     }
  4903.  
  4904.     /* try to advance to the column we want to be at */
  4905.     coladvance(curwin->w_curswant);
  4906.  
  4907.     if (upd_topline)
  4908.     update_topline();    /* make sure curwin->w_topline is valid */
  4909.  
  4910.     return OK;
  4911. }
  4912.  
  4913. /*
  4914.  * Cursor down a number of logical lines.
  4915.  */
  4916.     int
  4917. cursor_down(n, upd_topline)
  4918.     long    n;
  4919.     int        upd_topline;        /* When TRUE: update topline */
  4920. {
  4921.     linenr_T    lnum;
  4922.  
  4923.     if (n > 0)
  4924.     {
  4925.     lnum = curwin->w_cursor.lnum;
  4926. #ifdef FEAT_FOLDING
  4927.     /* Move to last line of fold, will fail if it's the end-of-file. */
  4928.     (void)hasFolding(lnum, NULL, &lnum);
  4929. #endif
  4930.     if (lnum >= curbuf->b_ml.ml_line_count)
  4931.         return FAIL;
  4932.     if (lnum + n >= curbuf->b_ml.ml_line_count)
  4933.         lnum = curbuf->b_ml.ml_line_count;
  4934.     else
  4935. #ifdef FEAT_FOLDING
  4936.     if (hasAnyFolding(curwin))
  4937.     {
  4938.         linenr_T    last;
  4939.  
  4940.         /* count each sequence of folded lines as one logical line */
  4941.         while (n--)
  4942.         {
  4943.         if (hasFolding(lnum, NULL, &last))
  4944.             lnum = last + 1;
  4945.         else
  4946.             ++lnum;
  4947.         if (lnum >= curbuf->b_ml.ml_line_count)
  4948.             break;
  4949.         }
  4950.         if (lnum > curbuf->b_ml.ml_line_count)
  4951.         lnum = curbuf->b_ml.ml_line_count;
  4952.     }
  4953.     else
  4954. #endif
  4955.         lnum += n;
  4956.     curwin->w_cursor.lnum = lnum;
  4957.     }
  4958.  
  4959.     /* try to advance to the column we want to be at */
  4960.     coladvance(curwin->w_curswant);
  4961.  
  4962.     if (upd_topline)
  4963.     update_topline();    /* make sure curwin->w_topline is valid */
  4964.  
  4965.     return OK;
  4966. }
  4967.  
  4968. /*
  4969.  * Stuff the last inserted text in the read buffer.
  4970.  * Last_insert actually is a copy of the redo buffer, so we
  4971.  * first have to remove the command.
  4972.  */
  4973.     int
  4974. stuff_inserted(c, count, no_esc)
  4975.     int        c;        /* Command character to be inserted */
  4976.     long    count;    /* Repeat this many times */
  4977.     int        no_esc;    /* Don't add an ESC at the end */
  4978. {
  4979.     char_u    *esc_ptr;
  4980.     char_u    *ptr;
  4981.     char_u    *last_ptr;
  4982.     char_u    last = NUL;
  4983.  
  4984.     ptr = get_last_insert();
  4985.     if (ptr == NULL)
  4986.     {
  4987.     EMSG(_(e_noinstext));
  4988.     return FAIL;
  4989.     }
  4990.  
  4991.     /* may want to stuff the command character, to start Insert mode */
  4992.     if (c != NUL)
  4993.     stuffcharReadbuff(c);
  4994.     if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
  4995.     *esc_ptr = NUL;        /* remove the ESC */
  4996.  
  4997.     /* when the last char is either "0" or "^" it will be quoted if no ESC
  4998.      * comes after it OR if it will inserted more than once and "ptr"
  4999.      * starts with ^D.    -- Acevedo
  5000.      */
  5001.     last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
  5002.     if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
  5003.         && (no_esc || (*ptr == Ctrl_D && count > 1)))
  5004.     {
  5005.     last = *last_ptr;
  5006.     *last_ptr = NUL;
  5007.     }
  5008.  
  5009.     do
  5010.     {
  5011.     stuffReadbuff(ptr);
  5012.     /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
  5013.     if (last)
  5014.         stuffReadbuff((char_u *)(last == '0'
  5015.             ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0")
  5016.             : IF_EB("\026^", CTRL_V_STR "^")));
  5017.     }
  5018.     while (--count > 0);
  5019.  
  5020.     if (last)
  5021.     *last_ptr = last;
  5022.  
  5023.     if (esc_ptr != NULL)
  5024.     *esc_ptr = ESC;        /* put the ESC back */
  5025.  
  5026.     /* may want to stuff a trailing ESC, to get out of Insert mode */
  5027.     if (!no_esc)
  5028.     stuffcharReadbuff(ESC);
  5029.  
  5030.     return OK;
  5031. }
  5032.  
  5033.     char_u *
  5034. get_last_insert()
  5035. {
  5036.     if (last_insert == NULL)
  5037.     return NULL;
  5038.     return last_insert + last_insert_skip;
  5039. }
  5040.  
  5041. /*
  5042.  * Get last inserted string, and remove trailing <Esc>.
  5043.  * Returns pointer to allocated memory (must be freed) or NULL.
  5044.  */
  5045.     char_u *
  5046. get_last_insert_save()
  5047. {
  5048.     char_u    *s;
  5049.     int        len;
  5050.  
  5051.     if (last_insert == NULL)
  5052.     return NULL;
  5053.     s = vim_strsave(last_insert + last_insert_skip);
  5054.     if (s != NULL)
  5055.     {
  5056.     len = (int)STRLEN(s);
  5057.     if (len > 0 && s[len - 1] == ESC)    /* remove trailing ESC */
  5058.         s[len - 1] = NUL;
  5059.     }
  5060.     return s;
  5061. }
  5062.  
  5063. /*
  5064.  * Check the word in front of the cursor for an abbreviation.
  5065.  * Called when the non-id character "c" has been entered.
  5066.  * When an abbreviation is recognized it is removed from the text and
  5067.  * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
  5068.  */
  5069.     static int
  5070. echeck_abbr(c)
  5071.     int c;
  5072. {
  5073.     /* Don't check for abbreviation in paste mode, when disabled and just
  5074.      * after moving around with cursor keys. */
  5075.     if (p_paste || no_abbr || arrow_used)
  5076.     return FALSE;
  5077.  
  5078.     return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
  5079.         curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
  5080. }
  5081.  
  5082. /*
  5083.  * replace-stack functions
  5084.  *
  5085.  * When replacing characters, the replaced characters are remembered for each
  5086.  * new character.  This is used to re-insert the old text when backspacing.
  5087.  *
  5088.  * There is a NUL headed list of characters for each character that is
  5089.  * currently in the file after the insertion point.  When BS is used, one NUL
  5090.  * headed list is put back for the deleted character.
  5091.  *
  5092.  * For a newline, there are two NUL headed lists.  One contains the characters
  5093.  * that the NL replaced.  The extra one stores the characters after the cursor
  5094.  * that were deleted (always white space).
  5095.  *
  5096.  * Replace_offset is normally 0, in which case replace_push will add a new
  5097.  * character at the end of the stack.  If replace_offset is not 0, that many
  5098.  * characters will be left on the stack above the newly inserted character.
  5099.  */
  5100.  
  5101. char_u    *replace_stack = NULL;
  5102. long    replace_stack_nr = 0;        /* next entry in replace stack */
  5103. long    replace_stack_len = 0;        /* max. number of entries */
  5104.  
  5105.     void
  5106. replace_push(c)
  5107.     int        c;        /* character that is replaced (NUL is none) */
  5108. {
  5109.     char_u  *p;
  5110.  
  5111.     if (replace_stack_nr < replace_offset)    /* nothing to do */
  5112.     return;
  5113.     if (replace_stack_len <= replace_stack_nr)
  5114.     {
  5115.     replace_stack_len += 50;
  5116.     p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
  5117.     if (p == NULL)        /* out of memory */
  5118.     {
  5119.         replace_stack_len -= 50;
  5120.         return;
  5121.     }
  5122.     if (replace_stack != NULL)
  5123.     {
  5124.         mch_memmove(p, replace_stack,
  5125.                  (size_t)(replace_stack_nr * sizeof(char_u)));
  5126.         vim_free(replace_stack);
  5127.     }
  5128.     replace_stack = p;
  5129.     }
  5130.     p = replace_stack + replace_stack_nr - replace_offset;
  5131.     if (replace_offset)
  5132.     mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
  5133.     *p = c;
  5134.     ++replace_stack_nr;
  5135. }
  5136.  
  5137. /*
  5138.  * call replace_push(c) with replace_offset set to the first NUL.
  5139.  */
  5140.     static void
  5141. replace_push_off(c)
  5142.     int        c;
  5143. {
  5144.     char_u    *p;
  5145.  
  5146.     p = replace_stack + replace_stack_nr;
  5147.     for (replace_offset = 1; replace_offset < replace_stack_nr;
  5148.                                  ++replace_offset)
  5149.     if (*--p == NUL)
  5150.         break;
  5151.     replace_push(c);
  5152.     replace_offset = 0;
  5153. }
  5154.  
  5155. /*
  5156.  * Pop one item from the replace stack.
  5157.  * return -1 if stack empty
  5158.  * return replaced character or NUL otherwise
  5159.  */
  5160.     static int
  5161. replace_pop()
  5162. {
  5163.     if (replace_stack_nr == 0)
  5164.     return -1;
  5165.     return (int)replace_stack[--replace_stack_nr];
  5166. }
  5167.  
  5168. /*
  5169.  * Join the top two items on the replace stack.  This removes to "off"'th NUL
  5170.  * encountered.
  5171.  */
  5172.     static void
  5173. replace_join(off)
  5174.     int        off;    /* offset for which NUL to remove */
  5175. {
  5176.     int        i;
  5177.  
  5178.     for (i = replace_stack_nr; --i >= 0; )
  5179.     if (replace_stack[i] == NUL && off-- <= 0)
  5180.     {
  5181.         --replace_stack_nr;
  5182.         mch_memmove(replace_stack + i, replace_stack + i + 1,
  5183.                           (size_t)(replace_stack_nr - i));
  5184.         return;
  5185.     }
  5186. }
  5187.  
  5188. /*
  5189.  * Pop bytes from the replace stack until a NUL is found, and insert them
  5190.  * before the cursor.  Can only be used in REPLACE or VREPLACE mode.
  5191.  */
  5192.     static void
  5193. replace_pop_ins()
  5194. {
  5195.     int        cc;
  5196.     int        oldState = State;
  5197.  
  5198.     State = NORMAL;            /* don't want REPLACE here */
  5199.     while ((cc = replace_pop()) > 0)
  5200.     {
  5201. #ifdef FEAT_MBYTE
  5202.     mb_replace_pop_ins(cc);
  5203. #else
  5204.     ins_char(cc);
  5205. #endif
  5206.     dec_cursor();
  5207.     }
  5208.     State = oldState;
  5209. }
  5210.  
  5211. #ifdef FEAT_MBYTE
  5212. /*
  5213.  * Insert bytes popped from the replace stack. "cc" is the first byte.  If it
  5214.  * indicates a multi-byte char, pop the other bytes too.
  5215.  */
  5216.     static void
  5217. mb_replace_pop_ins(cc)
  5218.     int        cc;
  5219. {
  5220.     int        n;
  5221.     char_u    buf[MB_MAXBYTES];
  5222.     int        i;
  5223.     int        c;
  5224.  
  5225.     if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1)
  5226.     {
  5227.     buf[0] = cc;
  5228.     for (i = 1; i < n; ++i)
  5229.         buf[i] = replace_pop();
  5230.     ins_bytes_len(buf, n);
  5231.     }
  5232.     else
  5233.     ins_char(cc);
  5234.  
  5235.     if (enc_utf8)
  5236.     /* Handle composing chars. */
  5237.     for (;;)
  5238.     {
  5239.         c = replace_pop();
  5240.         if (c == -1)        /* stack empty */
  5241.         break;
  5242.         if ((n = MB_BYTE2LEN(c)) == 1)
  5243.         {
  5244.         /* Not a multi-byte char, put it back. */
  5245.         replace_push(c);
  5246.         break;
  5247.         }
  5248.         else
  5249.         {
  5250.         buf[0] = c;
  5251.         for (i = 1; i < n; ++i)
  5252.             buf[i] = replace_pop();
  5253.         if (utf_iscomposing(utf_ptr2char(buf)))
  5254.             ins_bytes_len(buf, n);
  5255.         else
  5256.         {
  5257.             /* Not a composing char, put it back. */
  5258.             for (i = n - 1; i >= 0; --i)
  5259.             replace_push(buf[i]);
  5260.             break;
  5261.         }
  5262.         }
  5263.     }
  5264. }
  5265. #endif
  5266.  
  5267. /*
  5268.  * make the replace stack empty
  5269.  * (called when exiting replace mode)
  5270.  */
  5271.     static void
  5272. replace_flush()
  5273. {
  5274.     vim_free(replace_stack);
  5275.     replace_stack = NULL;
  5276.     replace_stack_len = 0;
  5277.     replace_stack_nr = 0;
  5278. }
  5279.  
  5280. /*
  5281.  * Handle doing a BS for one character.
  5282.  * cc < 0: replace stack empty, just move cursor
  5283.  * cc == 0: character was inserted, delete it
  5284.  * cc > 0: character was replaced, put cc (first byte of original char) back
  5285.  * and check for more characters to be put back
  5286.  */
  5287.     static void
  5288. replace_do_bs()
  5289. {
  5290.     int        cc;
  5291. #ifdef FEAT_VREPLACE
  5292.     int        orig_len = 0;
  5293.     int        ins_len;
  5294.     int        orig_vcols = 0;
  5295.     colnr_T    start_vcol;
  5296.     char_u    *p;
  5297.     int        i;
  5298.     int        vcol;
  5299. #endif
  5300.  
  5301.     cc = replace_pop();
  5302.     if (cc > 0)
  5303.     {
  5304. #ifdef FEAT_VREPLACE
  5305.     if (State & VREPLACE_FLAG)
  5306.     {
  5307.         /* Get the number of screen cells used by the character we are
  5308.          * going to delete. */
  5309.         getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
  5310.         orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
  5311.     }
  5312. #endif
  5313. #ifdef FEAT_MBYTE
  5314.     if (has_mbyte)
  5315.     {
  5316.         del_char(FALSE);
  5317. # ifdef FEAT_VREPLACE
  5318.         if (State & VREPLACE_FLAG)
  5319.         orig_len = STRLEN(ml_get_cursor());
  5320. # endif
  5321.         replace_push(cc);
  5322.     }
  5323.     else
  5324. #endif
  5325.     {
  5326.         pchar_cursor(cc);
  5327. #ifdef FEAT_VREPLACE
  5328.         if (State & VREPLACE_FLAG)
  5329.         orig_len = STRLEN(ml_get_cursor()) - 1;
  5330. #endif
  5331.     }
  5332.     replace_pop_ins();
  5333.  
  5334. #ifdef FEAT_VREPLACE
  5335.     if (State & VREPLACE_FLAG)
  5336.     {
  5337.         /* Get the number of screen cells used by the inserted characters */
  5338.         p = ml_get_cursor();
  5339.         ins_len = STRLEN(p) - orig_len;
  5340.         vcol = start_vcol;
  5341.         for (i = 0; i < ins_len; ++i)
  5342.         {
  5343.         vcol += chartabsize(p + i, vcol);
  5344. #ifdef FEAT_MBYTE
  5345.         i += (*mb_ptr2len_check)(p) - 1;
  5346. #endif
  5347.         }
  5348.         vcol -= start_vcol;
  5349.  
  5350.         /* Delete spaces that were inserted after the cursor to keep the
  5351.          * text aligned. */
  5352.         curwin->w_cursor.col += ins_len;
  5353.         while (vcol > orig_vcols && gchar_cursor() == ' ')
  5354.         {
  5355.         del_char(FALSE);
  5356.         ++orig_vcols;
  5357.         }
  5358.         curwin->w_cursor.col -= ins_len;
  5359.     }
  5360. #endif
  5361.  
  5362.     /* mark the buffer as changed and prepare for displaying */
  5363.     changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
  5364.     }
  5365.     else if (cc == 0)
  5366.     (void)del_char(FALSE);
  5367. }
  5368.  
  5369. #ifdef FEAT_CINDENT
  5370. /*
  5371.  * Return TRUE if C-indenting is on.
  5372.  */
  5373.     static int
  5374. cindent_on()
  5375. {
  5376.     return (!p_paste && (curbuf->b_p_cin
  5377. # ifdef FEAT_EVAL
  5378.             || *curbuf->b_p_inde != NUL
  5379. # endif
  5380.             ));
  5381. }
  5382. #endif
  5383.  
  5384. #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
  5385. /*
  5386.  * Re-indent the current line, based on the current contents of it and the
  5387.  * surrounding lines. Fixing the cursor position seems really easy -- I'm very
  5388.  * confused what all the part that handles Control-T is doing that I'm not.
  5389.  * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
  5390.  */
  5391.  
  5392.     void
  5393. fixthisline(get_the_indent)
  5394.     int (*get_the_indent) __ARGS((void));
  5395. {
  5396.     change_indent(INDENT_SET, get_the_indent(), FALSE, 0);
  5397.     if (linewhite(curwin->w_cursor.lnum))
  5398.     did_ai = TRUE;        /* delete the indent if the line stays empty */
  5399. }
  5400.  
  5401.     void
  5402. fix_indent()
  5403. {
  5404.     if (p_paste)
  5405.     return;
  5406. # ifdef FEAT_LISP
  5407.     if (curbuf->b_p_lisp && curbuf->b_p_ai)
  5408.     fixthisline(get_lisp_indent);
  5409. # endif
  5410. # if defined(FEAT_LISP) && defined(FEAT_CINDENT)
  5411.     else
  5412. # endif
  5413. # ifdef FEAT_CINDENT
  5414.     if (cindent_on())
  5415.         do_c_expr_indent();
  5416. # endif
  5417. }
  5418.  
  5419. #endif
  5420.  
  5421. #ifdef FEAT_CINDENT
  5422. /*
  5423.  * return TRUE if 'cinkeys' contains the key "keytyped",
  5424.  * when == '*':        Only if key is preceded with '*'    (indent before insert)
  5425.  * when == '!':        Only if key is prededed with '!'    (don't insert)
  5426.  * when == ' ':        Only if key is not preceded with '*'(indent afterwards)
  5427.  *
  5428.  * "keytyped" can have a few special values:
  5429.  * KEY_OPEN_FORW
  5430.  * KEY_OPEN_BACK
  5431.  * KEY_COMPLETE        just finished completion.
  5432.  *
  5433.  * If line_is_empty is TRUE accept keys with '0' before them.
  5434.  */
  5435.     int
  5436. in_cinkeys(keytyped, when, line_is_empty)
  5437.     int        keytyped;
  5438.     int        when;
  5439.     int        line_is_empty;
  5440. {
  5441.     char_u    *look;
  5442.     int        try_match;
  5443.     int        try_match_word;
  5444.     char_u    *p;
  5445.     char_u    *line;
  5446.     int        icase;
  5447.     int        i;
  5448.  
  5449. #ifdef FEAT_EVAL
  5450.     if (*curbuf->b_p_inde != NUL)
  5451.     look = curbuf->b_p_indk;    /* 'indentexpr' set: use 'indentkeys' */
  5452.     else
  5453. #endif
  5454.     look = curbuf->b_p_cink;    /* 'indentexpr' empty: use 'cinkeys' */
  5455.     while (*look)
  5456.     {
  5457.     /*
  5458.      * Find out if we want to try a match with this key, depending on
  5459.      * 'when' and a '*' or '!' before the key.
  5460.      */
  5461.     switch (when)
  5462.     {
  5463.         case '*': try_match = (*look == '*'); break;
  5464.         case '!': try_match = (*look == '!'); break;
  5465.          default: try_match = (*look != '*'); break;
  5466.     }
  5467.     if (*look == '*' || *look == '!')
  5468.         ++look;
  5469.  
  5470.     /*
  5471.      * If there is a '0', only accept a match if the line is empty.
  5472.      * But may still match when typing last char of a word.
  5473.      */
  5474.     if (*look == '0')
  5475.     {
  5476.         try_match_word = try_match;
  5477.         if (!line_is_empty)
  5478.         try_match = FALSE;
  5479.         ++look;
  5480.     }
  5481.     else
  5482.         try_match_word = FALSE;
  5483.  
  5484.     /*
  5485.      * does it look like a control character?
  5486.      */
  5487.     if (*look == '^'
  5488. #ifdef EBCDIC
  5489.         && (Ctrl_chr(look[1]) != 0)
  5490. #else
  5491.         && look[1] >= '?' && look[1] <= '_'
  5492. #endif
  5493.         )
  5494.     {
  5495.         if (try_match && keytyped == Ctrl_chr(look[1]))
  5496.         return TRUE;
  5497.         look += 2;
  5498.     }
  5499.     /*
  5500.      * 'o' means "o" command, open forward.
  5501.      * 'O' means "O" command, open backward.
  5502.      */
  5503.     else if (*look == 'o')
  5504.     {
  5505.         if (try_match && keytyped == KEY_OPEN_FORW)
  5506.         return TRUE;
  5507.         ++look;
  5508.     }
  5509.     else if (*look == 'O')
  5510.     {
  5511.         if (try_match && keytyped == KEY_OPEN_BACK)
  5512.         return TRUE;
  5513.         ++look;
  5514.     }
  5515.  
  5516.     /*
  5517.      * 'e' means to check for "else" at start of line and just before the
  5518.      * cursor.
  5519.      */
  5520.     else if (*look == 'e')
  5521.     {
  5522.         if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
  5523.         {
  5524.         p = ml_get_curline();
  5525.         if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
  5526.             STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
  5527.             return TRUE;
  5528.         }
  5529.         ++look;
  5530.     }
  5531.  
  5532.     /*
  5533.      * ':' only causes an indent if it is at the end of a label or case
  5534.      * statement, or when it was before typing the ':' (to fix
  5535.      * class::method for C++).
  5536.      */
  5537.     else if (*look == ':')
  5538.     {
  5539.         if (try_match && keytyped == ':')
  5540.         {
  5541.         p = ml_get_curline();
  5542.         if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30))
  5543.             return TRUE;
  5544.         if (curwin->w_cursor.col > 2
  5545.             && p[curwin->w_cursor.col - 1] == ':'
  5546.             && p[curwin->w_cursor.col - 2] == ':')
  5547.         {
  5548.             p[curwin->w_cursor.col - 1] = ' ';
  5549.             i = (cin_iscase(p) || cin_isscopedecl(p)
  5550.                               || cin_islabel(30));
  5551.             p = ml_get_curline();
  5552.             p[curwin->w_cursor.col - 1] = ':';
  5553.             if (i)
  5554.             return TRUE;
  5555.         }
  5556.         }
  5557.         ++look;
  5558.     }
  5559.  
  5560.  
  5561.     /*
  5562.      * Is it a key in <>, maybe?
  5563.      */
  5564.     else if (*look == '<')
  5565.     {
  5566.         if (try_match)
  5567.         {
  5568.         /*
  5569.          * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
  5570.          * <:> and <!> so that people can re-indent on o, O, e, 0, <,
  5571.          * >, *, : and ! keys if they really really want to.
  5572.          */
  5573.         if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
  5574.                                && keytyped == look[1])
  5575.             return TRUE;
  5576.  
  5577.         if (keytyped == get_special_key_code(look + 1))
  5578.             return TRUE;
  5579.         }
  5580.         while (*look && *look != '>')
  5581.         look++;
  5582.         while (*look == '>')
  5583.         look++;
  5584.     }
  5585.  
  5586.     /*
  5587.      * Is it a word: "=word"?
  5588.      */
  5589.     else if (*look == '=' && look[1] != ',' && look[1] != NUL)
  5590.     {
  5591.         ++look;
  5592.         if (*look == '~')
  5593.         {
  5594.         icase = TRUE;
  5595.         ++look;
  5596.         }
  5597.         else
  5598.         icase = FALSE;
  5599.         p = vim_strchr(look, ',');
  5600.         if (p == NULL)
  5601.         p = look + STRLEN(look);
  5602.         if ((try_match || try_match_word)
  5603.             && curwin->w_cursor.col >= (colnr_T)(p - look))
  5604.         {
  5605.         int        match = FALSE;
  5606.  
  5607. #ifdef FEAT_INS_EXPAND
  5608.         if (keytyped == KEY_COMPLETE)
  5609.         {
  5610.             char_u    *s;
  5611.  
  5612.             /* Just completed a word, check if it starts with "look".
  5613.              * search back for the start of a word. */
  5614.             line = ml_get_curline();
  5615. # ifdef FEAT_MBYTE
  5616.             if (has_mbyte)
  5617.             {
  5618.             char_u    *n;
  5619.  
  5620.             for (s = line + curwin->w_cursor.col; s > line; s = n)
  5621.             {
  5622.                 n = mb_prevptr(line, s);
  5623.                 if (!vim_iswordp(n))
  5624.                 break;
  5625.             }
  5626.             }
  5627.             else
  5628. # endif
  5629.             for (s = line + curwin->w_cursor.col; s > line; --s)
  5630.                 if (!vim_iswordc(s[-1]))
  5631.                 break;
  5632.             if (s + (p - look) <= line + curwin->w_cursor.col
  5633.                 && (icase
  5634.                 ? MB_STRNICMP(s, look, p - look)
  5635.                 : STRNCMP(s, look, p - look)) == 0)
  5636.             match = TRUE;
  5637.         }
  5638.         else
  5639. #endif
  5640.             /* TODO: multi-byte */
  5641.             if (keytyped == (int)p[-1] || (icase && keytyped < 256
  5642.              && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
  5643.         {
  5644.             line = ml_get_cursor();
  5645.             if ((curwin->w_cursor.col == (colnr_T)(p - look)
  5646.                 || !vim_iswordc(line[-(p - look) - 1]))
  5647.                 && (icase
  5648.                 ? MB_STRNICMP(line - (p - look), look, p - look)
  5649.                 : STRNCMP(line - (p - look), look, p - look))
  5650.                                      == 0)
  5651.             match = TRUE;
  5652.         }
  5653.         if (match && try_match_word && !try_match)
  5654.         {
  5655.             /* "0=word": Check if there are only blanks before the
  5656.              * word. */
  5657.             line = ml_get_curline();
  5658.             if ((int)(skipwhite(line) - line) !=
  5659.                      (int)(curwin->w_cursor.col - (p - look)))
  5660.             match = FALSE;
  5661.         }
  5662.         if (match)
  5663.             return TRUE;
  5664.         }
  5665.         look = p;
  5666.     }
  5667.  
  5668.     /*
  5669.      * ok, it's a boring generic character.
  5670.      */
  5671.     else
  5672.     {
  5673.         if (try_match && *look == keytyped)
  5674.         return TRUE;
  5675.         ++look;
  5676.     }
  5677.  
  5678.     /*
  5679.      * Skip over ", ".
  5680.      */
  5681.     look = skip_to_option_part(look);
  5682.     }
  5683.     return FALSE;
  5684. }
  5685. #endif /* FEAT_CINDENT */
  5686.  
  5687. #if defined(FEAT_RIGHTLEFT) || defined(PROTO)
  5688. /*
  5689.  * Map Hebrew keyboard when in hkmap mode.
  5690.  */
  5691.     int
  5692. hkmap(c)
  5693.     int c;
  5694. {
  5695.     if (p_hkmapp)   /* phonetic mapping, by Ilya Dogolazky */
  5696.     {
  5697.     enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
  5698.         KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
  5699.         PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
  5700.     static char_u map[26] =
  5701.         {(char_u)hALEF/*a*/, (char_u)BET  /*b*/, (char_u)hKAF    /*c*/,
  5702.          (char_u)DALET/*d*/, (char_u)-1   /*e*/, (char_u)PEIsofit/*f*/,
  5703.          (char_u)GIMEL/*g*/, (char_u)HEI  /*h*/, (char_u)IUD     /*i*/,
  5704.          (char_u)HET  /*j*/, (char_u)KOF  /*k*/, (char_u)LAMED   /*l*/,
  5705.          (char_u)MEM  /*m*/, (char_u)NUN  /*n*/, (char_u)SAMEH   /*o*/,
  5706.          (char_u)PEI  /*p*/, (char_u)-1   /*q*/, (char_u)RESH    /*r*/,
  5707.          (char_u)ZAIN /*s*/, (char_u)TAV  /*t*/, (char_u)TET     /*u*/,
  5708.          (char_u)VAV  /*v*/, (char_u)hSHIN/*w*/, (char_u)-1      /*x*/,
  5709.          (char_u)AIN  /*y*/, (char_u)ZADI /*z*/};
  5710.  
  5711.     if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
  5712.         return (int)(map[CharOrd(c)] - 1 + p_aleph);
  5713.                                 /* '-1'='sofit' */
  5714.     else if (c == 'x')
  5715.         return 'X';
  5716.     else if (c == 'q')
  5717.         return '\''; /* {geresh}={'} */
  5718.     else if (c == 246)
  5719.         return ' ';  /* \"o --> ' ' for a german keyboard */
  5720.     else if (c == 228)
  5721.         return ' ';  /* \"a --> ' '      -- / --           */
  5722.     else if (c == 252)
  5723.         return ' ';  /* \"u --> ' '      -- / --           */
  5724. #ifdef EBCDIC
  5725.     else if (islower(c))
  5726. #else
  5727.     /* NOTE: islower() does not do the right thing for us on Linux so we
  5728.      * do this the same was as 5.7 and previous, so it works correctly on
  5729.      * all systems.  Specifically, the e.g. Delete and Arrow keys are
  5730.      * munged and won't work if e.g. searching for Hebrew text.
  5731.      */
  5732.     else if (c >= 'a' && c <= 'z')
  5733. #endif
  5734.         return (int)(map[CharOrdLow(c)] + p_aleph);
  5735.     else
  5736.         return c;
  5737.     }
  5738.     else
  5739.     {
  5740.     switch (c)
  5741.     {
  5742.         case '`':    return ';';
  5743.         case '/':    return '.';
  5744.         case '\'':    return ',';
  5745.         case 'q':    return '/';
  5746.         case 'w':    return '\'';
  5747.  
  5748.             /* Hebrew letters - set offset from 'a' */
  5749.         case ',':    c = '{'; break;
  5750.         case '.':    c = 'v'; break;
  5751.         case ';':    c = 't'; break;
  5752.         default: {
  5753.              static char str[] = "zqbcxlsjphmkwonu ydafe rig";
  5754.  
  5755. #ifdef EBCDIC
  5756.              /* see note about islower() above */
  5757.              if (!islower(c))
  5758. #else
  5759.              if (c < 'a' || c > 'z')
  5760. #endif
  5761.                  return c;
  5762.              c = str[CharOrdLow(c)];
  5763.              break;
  5764.              }
  5765.     }
  5766.  
  5767.     return (int)(CharOrdLow(c) + p_aleph);
  5768.     }
  5769. }
  5770. #endif
  5771.  
  5772.     static void
  5773. ins_reg()
  5774. {
  5775.     int        need_redraw = FALSE;
  5776.     int        regname;
  5777.     int        literally = 0;
  5778.  
  5779.     /*
  5780.      * If we are going to wait for a character, show a '"'.
  5781.      */
  5782.     pc_status = PC_STATUS_UNSET;
  5783.     if (redrawing() && !char_avail())
  5784.     {
  5785.     /* may need to redraw when no more chars available now */
  5786.     ins_redraw();
  5787.  
  5788.     edit_putchar('"', TRUE);
  5789. #ifdef FEAT_CMDL_INFO
  5790.     add_to_showcmd_c(Ctrl_R);
  5791. #endif
  5792.     }
  5793.  
  5794. #ifdef USE_ON_FLY_SCROLL
  5795.     dont_scroll = TRUE;        /* disallow scrolling here */
  5796. #endif
  5797.  
  5798.     /*
  5799.      * Don't map the register name. This also prevents the mode message to be
  5800.      * deleted when ESC is hit.
  5801.      */
  5802.     ++no_mapping;
  5803.     regname = safe_vgetc();
  5804. #ifdef FEAT_LANGMAP
  5805.     LANGMAP_ADJUST(regname, TRUE);
  5806. #endif
  5807.     if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P)
  5808.     {
  5809.     /* Get a third key for literal register insertion */
  5810.     literally = regname;
  5811. #ifdef FEAT_CMDL_INFO
  5812.     add_to_showcmd_c(literally);
  5813. #endif
  5814.     regname = safe_vgetc();
  5815. #ifdef FEAT_LANGMAP
  5816.     LANGMAP_ADJUST(regname, TRUE);
  5817. #endif
  5818.     }
  5819.     --no_mapping;
  5820.  
  5821. #ifdef FEAT_EVAL
  5822.     /*
  5823.      * Don't call u_sync() while getting the expression,
  5824.      * evaluating it or giving an error message for it!
  5825.      */
  5826.     ++no_u_sync;
  5827.     if (regname == '=')
  5828.     {
  5829. #ifdef USE_IM_CONTROL
  5830.     int    im_on = im_get_status();
  5831. #endif
  5832.     regname = get_expr_register();
  5833. #ifdef USE_IM_CONTROL
  5834.     /* Restore the Input Method. */
  5835.     if (im_on)
  5836.         im_set_active(TRUE);
  5837. #endif
  5838.     }
  5839.     if (regname == NUL)
  5840.     need_redraw = TRUE;    /* remove the '"' */
  5841.     else
  5842.     {
  5843. #endif
  5844.     if (literally == Ctrl_O || literally == Ctrl_P)
  5845.     {
  5846.         /* Append the command to the redo buffer. */
  5847.         AppendCharToRedobuff(Ctrl_R);
  5848.         AppendCharToRedobuff(literally);
  5849.         AppendCharToRedobuff(regname);
  5850.  
  5851.         do_put(regname, BACKWARD, 1L,
  5852.          (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
  5853.     }
  5854.     else if (insert_reg(regname, literally) == FAIL)
  5855.     {
  5856.         vim_beep();
  5857.         need_redraw = TRUE;    /* remove the '"' */
  5858.     }
  5859. #ifdef FEAT_EVAL
  5860.     }
  5861.     --no_u_sync;
  5862. #endif
  5863. #ifdef FEAT_CMDL_INFO
  5864.     clear_showcmd();
  5865. #endif
  5866.  
  5867.     /* If the inserted register is empty, we need to remove the '"' */
  5868.     if (need_redraw || stuff_empty())
  5869.     edit_unputchar();
  5870. }
  5871.  
  5872. /*
  5873.  * CTRL-G commands in Insert mode.
  5874.  */
  5875.     static void
  5876. ins_ctrl_g()
  5877. {
  5878.     int        c;
  5879.  
  5880. #ifdef FEAT_INS_EXPAND
  5881.     /* Right after CTRL-X the cursor will be after the ruler. */
  5882.     setcursor();
  5883. #endif
  5884.  
  5885.     /*
  5886.      * Don't map the register name. This also prevents the mode message to be
  5887.      * deleted when ESC is hit.
  5888.      */
  5889.     ++no_mapping;
  5890.     c = safe_vgetc();
  5891.     --no_mapping;
  5892.     switch (c)
  5893.     {
  5894.     /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
  5895.     case K_UP:
  5896.     case Ctrl_K:
  5897.     case 'k': ins_up(TRUE);
  5898.           break;
  5899.  
  5900.     /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
  5901.     case K_DOWN:
  5902.     case Ctrl_J:
  5903.     case 'j': ins_down(TRUE);
  5904.           break;
  5905.  
  5906.     /* Unknown CTRL-G command, reserved for future expansion. */
  5907.     default:  vim_beep();
  5908.     }
  5909. }
  5910.  
  5911. /*
  5912.  * Handle ESC in insert mode.
  5913.  * Returns TRUE when leaving insert mode, FALSE when going to repeat the
  5914.  * insert.
  5915.  */
  5916.     static int
  5917. ins_esc(count, cmdchar)
  5918.     long    *count;
  5919.     int        cmdchar;
  5920. {
  5921.     int        temp;
  5922.     static int    disabled_redraw = FALSE;
  5923.  
  5924. #if defined(FEAT_HANGULIN)
  5925. # if defined(ESC_CHG_TO_ENG_MODE)
  5926.     hangul_input_state_set(0);
  5927. # endif
  5928.     if (composing_hangul)
  5929.     {
  5930.     push_raw_key(composing_hangul_buffer, 2);
  5931.     composing_hangul = 0;
  5932.     }
  5933. #endif
  5934. #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
  5935.     previous_script = GetScriptManagerVariable(smKeyScript);
  5936.     KeyScript(smKeyRoman); /* or smKeySysScript */
  5937. #endif
  5938.  
  5939.     temp = curwin->w_cursor.col;
  5940.     if (disabled_redraw)
  5941.     {
  5942.     --RedrawingDisabled;
  5943.     disabled_redraw = FALSE;
  5944.     }
  5945.     if (!arrow_used)
  5946.     {
  5947.     /*
  5948.      * Don't append the ESC for "r<CR>".
  5949.      */
  5950.     if (cmdchar != 'r' && cmdchar != 'v')
  5951.         AppendToRedobuff(ESC_STR);
  5952.  
  5953.     /*
  5954.      * Repeating insert may take a long time.  Check for
  5955.      * interrupt now and then.
  5956.      */
  5957.     if (*count)
  5958.     {
  5959.         line_breakcheck();
  5960.         if (got_int)
  5961.         *count = 0;
  5962.     }
  5963.  
  5964.     if (--*count > 0)    /* repeat what was typed */
  5965.     {
  5966.         (void)start_redo_ins();
  5967.         ++RedrawingDisabled;
  5968.         disabled_redraw = TRUE;
  5969.         return FALSE;    /* repeat the insert */
  5970.     }
  5971.     stop_insert(&curwin->w_cursor);
  5972.     undisplay_dollar();
  5973.     }
  5974.  
  5975.     /* When an autoindent was removed, curswant stays after the
  5976.      * indent */
  5977.     if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col)
  5978.     curwin->w_set_curswant = TRUE;
  5979.  
  5980.     /* Remember the last Insert position in the '^ mark. */
  5981.     curbuf->b_last_insert = curwin->w_cursor;
  5982.  
  5983.     /*
  5984.      * The cursor should end up on the last inserted character.
  5985.      */
  5986.     if ((curwin->w_cursor.col != 0
  5987. #ifdef FEAT_VIRTUALEDIT
  5988.         || curwin->w_cursor.coladd > 0
  5989. #endif
  5990.     ) && (restart_edit == NUL
  5991.         || (gchar_cursor() == NUL
  5992. #ifdef FEAT_VISUAL
  5993.             && !VIsual_active
  5994. #endif
  5995.             ))
  5996. #ifdef FEAT_RIGHTLEFT
  5997.         && !revins_on
  5998. #endif
  5999.                       )
  6000.     {
  6001. #ifdef FEAT_VIRTUALEDIT
  6002.     if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL)
  6003.     {
  6004.         oneleft();
  6005.         if (restart_edit != NUL)
  6006.         ++curwin->w_cursor.coladd;
  6007.     }
  6008.     else
  6009. #endif
  6010.         --curwin->w_cursor.col;
  6011.     }
  6012.  
  6013. #ifdef USE_IM_CONTROL
  6014.     /* Disable IM to allow typing English directly for Normal mode commands.
  6015.      * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
  6016.      * well). */
  6017.     if (!(State & LANGMAP))
  6018.     im_save_status(&curbuf->b_p_iminsert);
  6019.     im_set_active(FALSE);
  6020. #endif
  6021.  
  6022.     State = NORMAL;
  6023.     /* need to position cursor again (e.g. when on a TAB ) */
  6024.     changed_cline_bef_curs();
  6025.  
  6026. #ifdef FEAT_MOUSE
  6027.     setmouse();
  6028. #endif
  6029. #ifdef CURSOR_SHAPE
  6030.     ui_cursor_shape();        /* may show different cursor shape */
  6031. #endif
  6032.  
  6033.     /*
  6034.      * When recording or for CTRL-O, need to display the new mode.
  6035.      * Otherwise remove the mode message.
  6036.      */
  6037.     if (Recording || restart_edit != NUL)
  6038.     showmode();
  6039.     else if (p_smd)
  6040.     MSG("");
  6041.  
  6042.     return TRUE;        /* exit Insert mode */
  6043. }
  6044.  
  6045. #ifdef FEAT_RIGHTLEFT
  6046. /*
  6047.  * Toggle language: hkmap and revins_on.
  6048.  * Move to end of reverse inserted text.
  6049.  */
  6050.     static void
  6051. ins_ctrl_()
  6052. {
  6053.     if (revins_on && revins_chars && revins_scol >= 0)
  6054.     {
  6055.     while (gchar_cursor() != NUL && revins_chars--)
  6056.         ++curwin->w_cursor.col;
  6057.     }
  6058.     p_ri = !p_ri;
  6059.     revins_on = (State == INSERT && p_ri);
  6060.     if (revins_on)
  6061.     {
  6062.     revins_scol = curwin->w_cursor.col;
  6063.     revins_legal++;
  6064.     revins_chars = 0;
  6065.     undisplay_dollar();
  6066.     }
  6067.     else
  6068.     revins_scol = -1;
  6069. #ifdef FEAT_FKMAP
  6070.     if (p_altkeymap)
  6071.     {
  6072.     /*
  6073.      * to be consistent also for redo command, using '.'
  6074.      * set arrow_used to true and stop it - causing to redo
  6075.      * characters entered in one mode (normal/reverse insert).
  6076.      */
  6077.     arrow_used = TRUE;
  6078.     (void)stop_arrow();
  6079.     p_fkmap = curwin->w_p_rl ^ p_ri;
  6080.     if (p_fkmap && p_ri)
  6081.         State = INSERT;
  6082.     }
  6083.     else
  6084. #endif
  6085.     p_hkmap = curwin->w_p_rl ^ p_ri;    /* be consistent! */
  6086.     showmode();
  6087. }
  6088. #endif
  6089.  
  6090. #ifdef FEAT_VISUAL
  6091. /*
  6092.  * If 'keymodel' contains "startsel", may start selection.
  6093.  * Returns TRUE when a CTRL-O and other keys stuffed.
  6094.  */
  6095.     static int
  6096. ins_start_select(c)
  6097.     int        c;
  6098. {
  6099.     if (km_startsel)
  6100.     switch (c)
  6101.     {
  6102.         case K_KHOME:
  6103.         case K_XHOME:
  6104.         case K_KEND:
  6105.         case K_XEND:
  6106.         case K_PAGEUP:
  6107.         case K_KPAGEUP:
  6108.         case K_PAGEDOWN:
  6109.         case K_KPAGEDOWN:
  6110. # ifdef MACOS
  6111.         case K_LEFT:
  6112.         case K_RIGHT:
  6113.         case K_UP:
  6114.         case K_DOWN:
  6115.         case K_END:
  6116.         case K_HOME:
  6117. # endif
  6118.         if (!(mod_mask & MOD_MASK_SHIFT))
  6119.             break;
  6120.         /* FALLTHROUGH */
  6121.         case K_S_LEFT:
  6122.         case K_S_RIGHT:
  6123.         case K_S_UP:
  6124.         case K_S_DOWN:
  6125.         case K_S_END:
  6126.         case K_S_HOME:
  6127.         /* Start selection right away, the cursor can move with
  6128.          * CTRL-O when beyond the end of the line. */
  6129.         start_selection();
  6130.  
  6131.         /* Execute the key in (insert) Select mode. */
  6132.         stuffcharReadbuff(Ctrl_O);
  6133.         if (mod_mask)
  6134.         {
  6135.             char_u        buf[4];
  6136.  
  6137.             buf[0] = K_SPECIAL;
  6138.             buf[1] = KS_MODIFIER;
  6139.             buf[2] = mod_mask;
  6140.             buf[3] = NUL;
  6141.             stuffReadbuff(buf);
  6142.         }
  6143.         stuffcharReadbuff(c);
  6144.         return TRUE;
  6145.     }
  6146.     return FALSE;
  6147. }
  6148. #endif
  6149.  
  6150. /*
  6151.  * If the cursor is on an indent, ^T/^D insert/delete one
  6152.  * shiftwidth.    Otherwise ^T/^D behave like a "<<" or ">>".
  6153.  * Always round the indent to 'shiftwith', this is compatible
  6154.  * with vi.  But vi only supports ^T and ^D after an
  6155.  * autoindent, we support it everywhere.
  6156.  */
  6157.     static void
  6158. ins_shift(c, lastc)
  6159.     int        c;
  6160.     int        lastc;
  6161. {
  6162.     if (stop_arrow() == FAIL)
  6163.     return;
  6164.     AppendCharToRedobuff(c);
  6165.  
  6166.     /*
  6167.      * 0^D and ^^D: remove all indent.
  6168.      */
  6169.     if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
  6170.     {
  6171.     --curwin->w_cursor.col;
  6172.     (void)del_char(FALSE);        /* delete the '^' or '0' */
  6173.     /* In Replace mode, restore the characters that '^' or '0' replaced. */
  6174.     if (State & REPLACE_FLAG)
  6175.         replace_pop_ins();
  6176.     if (lastc == '^')
  6177.         old_indent = get_indent();    /* remember curr. indent */
  6178.     change_indent(INDENT_SET, 0, TRUE, 0);
  6179.     }
  6180.     else
  6181.     change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0);
  6182.  
  6183.     if (did_ai && *skipwhite(ml_get_curline()) != NUL)
  6184.     did_ai = FALSE;
  6185. #ifdef FEAT_SMARTINDENT
  6186.     did_si = FALSE;
  6187.     can_si = FALSE;
  6188.     can_si_back = FALSE;
  6189. #endif
  6190. #ifdef FEAT_CINDENT
  6191.     can_cindent = FALSE;    /* no cindenting after ^D or ^T */
  6192. #endif
  6193. }
  6194.  
  6195.     static void
  6196. ins_del()
  6197. {
  6198.     int        temp;
  6199.  
  6200.     if (stop_arrow() == FAIL)
  6201.     return;
  6202.     if (gchar_cursor() == NUL)        /* delete newline */
  6203.     {
  6204.     temp = curwin->w_cursor.col;
  6205.     if (!can_bs(BS_EOL)        /* only if "eol" included */
  6206.         || u_save((linenr_T)(curwin->w_cursor.lnum - 1),
  6207.             (linenr_T)(curwin->w_cursor.lnum + 2)) == FAIL
  6208.         || do_join(FALSE) == FAIL)
  6209.         vim_beep();
  6210.     else
  6211.         curwin->w_cursor.col = temp;
  6212.     }
  6213.     else if (del_char(FALSE) == FAIL)    /* delete char under cursor */
  6214.     vim_beep();
  6215.     did_ai = FALSE;
  6216. #ifdef FEAT_SMARTINDENT
  6217.     did_si = FALSE;
  6218.     can_si = FALSE;
  6219.     can_si_back = FALSE;
  6220. #endif
  6221.     AppendCharToRedobuff(K_DEL);
  6222. }
  6223.  
  6224. /*
  6225.  * Handle Backspace, delete-word and delete-line in Insert mode.
  6226.  * Return TRUE when backspace was actually used.
  6227.  */
  6228.     static int
  6229. ins_bs(c, mode, inserted_space_p)
  6230.     int        c;
  6231.     int        mode;
  6232.     int        *inserted_space_p;
  6233. {
  6234.     linenr_T    lnum;
  6235.     int        cc;
  6236.     int        temp = 0;        /* init for GCC */
  6237.     colnr_T    mincol;
  6238.     int        did_backspace = FALSE;
  6239.     int        in_indent;
  6240.     int        oldState;
  6241. #ifdef FEAT_MBYTE
  6242.     int        p1, p2;
  6243. #endif
  6244.  
  6245.     /*
  6246.      * can't delete anything in an empty file
  6247.      * can't backup past first character in buffer
  6248.      * can't backup past starting point unless 'backspace' > 1
  6249.      * can backup to a previous line if 'backspace' == 0
  6250.      */
  6251.     if (       bufempty()
  6252.         || (
  6253. #ifdef FEAT_RIGHTLEFT
  6254.         !revins_on &&
  6255. #endif
  6256.         ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
  6257.             || (!can_bs(BS_START)
  6258.             && (arrow_used
  6259.                 || (curwin->w_cursor.lnum == Insstart.lnum
  6260.                 && curwin->w_cursor.col <= Insstart.col)))
  6261.             || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
  6262.                      && curwin->w_cursor.col <= ai_col)
  6263.             || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0))))
  6264.     {
  6265.     vim_beep();
  6266.     return FALSE;
  6267.     }
  6268.  
  6269.     if (stop_arrow() == FAIL)
  6270.     return FALSE;
  6271.     in_indent = inindent(0);
  6272. #ifdef FEAT_CINDENT
  6273.     if (in_indent)
  6274.     can_cindent = FALSE;
  6275. #endif
  6276. #ifdef FEAT_COMMENTS
  6277.     end_comment_pending = NUL;    /* After BS, don't auto-end comment */
  6278. #endif
  6279. #ifdef FEAT_RIGHTLEFT
  6280.     if (revins_on)        /* put cursor after last inserted char */
  6281.     inc_cursor();
  6282. #endif
  6283.  
  6284. #ifdef FEAT_VIRTUALEDIT
  6285.     /* Virtualedit:
  6286.      *    BACKSPACE_CHAR eats a virtual space
  6287.      *    BACKSPACE_WORD eats all coladd
  6288.      *    BACKSPACE_LINE eats all coladd and keeps going
  6289.      */
  6290.     if (curwin->w_cursor.coladd > 0)
  6291.     {
  6292.     if (mode == BACKSPACE_CHAR)
  6293.     {
  6294.         --curwin->w_cursor.coladd;
  6295.         return TRUE;
  6296.     }
  6297.     if (mode == BACKSPACE_WORD)
  6298.     {
  6299.         curwin->w_cursor.coladd = 0;
  6300.         return TRUE;
  6301.     }
  6302.     curwin->w_cursor.coladd = 0;
  6303.     }
  6304. #endif
  6305.  
  6306.     /*
  6307.      * delete newline!
  6308.      */
  6309.     if (curwin->w_cursor.col == 0)
  6310.     {
  6311.     lnum = Insstart.lnum;
  6312.     if (curwin->w_cursor.lnum == Insstart.lnum
  6313. #ifdef FEAT_RIGHTLEFT
  6314.             || revins_on
  6315. #endif
  6316.                     )
  6317.     {
  6318.         if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
  6319.                    (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
  6320.         return FALSE;
  6321.         --Insstart.lnum;
  6322.         Insstart.col = MAXCOL;
  6323.     }
  6324.     /*
  6325.      * In replace mode:
  6326.      * cc < 0: NL was inserted, delete it
  6327.      * cc >= 0: NL was replaced, put original characters back
  6328.      */
  6329.     cc = -1;
  6330.     if (State & REPLACE_FLAG)
  6331.         cc = replace_pop();        /* returns -1 if NL was inserted */
  6332.     /*
  6333.      * In replace mode, in the line we started replacing, we only move the
  6334.      * cursor.
  6335.      */
  6336.     if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum)
  6337.     {
  6338.         dec_cursor();
  6339.     }
  6340.     else
  6341.     {
  6342. #ifdef FEAT_VREPLACE
  6343.         if (!(State & VREPLACE_FLAG)
  6344.                    || curwin->w_cursor.lnum > orig_line_count)
  6345. #endif
  6346.         {
  6347.         temp = gchar_cursor();    /* remember current char */
  6348.         --curwin->w_cursor.lnum;
  6349.         (void)do_join(FALSE);
  6350.         if (temp == NUL && gchar_cursor() != NUL)
  6351.             inc_cursor();
  6352.         }
  6353. #ifdef FEAT_VREPLACE
  6354.         else
  6355.         dec_cursor();
  6356. #endif
  6357.  
  6358.         /*
  6359.          * In REPLACE mode we have to put back the text that was replaced
  6360.          * by the NL. On the replace stack is first a NUL-terminated
  6361.          * sequence of characters that were deleted and then the
  6362.          * characters that NL replaced.
  6363.          */
  6364.         if (State & REPLACE_FLAG)
  6365.         {
  6366.         /*
  6367.          * Do the next ins_char() in NORMAL state, to
  6368.          * prevent ins_char() from replacing characters and
  6369.          * avoiding showmatch().
  6370.          */
  6371.         oldState = State;
  6372.         State = NORMAL;
  6373.         /*
  6374.          * restore characters (blanks) deleted after cursor
  6375.          */
  6376.         while (cc > 0)
  6377.         {
  6378.             temp = curwin->w_cursor.col;
  6379. #ifdef FEAT_MBYTE
  6380.             mb_replace_pop_ins(cc);
  6381. #else
  6382.             ins_char(cc);
  6383. #endif
  6384.             curwin->w_cursor.col = temp;
  6385.             cc = replace_pop();
  6386.         }
  6387.         /* restore the characters that NL replaced */
  6388.         replace_pop_ins();
  6389.         State = oldState;
  6390.         }
  6391.     }
  6392.     did_ai = FALSE;
  6393.     }
  6394.     else
  6395.     {
  6396.     /*
  6397.      * Delete character(s) before the cursor.
  6398.      */
  6399. #ifdef FEAT_RIGHTLEFT
  6400.     if (revins_on)        /* put cursor on last inserted char */
  6401.         dec_cursor();
  6402. #endif
  6403.     mincol = 0;
  6404.                         /* keep indent */
  6405.     if (mode == BACKSPACE_LINE && curbuf->b_p_ai
  6406. #ifdef FEAT_RIGHTLEFT
  6407.         && !revins_on
  6408. #endif
  6409.                 )
  6410.     {
  6411.         temp = curwin->w_cursor.col;
  6412.         beginline(BL_WHITE);
  6413.         if (curwin->w_cursor.col < (colnr_T)temp)
  6414.         mincol = curwin->w_cursor.col;
  6415.         curwin->w_cursor.col = temp;
  6416.     }
  6417.  
  6418.     /*
  6419.      * Handle deleting one 'shiftwidth' or 'softtabstop'.
  6420.      */
  6421.     if (       mode == BACKSPACE_CHAR
  6422.         && ((p_sta && in_indent)
  6423.             || (curbuf->b_p_sts
  6424.             && (*(ml_get_cursor() - 1) == TAB
  6425.                 || (*(ml_get_cursor() - 1) == ' '
  6426.                 && (!*inserted_space_p
  6427.                     || arrow_used))))))
  6428.     {
  6429.         int        ts;
  6430.         colnr_T    vcol;
  6431.         colnr_T    want_vcol;
  6432.         int        extra = 0;
  6433.  
  6434.         *inserted_space_p = FALSE;
  6435.         if (p_sta)
  6436.         ts = curbuf->b_p_sw;
  6437.         else
  6438.         ts = curbuf->b_p_sts;
  6439.         /* Compute the virtual column where we want to be.  Since
  6440.          * 'showbreak' may get in the way, need to get the last column of
  6441.          * the previous character. */
  6442.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6443.         dec_cursor();
  6444.         getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
  6445.         inc_cursor();
  6446.         want_vcol = (want_vcol / ts) * ts;
  6447.  
  6448.         /* delete characters until we are at or before want_vcol */
  6449.         while (vcol > want_vcol
  6450.             && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
  6451.         {
  6452.         dec_cursor();
  6453.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6454.         if (State & REPLACE_FLAG)
  6455.         {
  6456.             /* Don't delete characters before the insert point when in
  6457.              * Replace mode */
  6458.             if (curwin->w_cursor.lnum != Insstart.lnum
  6459.                 || curwin->w_cursor.col >= Insstart.col)
  6460.             {
  6461. #if 0    /* what was this for?  It causes problems when sw != ts. */
  6462.             if (State == REPLACE && (int)vcol < want_vcol)
  6463.             {
  6464.                 (void)del_char(FALSE);
  6465.                 extra = 2;    /* don't pop too much */
  6466.             }
  6467.             else
  6468. #endif
  6469.                 replace_do_bs();
  6470.             }
  6471.         }
  6472.         else
  6473.             (void)del_char(FALSE);
  6474.         }
  6475.  
  6476.         /* insert extra spaces until we are at want_vcol */
  6477.         while (vcol < want_vcol)
  6478.         {
  6479.         /* Remember the first char we inserted */
  6480.         if (curwin->w_cursor.lnum == Insstart.lnum
  6481.                    && curwin->w_cursor.col < Insstart.col)
  6482.             Insstart.col = curwin->w_cursor.col;
  6483.  
  6484. #ifdef FEAT_VREPLACE
  6485.         if (State & VREPLACE_FLAG)
  6486.             ins_char(' ');
  6487.         else
  6488. #endif
  6489.         {
  6490.             ins_str((char_u *)" ");
  6491.             if ((State & REPLACE_FLAG) && extra <= 1)
  6492.             {
  6493.             if (extra)
  6494.                 replace_push_off(NUL);
  6495.             else
  6496.                 replace_push(NUL);
  6497.             }
  6498.             if (extra == 2)
  6499.             extra = 1;
  6500.         }
  6501.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6502.         }
  6503.     }
  6504.  
  6505.     /*
  6506.      * Delete upto starting point, start of line or previous word.
  6507.      */
  6508.     else do
  6509.     {
  6510. #ifdef FEAT_RIGHTLEFT
  6511.         if (!revins_on) /* put cursor on char to be deleted */
  6512. #endif
  6513.         dec_cursor();
  6514.  
  6515.         /* start of word? */
  6516.         if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor()))
  6517.         {
  6518.         mode = BACKSPACE_WORD_NOT_SPACE;
  6519.         temp = vim_iswordc(gchar_cursor());
  6520.         }
  6521.         /* end of word? */
  6522.         else if (mode == BACKSPACE_WORD_NOT_SPACE
  6523.             && (vim_isspace(cc = gchar_cursor())
  6524.                 || vim_iswordc(cc) != temp))
  6525.         {
  6526. #ifdef FEAT_RIGHTLEFT
  6527.         if (!revins_on)
  6528. #endif
  6529.             inc_cursor();
  6530. #ifdef FEAT_RIGHTLEFT
  6531.         else if (State & REPLACE_FLAG)
  6532.             dec_cursor();
  6533. #endif
  6534.         break;
  6535.         }
  6536.         if (State & REPLACE_FLAG)
  6537.         replace_do_bs();
  6538.         else
  6539.         {
  6540. #ifdef FEAT_MBYTE
  6541.         if (enc_utf8 && p_deco)
  6542.             (void)utfc_ptr2char(ml_get_cursor(), &p1, &p2);
  6543. #endif
  6544.         (void)del_char(FALSE);
  6545. #ifdef FEAT_MBYTE
  6546.         /*
  6547.          * If p1 or p2 is non-zero, there are combining characters we
  6548.          * need to take account of.  Don't back up before the base
  6549.          * character.
  6550.          */
  6551.         if (enc_utf8 && p_deco && (p1 != NUL || p2 != NUL))
  6552.             inc_cursor();
  6553. #endif
  6554. #ifdef FEAT_RIGHTLEFT
  6555.         if (revins_chars)
  6556.         {
  6557.             revins_chars--;
  6558.             revins_legal++;
  6559.         }
  6560.         if (revins_on && gchar_cursor() == NUL)
  6561.             break;
  6562. #endif
  6563.         }
  6564.         /* Just a single backspace?: */
  6565.         if (mode == BACKSPACE_CHAR)
  6566.         break;
  6567.     } while (
  6568. #ifdef FEAT_RIGHTLEFT
  6569.         revins_on ||
  6570. #endif
  6571.         (curwin->w_cursor.col > mincol
  6572.          && (curwin->w_cursor.lnum != Insstart.lnum
  6573.              || curwin->w_cursor.col != Insstart.col)));
  6574.     did_backspace = TRUE;
  6575.     }
  6576. #ifdef FEAT_SMARTINDENT
  6577.     did_si = FALSE;
  6578.     can_si = FALSE;
  6579.     can_si_back = FALSE;
  6580. #endif
  6581.     if (curwin->w_cursor.col <= 1)
  6582.     did_ai = FALSE;
  6583.     /*
  6584.      * It's a little strange to put backspaces into the redo
  6585.      * buffer, but it makes auto-indent a lot easier to deal
  6586.      * with.
  6587.      */
  6588.     AppendCharToRedobuff(c);
  6589.  
  6590.     /* If deleted before the insertion point, adjust it */
  6591.     if (curwin->w_cursor.lnum == Insstart.lnum
  6592.                        && curwin->w_cursor.col < Insstart.col)
  6593.     Insstart.col = curwin->w_cursor.col;
  6594.  
  6595.     /* vi behaviour: the cursor moves backward but the character that
  6596.      *             was there remains visible
  6597.      * Vim behaviour: the cursor moves backward and the character that
  6598.      *              was there is erased from the screen.
  6599.      * We can emulate the vi bahaviour by pretending there is a dollar
  6600.      * displayed even when there isn't.
  6601.      *  --pkv Sun Jan 19 01:56:40 EST 2003 */
  6602.     if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0)
  6603.     dollar_vcol = curwin->w_virtcol + 1;
  6604.  
  6605.     return did_backspace;
  6606. }
  6607.  
  6608. #ifdef FEAT_MOUSE
  6609.     static void
  6610. ins_mouse(c)
  6611.     int        c;
  6612. {
  6613.     pos_T    tpos;
  6614.  
  6615. # ifdef FEAT_GUI
  6616.     /* When GUI is active, also move/paste when 'mouse' is empty */
  6617.     if (!gui.in_use)
  6618. # endif
  6619.     if (!mouse_has(MOUSE_INSERT))
  6620.         return;
  6621.  
  6622.     undisplay_dollar();
  6623.     tpos = curwin->w_cursor;
  6624.     if (do_mouse(NULL, c, BACKWARD, 1L, 0))
  6625.     {
  6626.     start_arrow(&tpos);
  6627. # ifdef FEAT_CINDENT
  6628.     can_cindent = TRUE;
  6629. # endif
  6630.     }
  6631.  
  6632. #ifdef FEAT_WINDOWS
  6633.     /* redraw status lines (in case another window became active) */
  6634.     redraw_statuslines();
  6635. #endif
  6636. }
  6637.  
  6638.     static void
  6639. ins_mousescroll(up)
  6640.     int        up;
  6641. {
  6642.     pos_T    tpos;
  6643. # if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
  6644.     win_T    *old_curwin;
  6645. # endif
  6646.  
  6647.     tpos = curwin->w_cursor;
  6648.  
  6649. # if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
  6650.     old_curwin = curwin;
  6651.  
  6652.     /* Currently the mouse coordinates are only known in the GUI. */
  6653.     if (gui.in_use && mouse_row >= 0 && mouse_col >= 0)
  6654.     {
  6655.     int row, col;
  6656.  
  6657.     row = mouse_row;
  6658.     col = mouse_col;
  6659.  
  6660.     /* find the window at the pointer coordinates */
  6661.     curwin = mouse_find_win(&row, &col);
  6662.     curbuf = curwin->w_buffer;
  6663.     }
  6664.     if (curwin == old_curwin)
  6665. # endif
  6666.     undisplay_dollar();
  6667.  
  6668.     if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
  6669.     scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
  6670.     else
  6671.     scroll_redraw(up, 3L);
  6672.  
  6673. # if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
  6674.     curwin->w_redr_status = TRUE;
  6675.  
  6676.     curwin = old_curwin;
  6677.     curbuf = curwin->w_buffer;
  6678. # endif
  6679.  
  6680.     if (!equal(curwin->w_cursor, tpos))
  6681.     {
  6682.     start_arrow(&tpos);
  6683. # ifdef FEAT_CINDENT
  6684.     can_cindent = TRUE;
  6685. # endif
  6686.     }
  6687. }
  6688. #endif
  6689.  
  6690. #ifdef FEAT_GUI
  6691.     void
  6692. ins_scroll()
  6693. {
  6694.     pos_T    tpos;
  6695.  
  6696.     undisplay_dollar();
  6697.     tpos = curwin->w_cursor;
  6698.     if (gui_do_scroll())
  6699.     {
  6700.     start_arrow(&tpos);
  6701. # ifdef FEAT_CINDENT
  6702.     can_cindent = TRUE;
  6703. # endif
  6704.     }
  6705. }
  6706.  
  6707.     void
  6708. ins_horscroll()
  6709. {
  6710.     pos_T    tpos;
  6711.  
  6712.     undisplay_dollar();
  6713.     tpos = curwin->w_cursor;
  6714.     if (gui_do_horiz_scroll())
  6715.     {
  6716.     start_arrow(&tpos);
  6717. # ifdef FEAT_CINDENT
  6718.     can_cindent = TRUE;
  6719. # endif
  6720.     }
  6721. }
  6722. #endif
  6723.  
  6724.     static void
  6725. ins_left()
  6726. {
  6727.     pos_T    tpos;
  6728.  
  6729. #ifdef FEAT_FOLDING
  6730.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6731.     foldOpenCursor();
  6732. #endif
  6733.     undisplay_dollar();
  6734.     tpos = curwin->w_cursor;
  6735.     if (oneleft() == OK)
  6736.     {
  6737.     start_arrow(&tpos);
  6738. #ifdef FEAT_RIGHTLEFT
  6739.     /* If exit reversed string, position is fixed */
  6740.     if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
  6741.         revins_legal++;
  6742.     revins_chars++;
  6743. #endif
  6744.     }
  6745.  
  6746.     /*
  6747.      * if 'whichwrap' set for cursor in insert mode may go to
  6748.      * previous line
  6749.      */
  6750.     else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
  6751.     {
  6752.     start_arrow(&tpos);
  6753.     --(curwin->w_cursor.lnum);
  6754.     coladvance((colnr_T)MAXCOL);
  6755.     curwin->w_set_curswant = TRUE;    /* so we stay at the end */
  6756.     }
  6757.     else
  6758.     vim_beep();
  6759. }
  6760.  
  6761.     static void
  6762. ins_home(c)
  6763.     int        c;
  6764. {
  6765.     pos_T    tpos;
  6766.  
  6767. #ifdef FEAT_FOLDING
  6768.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6769.     foldOpenCursor();
  6770. #endif
  6771.     undisplay_dollar();
  6772.     tpos = curwin->w_cursor;
  6773.     if (c == K_C_HOME)
  6774.     curwin->w_cursor.lnum = 1;
  6775.     curwin->w_cursor.col = 0;
  6776. #ifdef FEAT_VIRTUALEDIT
  6777.     curwin->w_cursor.coladd = 0;
  6778. #endif
  6779.     curwin->w_curswant = 0;
  6780.     start_arrow(&tpos);
  6781. }
  6782.  
  6783.     static void
  6784. ins_end(c)
  6785.     int        c;
  6786. {
  6787.     pos_T    tpos;
  6788.  
  6789. #ifdef FEAT_FOLDING
  6790.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6791.     foldOpenCursor();
  6792. #endif
  6793.     undisplay_dollar();
  6794.     tpos = curwin->w_cursor;
  6795.     if (c == K_C_END)
  6796.     curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  6797.     coladvance((colnr_T)MAXCOL);
  6798.     curwin->w_curswant = MAXCOL;
  6799.  
  6800.     start_arrow(&tpos);
  6801. }
  6802.  
  6803.     static void
  6804. ins_s_left()
  6805. {
  6806. #ifdef FEAT_FOLDING
  6807.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6808.     foldOpenCursor();
  6809. #endif
  6810.     undisplay_dollar();
  6811.     if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
  6812.     {
  6813.     start_arrow(&curwin->w_cursor);
  6814.     (void)bck_word(1L, FALSE, FALSE);
  6815.     curwin->w_set_curswant = TRUE;
  6816.     }
  6817.     else
  6818.     vim_beep();
  6819. }
  6820.  
  6821.     static void
  6822. ins_right()
  6823. {
  6824. #ifdef FEAT_FOLDING
  6825.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6826.     foldOpenCursor();
  6827. #endif
  6828.     undisplay_dollar();
  6829.     if (gchar_cursor() != NUL || virtual_active()
  6830.         )
  6831.     {
  6832.     start_arrow(&curwin->w_cursor);
  6833.     curwin->w_set_curswant = TRUE;
  6834. #ifdef FEAT_VIRTUALEDIT
  6835.     if (virtual_active())
  6836.         oneright();
  6837.     else
  6838. #endif
  6839.     {
  6840. #ifdef FEAT_MBYTE
  6841.         if (has_mbyte)
  6842.         curwin->w_cursor.col += (*mb_ptr2len_check)(ml_get_cursor());
  6843.         else
  6844. #endif
  6845.         ++curwin->w_cursor.col;
  6846.     }
  6847.  
  6848. #ifdef FEAT_RIGHTLEFT
  6849.     revins_legal++;
  6850.     if (revins_chars)
  6851.         revins_chars--;
  6852. #endif
  6853.     }
  6854.     /* if 'whichwrap' set for cursor in insert mode, may move the
  6855.      * cursor to the next line */
  6856.     else if (vim_strchr(p_ww, ']') != NULL
  6857.         && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  6858.     {
  6859.     start_arrow(&curwin->w_cursor);
  6860.     curwin->w_set_curswant = TRUE;
  6861.     ++curwin->w_cursor.lnum;
  6862.     curwin->w_cursor.col = 0;
  6863.     }
  6864.     else
  6865.     vim_beep();
  6866. }
  6867.  
  6868.     static void
  6869. ins_s_right()
  6870. {
  6871. #ifdef FEAT_FOLDING
  6872.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6873.     foldOpenCursor();
  6874. #endif
  6875.     undisplay_dollar();
  6876.     if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  6877.         || gchar_cursor() != NUL)
  6878.     {
  6879.     start_arrow(&curwin->w_cursor);
  6880.     (void)fwd_word(1L, FALSE, 0);
  6881.     curwin->w_set_curswant = TRUE;
  6882.     }
  6883.     else
  6884.     vim_beep();
  6885. }
  6886.  
  6887.     static void
  6888. ins_up(startcol)
  6889.     int        startcol;    /* when TRUE move to Insstart.col */
  6890. {
  6891.     pos_T    tpos;
  6892.     linenr_T    old_topline = curwin->w_topline;
  6893. #ifdef FEAT_DIFF
  6894.     int        old_topfill = curwin->w_topfill;
  6895. #endif
  6896.  
  6897.     undisplay_dollar();
  6898.     tpos = curwin->w_cursor;
  6899.     if (cursor_up(1L, TRUE) == OK)
  6900.     {
  6901.     if (startcol)
  6902.         coladvance(getvcol_nolist(&Insstart));
  6903.     if (old_topline != curwin->w_topline
  6904. #ifdef FEAT_DIFF
  6905.         || old_topfill != curwin->w_topfill
  6906. #endif
  6907.         )
  6908.         redraw_later(VALID);
  6909.     start_arrow(&tpos);
  6910. #ifdef FEAT_CINDENT
  6911.     can_cindent = TRUE;
  6912. #endif
  6913.     }
  6914.     else
  6915.     vim_beep();
  6916. }
  6917.  
  6918.     static void
  6919. ins_pageup()
  6920. {
  6921.     pos_T    tpos;
  6922.  
  6923.     undisplay_dollar();
  6924.     tpos = curwin->w_cursor;
  6925.     if (onepage(BACKWARD, 1L) == OK)
  6926.     {
  6927.     start_arrow(&tpos);
  6928. #ifdef FEAT_CINDENT
  6929.     can_cindent = TRUE;
  6930. #endif
  6931.     }
  6932.     else
  6933.     vim_beep();
  6934. }
  6935.  
  6936.     static void
  6937. ins_down(startcol)
  6938.     int        startcol;    /* when TRUE move to Insstart.col */
  6939. {
  6940.     pos_T    tpos;
  6941.     linenr_T    old_topline = curwin->w_topline;
  6942. #ifdef FEAT_DIFF
  6943.     int        old_topfill = curwin->w_topfill;
  6944. #endif
  6945.  
  6946.     undisplay_dollar();
  6947.     tpos = curwin->w_cursor;
  6948.     if (cursor_down(1L, TRUE) == OK)
  6949.     {
  6950.     if (startcol)
  6951.         coladvance(getvcol_nolist(&Insstart));
  6952.     if (old_topline != curwin->w_topline
  6953. #ifdef FEAT_DIFF
  6954.         || old_topfill != curwin->w_topfill
  6955. #endif
  6956.         )
  6957.         redraw_later(VALID);
  6958.     start_arrow(&tpos);
  6959. #ifdef FEAT_CINDENT
  6960.     can_cindent = TRUE;
  6961. #endif
  6962.     }
  6963.     else
  6964.     vim_beep();
  6965. }
  6966.  
  6967.     static void
  6968. ins_pagedown()
  6969. {
  6970.     pos_T    tpos;
  6971.  
  6972.     undisplay_dollar();
  6973.     tpos = curwin->w_cursor;
  6974.     if (onepage(FORWARD, 1L) == OK)
  6975.     {
  6976.     start_arrow(&tpos);
  6977. #ifdef FEAT_CINDENT
  6978.     can_cindent = TRUE;
  6979. #endif
  6980.     }
  6981.     else
  6982.     vim_beep();
  6983. }
  6984.  
  6985. #ifdef FEAT_DND
  6986.     static void
  6987. ins_drop()
  6988. {
  6989.     do_put('~', BACKWARD, 1L, PUT_CURSEND);
  6990. }
  6991. #endif
  6992.  
  6993. /*
  6994.  * Handle TAB in Insert or Replace mode.
  6995.  * Return TRUE when the TAB needs to be inserted like a normal character.
  6996.  */
  6997.     static int
  6998. ins_tab()
  6999. {
  7000.     int        ind;
  7001.     int        i;
  7002.     int        temp;
  7003.  
  7004.     if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
  7005.     Insstart_blank_vcol = get_nolist_virtcol();
  7006.     if (echeck_abbr(TAB + ABBR_OFF))
  7007.     return FALSE;
  7008.  
  7009.     ind = inindent(0);
  7010. #ifdef FEAT_CINDENT
  7011.     if (ind)
  7012.     can_cindent = FALSE;
  7013. #endif
  7014.  
  7015.     /*
  7016.      * When nothing special, insert TAB like a normal character
  7017.      */
  7018.     if (!curbuf->b_p_et
  7019.         && !(p_sta && ind && curbuf->b_p_ts != curbuf->b_p_sw)
  7020.         && curbuf->b_p_sts == 0)
  7021.     return TRUE;
  7022.  
  7023.     if (stop_arrow() == FAIL)
  7024.     return TRUE;
  7025.  
  7026.     did_ai = FALSE;
  7027. #ifdef FEAT_SMARTINDENT
  7028.     did_si = FALSE;
  7029.     can_si = FALSE;
  7030.     can_si_back = FALSE;
  7031. #endif
  7032.     AppendToRedobuff((char_u *)"\t");
  7033.  
  7034.     if (p_sta && ind)        /* insert tab in indent, use 'shiftwidth' */
  7035.     temp = (int)curbuf->b_p_sw;
  7036.     else if (curbuf->b_p_sts > 0) /* use 'softtabstop' when set */
  7037.     temp = (int)curbuf->b_p_sts;
  7038.     else            /* otherwise use 'tabstop' */
  7039.     temp = (int)curbuf->b_p_ts;
  7040.     temp -= get_nolist_virtcol() % temp;
  7041.  
  7042.     /*
  7043.      * Insert the first space with ins_char().    It will delete one char in
  7044.      * replace mode.  Insert the rest with ins_str(); it will not delete any
  7045.      * chars.  For VREPLACE mode, we use ins_char() for all characters.
  7046.      */
  7047.     ins_char(' ');
  7048.     while (--temp > 0)
  7049.     {
  7050. #ifdef FEAT_VREPLACE
  7051.     if (State & VREPLACE_FLAG)
  7052.         ins_char(' ');
  7053.     else
  7054. #endif
  7055.     {
  7056.         ins_str((char_u *)" ");
  7057.         if (State & REPLACE_FLAG)        /* no char replaced */
  7058.         replace_push(NUL);
  7059.     }
  7060.     }
  7061.  
  7062.     /*
  7063.      * When 'expandtab' not set: Replace spaces by TABs where possible.
  7064.      */
  7065.     if (!curbuf->b_p_et && (curbuf->b_p_sts || (p_sta && ind)))
  7066.     {
  7067.     char_u        *ptr;
  7068. #ifdef FEAT_VREPLACE
  7069.     char_u        *saved_line = NULL;    /* init for GCC */
  7070.     pos_T        pos;
  7071. #endif
  7072.     pos_T        fpos;
  7073.     pos_T        *cursor;
  7074.     colnr_T        want_vcol, vcol;
  7075.     int        change_col = -1;
  7076.  
  7077.     /*
  7078.      * Get the current line.  For VREPLACE mode, don't make real changes
  7079.      * yet, just work on a copy of the line.
  7080.      */
  7081. #ifdef FEAT_VREPLACE
  7082.     if (State & VREPLACE_FLAG)
  7083.     {
  7084.         pos = curwin->w_cursor;
  7085.         cursor = &pos;
  7086.         saved_line = vim_strsave(ml_get_curline());
  7087.         if (saved_line == NULL)
  7088.         return FALSE;
  7089.         ptr = saved_line + pos.col;
  7090.     }
  7091.     else
  7092. #endif
  7093.     {
  7094.         ptr = ml_get_cursor();
  7095.         cursor = &curwin->w_cursor;
  7096.     }
  7097.  
  7098.     /* Find first white before the cursor */
  7099.     fpos = curwin->w_cursor;
  7100.     while (fpos.col > 0 && vim_iswhite(ptr[-1]))
  7101.     {
  7102.         --fpos.col;
  7103.         --ptr;
  7104.     }
  7105.  
  7106.     /* In Replace mode, don't change characters before the insert point. */
  7107.     if ((State & REPLACE_FLAG)
  7108.         && fpos.lnum == Insstart.lnum
  7109.         && fpos.col < Insstart.col)
  7110.     {
  7111.         ptr += Insstart.col - fpos.col;
  7112.         fpos.col = Insstart.col;
  7113.     }
  7114.  
  7115.     /* compute virtual column numbers of first white and cursor */
  7116.     getvcol(curwin, &fpos, &vcol, NULL, NULL);
  7117.     getvcol(curwin, cursor, &want_vcol, NULL, NULL);
  7118.  
  7119.     /* Use as many TABs as possible.  Beware of 'showbreak' and
  7120.      * 'linebreak' adding extra virtual columns. */
  7121.     while (vim_iswhite(*ptr))
  7122.     {
  7123.         i = lbr_chartabsize((char_u *)"\t", vcol);
  7124.         if (vcol + i > want_vcol)
  7125.         break;
  7126.         if (*ptr != TAB)
  7127.         {
  7128.         *ptr = TAB;
  7129.         if (change_col < 0)
  7130.         {
  7131.             change_col = fpos.col;  /* Column of first change */
  7132.             /* May have to adjust Insstart */
  7133.             if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col)
  7134.             Insstart.col = fpos.col;
  7135.         }
  7136.         }
  7137.         ++fpos.col;
  7138.         ++ptr;
  7139.         vcol += i;
  7140.     }
  7141.  
  7142.     if (change_col >= 0)
  7143.     {
  7144.         int repl_off = 0;
  7145.  
  7146.         /* Skip over the spaces we need. */
  7147.         while (vcol < want_vcol && *ptr == ' ')
  7148.         {
  7149.         vcol += lbr_chartabsize(ptr, vcol);
  7150.         ++ptr;
  7151.         ++repl_off;
  7152.         }
  7153.         if (vcol > want_vcol)
  7154.         {
  7155.         /* Must have a char with 'showbreak' just before it. */
  7156.         --ptr;
  7157.         --repl_off;
  7158.         }
  7159.         fpos.col += repl_off;
  7160.  
  7161.         /* Delete following spaces. */
  7162.         i = cursor->col - fpos.col;
  7163.         if (i > 0)
  7164.         {
  7165.         mch_memmove(ptr, ptr + i, STRLEN(ptr + i) + 1);
  7166.         /* correct replace stack. */
  7167.         if ((State & REPLACE_FLAG)
  7168. #ifdef FEAT_VREPLACE
  7169.             && !(State & VREPLACE_FLAG)
  7170. #endif
  7171.             )
  7172.             for (temp = i; --temp >= 0; )
  7173.             replace_join(repl_off);
  7174.         }
  7175.         cursor->col -= i;
  7176.  
  7177. #ifdef FEAT_VREPLACE
  7178.         /*
  7179.          * In VREPLACE mode, we haven't changed anything yet.  Do it now by
  7180.          * backspacing over the changed spacing and then inserting the new
  7181.          * spacing.
  7182.          */
  7183.         if (State & VREPLACE_FLAG)
  7184.         {
  7185.         /* Backspace from real cursor to change_col */
  7186.         backspace_until_column(change_col);
  7187.  
  7188.         /* Insert each char in saved_line from changed_col to
  7189.          * ptr-cursor */
  7190.         ins_bytes_len(saved_line + change_col,
  7191.                             cursor->col - change_col);
  7192.         }
  7193. #endif
  7194.     }
  7195.  
  7196. #ifdef FEAT_VREPLACE
  7197.     if (State & VREPLACE_FLAG)
  7198.         vim_free(saved_line);
  7199. #endif
  7200.     }
  7201.  
  7202.     return FALSE;
  7203. }
  7204.  
  7205. /*
  7206.  * Handle CR or NL in insert mode.
  7207.  * Return TRUE when out of memory or can't undo.
  7208.  */
  7209.     static int
  7210. ins_eol(c)
  7211.     int        c;
  7212. {
  7213.     int        i;
  7214.  
  7215.     if (echeck_abbr(c + ABBR_OFF))
  7216.     return FALSE;
  7217.     if (stop_arrow() == FAIL)
  7218.     return TRUE;
  7219.     undisplay_dollar();
  7220.  
  7221.     /*
  7222.      * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
  7223.      * character under the cursor.  Only push a NUL on the replace stack,
  7224.      * nothing to put back when the NL is deleted.
  7225.      */
  7226.     if ((State & REPLACE_FLAG)
  7227. #ifdef FEAT_VREPLACE
  7228.         && !(State & VREPLACE_FLAG)
  7229. #endif
  7230.         )
  7231.     replace_push(NUL);
  7232.  
  7233.     /*
  7234.      * In VREPLACE mode, a NL replaces the rest of the line, and starts
  7235.      * replacing the next line, so we push all of the characters left on the
  7236.      * line onto the replace stack.  This is not done here though, it is done
  7237.      * in open_line().
  7238.      */
  7239.  
  7240. #ifdef FEAT_RIGHTLEFT
  7241. # ifdef FEAT_FKMAP
  7242.     if (p_altkeymap && p_fkmap)
  7243.     fkmap(NL);
  7244. # endif
  7245.     /* NL in reverse insert will always start in the end of
  7246.      * current line. */
  7247.     if (revins_on)
  7248.     curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
  7249. #endif
  7250.  
  7251.     AppendToRedobuff(NL_STR);
  7252.     i = open_line(FORWARD,
  7253. #ifdef FEAT_COMMENTS
  7254.         has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
  7255. #endif
  7256.         0, old_indent);
  7257.     old_indent = 0;
  7258. #ifdef FEAT_CINDENT
  7259.     can_cindent = TRUE;
  7260. #endif
  7261.  
  7262.     return (!i);
  7263. }
  7264.  
  7265. #ifdef FEAT_DIGRAPHS
  7266. /*
  7267.  * Handle digraph in insert mode.
  7268.  * Returns character still to be inserted, or NUL when nothing remaining to be
  7269.  * done.
  7270.  */
  7271.     static int
  7272. ins_digraph()
  7273. {
  7274.     int        c;
  7275.     int        cc;
  7276.  
  7277.     pc_status = PC_STATUS_UNSET;
  7278.     if (redrawing() && !char_avail())
  7279.     {
  7280.     /* may need to redraw when no more chars available now */
  7281.     ins_redraw();
  7282.  
  7283.     edit_putchar('?', TRUE);
  7284. #ifdef FEAT_CMDL_INFO
  7285.     add_to_showcmd_c(Ctrl_K);
  7286. #endif
  7287.     }
  7288.  
  7289. #ifdef USE_ON_FLY_SCROLL
  7290.     dont_scroll = TRUE;        /* disallow scrolling here */
  7291. #endif
  7292.  
  7293.     /* don't map the digraph chars. This also prevents the
  7294.      * mode message to be deleted when ESC is hit */
  7295.     ++no_mapping;
  7296.     ++allow_keys;
  7297.     c = safe_vgetc();
  7298.     --no_mapping;
  7299.     --allow_keys;
  7300.     if (IS_SPECIAL(c) || mod_mask)        /* special key */
  7301.     {
  7302. #ifdef FEAT_CMDL_INFO
  7303.     clear_showcmd();
  7304. #endif
  7305.     insert_special(c, TRUE, FALSE);
  7306.     return NUL;
  7307.     }
  7308.     if (c != ESC)
  7309.     {
  7310.     if (redrawing() && !char_avail())
  7311.     {
  7312.         /* may need to redraw when no more chars available now */
  7313.         ins_redraw();
  7314.  
  7315.         if (char2cells(c) == 1)
  7316.         {
  7317.         /* first remove the '?', otherwise it's restored when typing
  7318.          * an ESC next */
  7319.         edit_unputchar();
  7320.         ins_redraw();
  7321.         edit_putchar(c, TRUE);
  7322.         }
  7323. #ifdef FEAT_CMDL_INFO
  7324.         add_to_showcmd_c(c);
  7325. #endif
  7326.     }
  7327.     ++no_mapping;
  7328.     ++allow_keys;
  7329.     cc = safe_vgetc();
  7330.     --no_mapping;
  7331.     --allow_keys;
  7332.     if (cc != ESC)
  7333.     {
  7334.         AppendToRedobuff((char_u *)CTRL_V_STR);
  7335.         c = getdigraph(c, cc, TRUE);
  7336. #ifdef FEAT_CMDL_INFO
  7337.         clear_showcmd();
  7338. #endif
  7339.         return c;
  7340.     }
  7341.     }
  7342.     edit_unputchar();
  7343. #ifdef FEAT_CMDL_INFO
  7344.     clear_showcmd();
  7345. #endif
  7346.     return NUL;
  7347. }
  7348. #endif
  7349.  
  7350. /*
  7351.  * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
  7352.  * Returns the char to be inserted, or NUL if none found.
  7353.  */
  7354.     static int
  7355. ins_copychar(lnum)
  7356.     linenr_T    lnum;
  7357. {
  7358.     int        c;
  7359.     int        temp;
  7360.     char_u  *ptr, *prev_ptr;
  7361.  
  7362.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
  7363.     {
  7364.     vim_beep();
  7365.     return NUL;
  7366.     }
  7367.  
  7368.     /* try to advance to the cursor column */
  7369.     temp = 0;
  7370.     ptr = ml_get(lnum);
  7371.     prev_ptr = ptr;
  7372.     validate_virtcol();
  7373.     while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
  7374.     {
  7375.     prev_ptr = ptr;
  7376.     temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp);
  7377.     }
  7378.     if ((colnr_T)temp > curwin->w_virtcol)
  7379.     ptr = prev_ptr;
  7380.  
  7381. #ifdef FEAT_MBYTE
  7382.     c = (*mb_ptr2char)(ptr);
  7383. #else
  7384.     c = *ptr;
  7385. #endif
  7386.     if (c == NUL)
  7387.     vim_beep();
  7388.     return c;
  7389. }
  7390.  
  7391. #ifdef FEAT_SMARTINDENT
  7392. /*
  7393.  * Try to do some very smart auto-indenting.
  7394.  * Used when inserting a "normal" character.
  7395.  */
  7396.     static void
  7397. ins_try_si(c)
  7398.     int        c;
  7399. {
  7400.     pos_T    *pos, old_pos;
  7401.     char_u    *ptr;
  7402.     int        i;
  7403.     int        temp;
  7404.  
  7405.     /*
  7406.      * do some very smart indenting when entering '{' or '}'
  7407.      */
  7408.     if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
  7409.     {
  7410.     /*
  7411.      * for '}' set indent equal to indent of line containing matching '{'
  7412.      */
  7413.     if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
  7414.     {
  7415.         old_pos = curwin->w_cursor;
  7416.         /*
  7417.          * If the matching '{' has a ')' immediately before it (ignoring
  7418.          * white-space), then line up with the start of the line
  7419.          * containing the matching '(' if there is one.  This handles the
  7420.          * case where an "if (..\n..) {" statement continues over multiple
  7421.          * lines -- webb
  7422.          */
  7423.         ptr = ml_get(pos->lnum);
  7424.         i = pos->col;
  7425.         if (i > 0)        /* skip blanks before '{' */
  7426.         while (--i > 0 && vim_iswhite(ptr[i]))
  7427.             ;
  7428.         curwin->w_cursor.lnum = pos->lnum;
  7429.         curwin->w_cursor.col = i;
  7430.         if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
  7431.         curwin->w_cursor = *pos;
  7432.         i = get_indent();
  7433.         curwin->w_cursor = old_pos;
  7434. #ifdef FEAT_VREPLACE
  7435.         if (State & VREPLACE_FLAG)
  7436.         change_indent(INDENT_SET, i, FALSE, NUL);
  7437.         else
  7438. #endif
  7439.         (void)set_indent(i, SIN_CHANGED);
  7440.     }
  7441.     else if (curwin->w_cursor.col > 0)
  7442.     {
  7443.         /*
  7444.          * when inserting '{' after "O" reduce indent, but not
  7445.          * more than indent of previous line
  7446.          */
  7447.         temp = TRUE;
  7448.         if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
  7449.         {
  7450.         old_pos = curwin->w_cursor;
  7451.         i = get_indent();
  7452.         while (curwin->w_cursor.lnum > 1)
  7453.         {
  7454.             ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
  7455.  
  7456.             /* ignore empty lines and lines starting with '#'. */
  7457.             if (*ptr != '#' && *ptr != NUL)
  7458.             break;
  7459.         }
  7460.         if (get_indent() >= i)
  7461.             temp = FALSE;
  7462.         curwin->w_cursor = old_pos;
  7463.         }
  7464.         if (temp)
  7465.         shift_line(TRUE, FALSE, 1);
  7466.     }
  7467.     }
  7468.  
  7469.     /*
  7470.      * set indent of '#' always to 0
  7471.      */
  7472.     if (curwin->w_cursor.col > 0 && can_si && c == '#')
  7473.     {
  7474.     /* remember current indent for next line */
  7475.     old_indent = get_indent();
  7476.     (void)set_indent(0, SIN_CHANGED);
  7477.     }
  7478.  
  7479.     /* Adjust ai_col, the char at this position can be deleted. */
  7480.     if (ai_col > curwin->w_cursor.col)
  7481.     ai_col = curwin->w_cursor.col;
  7482. }
  7483. #endif
  7484.  
  7485. /*
  7486.  * Get the value that w_virtcol would have when 'list' is off.
  7487.  * Unless 'cpo' contains the 'L' flag.
  7488.  */
  7489.     static colnr_T
  7490. get_nolist_virtcol()
  7491. {
  7492.     if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
  7493.     return getvcol_nolist(&curwin->w_cursor);
  7494.     validate_virtcol();
  7495.     return curwin->w_virtcol;
  7496. }
  7497.