xref: /vim-8.2.3635/src/edit.c (revision 147e7d0c)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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_NORMAL		0  /* CTRL-N CTRL-P completion, default */
23 # define CTRL_X_NOT_DEFINED_YET	1
24 # define CTRL_X_SCROLL		2
25 # define CTRL_X_WHOLE_LINE	3
26 # define CTRL_X_FILES		4
27 # define CTRL_X_TAGS		(5 + CTRL_X_WANT_IDENT)
28 # define CTRL_X_PATH_PATTERNS	(6 + CTRL_X_WANT_IDENT)
29 # define CTRL_X_PATH_DEFINES	(7 + CTRL_X_WANT_IDENT)
30 # define CTRL_X_FINISHED		8
31 # define CTRL_X_DICTIONARY	(9 + CTRL_X_WANT_IDENT)
32 # define CTRL_X_THESAURUS	(10 + CTRL_X_WANT_IDENT)
33 # define CTRL_X_CMDLINE		11
34 # define CTRL_X_FUNCTION		12
35 # define CTRL_X_OMNI		13
36 # define CTRL_X_SPELL		14
37 # define CTRL_X_LOCAL_MSG	15	/* only used in "ctrl_x_msgs" */
38 # define CTRL_X_EVAL		16	/* for builtin function complete() */
39 
40 # define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
41 # define CTRL_X_MODE_LINE_OR_EVAL(m) ((m) == CTRL_X_WHOLE_LINE || (m) == CTRL_X_EVAL)
42 
43 /* Message for CTRL-X mode, index is ctrl_x_mode. */
44 static char *ctrl_x_msgs[] =
45 {
46     N_(" Keyword completion (^N^P)"), /* CTRL_X_NORMAL, ^P/^N compl. */
47     N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
48     NULL, /* CTRL_X_SCROLL: depends on state */
49     N_(" Whole line completion (^L^N^P)"),
50     N_(" File name completion (^F^N^P)"),
51     N_(" Tag completion (^]^N^P)"),
52     N_(" Path pattern completion (^N^P)"),
53     N_(" Definition completion (^D^N^P)"),
54     NULL, /* CTRL_X_FINISHED */
55     N_(" Dictionary completion (^K^N^P)"),
56     N_(" Thesaurus completion (^T^N^P)"),
57     N_(" Command-line completion (^V^N^P)"),
58     N_(" User defined completion (^U^N^P)"),
59     N_(" Omni completion (^O^N^P)"),
60     N_(" Spelling suggestion (s^N^P)"),
61     N_(" Keyword Local completion (^N^P)"),
62     NULL,   /* CTRL_X_EVAL doesn't use msg. */
63 };
64 
65 static char e_hitend[] = N_("Hit end of paragraph");
66 # ifdef FEAT_COMPL_FUNC
67 static char e_complwin[] = N_("E839: Completion function changed window");
68 static char e_compldel[] = N_("E840: Completion function deleted text");
69 # endif
70 
71 /*
72  * Structure used to store one match for insert completion.
73  */
74 typedef struct compl_S compl_T;
75 struct compl_S
76 {
77     compl_T	*cp_next;
78     compl_T	*cp_prev;
79     char_u	*cp_str;	/* matched text */
80     char	cp_icase;	/* TRUE or FALSE: ignore case */
81     char_u	*(cp_text[CPT_COUNT]);	/* text for the menu */
82     char_u	*cp_fname;	/* file containing the match, allocated when
83 				 * cp_flags has FREE_FNAME */
84     int		cp_flags;	/* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
85     int		cp_number;	/* sequence number */
86 };
87 
88 # define ORIGINAL_TEXT	(1)   /* the original text when the expansion begun */
89 # define FREE_FNAME	(2)
90 
91 /*
92  * All the current matches are stored in a list.
93  * "compl_first_match" points to the start of the list.
94  * "compl_curr_match" points to the currently selected entry.
95  * "compl_shown_match" is different from compl_curr_match during
96  * ins_compl_get_exp().
97  */
98 static compl_T    *compl_first_match = NULL;
99 static compl_T    *compl_curr_match = NULL;
100 static compl_T    *compl_shown_match = NULL;
101 static compl_T    *compl_old_match = NULL;
102 
103 /* After using a cursor key <Enter> selects a match in the popup menu,
104  * otherwise it inserts a line break. */
105 static int	  compl_enter_selects = FALSE;
106 
107 /* When "compl_leader" is not NULL only matches that start with this string
108  * are used. */
109 static char_u	  *compl_leader = NULL;
110 
111 static int	  compl_get_longest = FALSE;	/* put longest common string
112 						   in compl_leader */
113 
114 static int	  compl_no_insert = FALSE;	/* FALSE: select & insert
115 						   TRUE: noinsert */
116 static int	  compl_no_select = FALSE;	/* FALSE: select & insert
117 						   TRUE: noselect */
118 
119 static int	  compl_used_match;	/* Selected one of the matches.  When
120 					   FALSE the match was edited or using
121 					   the longest common string. */
122 
123 static int	  compl_was_interrupted = FALSE;  /* didn't finish finding
124 						     completions. */
125 
126 static int	  compl_restarting = FALSE;	/* don't insert match */
127 
128 /* When the first completion is done "compl_started" is set.  When it's
129  * FALSE the word to be completed must be located. */
130 static int	  compl_started = FALSE;
131 
132 /* Which Ctrl-X mode are we in? */
133 static int	  ctrl_x_mode = CTRL_X_NORMAL;
134 
135 /* Set when doing something for completion that may call edit() recursively,
136  * which is not allowed. */
137 static int	  compl_busy = FALSE;
138 
139 static int	  compl_matches = 0;
140 static char_u	  *compl_pattern = NULL;
141 static int	  compl_direction = FORWARD;
142 static int	  compl_shows_dir = FORWARD;
143 static int	  compl_pending = 0;	    /* > 1 for postponed CTRL-N */
144 static pos_T	  compl_startpos;
145 static colnr_T	  compl_col = 0;	    /* column where the text starts
146 					     * that is being completed */
147 static char_u	  *compl_orig_text = NULL;  /* text as it was before
148 					     * completion started */
149 static int	  compl_cont_mode = 0;
150 static expand_T	  compl_xp;
151 
152 static int	  compl_opt_refresh_always = FALSE;
153 static int	  compl_opt_suppress_empty = FALSE;
154 
155 static void ins_ctrl_x(void);
156 static int  has_compl_option(int dict_opt);
157 static int  ins_compl_accept_char(int c);
158 static int ins_compl_add(char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup);
159 static void ins_compl_longest_match(compl_T *match);
160 static void ins_compl_del_pum(void);
161 static int  pum_wanted(void);
162 static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir);
163 static char_u *find_line_end(char_u *ptr);
164 static void ins_compl_free(void);
165 static void ins_compl_clear(void);
166 static int  ins_compl_bs(void);
167 static int  ins_compl_need_restart(void);
168 static void ins_compl_new_leader(void);
169 static void ins_compl_addleader(int c);
170 static int  ins_compl_len(void);
171 static void ins_compl_restart(void);
172 static void ins_compl_set_original_text(char_u *str);
173 static void ins_compl_addfrommatch(void);
174 static int  ins_compl_prep(int c);
175 static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
176 # if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
177 static void ins_compl_add_list(list_T *list);
178 static void ins_compl_add_dict(dict_T *dict);
179 # endif
180 static void ins_compl_delete(void);
181 static void ins_compl_insert(int in_compl_func);
182 static int  ins_compl_key2dir(int c);
183 static int  ins_compl_pum_key(int c);
184 static int  ins_compl_key2count(int c);
185 static int  ins_complete(int c, int enable_pum);
186 static void show_pum(int prev_w_wrow, int prev_w_leftcol);
187 static unsigned  quote_meta(char_u *dest, char_u *str, int len);
188 #endif /* FEAT_INS_EXPAND */
189 
190 #define BACKSPACE_CHAR		    1
191 #define BACKSPACE_WORD		    2
192 #define BACKSPACE_WORD_NOT_SPACE    3
193 #define BACKSPACE_LINE		    4
194 
195 static void ins_redraw(int ready);
196 static void ins_ctrl_v(void);
197 #ifdef FEAT_JOB_CHANNEL
198 static void init_prompt(int cmdchar_todo);
199 #endif
200 static void undisplay_dollar(void);
201 static void insert_special(int, int, int);
202 static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c);
203 static void check_auto_format(int);
204 static void redo_literal(int c);
205 static void start_arrow(pos_T *end_insert_pos);
206 static void start_arrow_common(pos_T *end_insert_pos, int change);
207 #ifdef FEAT_SPELL
208 static void check_spell_redraw(void);
209 static void spell_back_to_badword(void);
210 static int  spell_bad_len = 0;	/* length of located bad word */
211 #endif
212 static void stop_insert(pos_T *end_insert_pos, int esc, int nomove);
213 static int  echeck_abbr(int);
214 static void replace_join(int off);
215 #ifdef FEAT_MBYTE
216 static void mb_replace_pop_ins(int cc);
217 #endif
218 static void replace_flush(void);
219 static void replace_do_bs(int limit_col);
220 static int del_char_after_col(int limit_col);
221 #ifdef FEAT_CINDENT
222 static int cindent_on(void);
223 #endif
224 static void ins_reg(void);
225 static void ins_ctrl_g(void);
226 static void ins_ctrl_hat(void);
227 static int  ins_esc(long *count, int cmdchar, int nomove);
228 #ifdef FEAT_RIGHTLEFT
229 static void ins_ctrl_(void);
230 #endif
231 static int ins_start_select(int c);
232 static void ins_insert(int replaceState);
233 static void ins_ctrl_o(void);
234 static void ins_shift(int c, int lastc);
235 static void ins_del(void);
236 static int  ins_bs(int c, int mode, int *inserted_space_p);
237 #ifdef FEAT_MOUSE
238 static void ins_mouse(int c);
239 static void ins_mousescroll(int dir);
240 #endif
241 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
242 static void ins_tabline(int c);
243 #endif
244 static void ins_left(int end_change);
245 static void ins_home(int c);
246 static void ins_end(int c);
247 static void ins_s_left(void);
248 static void ins_right(int end_change);
249 static void ins_s_right(void);
250 static void ins_up(int startcol);
251 static void ins_pageup(void);
252 static void ins_down(int startcol);
253 static void ins_pagedown(void);
254 #ifdef FEAT_DND
255 static void ins_drop(void);
256 #endif
257 static int  ins_tab(void);
258 static int  ins_eol(int c);
259 #ifdef FEAT_DIGRAPHS
260 static int  ins_digraph(void);
261 #endif
262 static int  ins_ctrl_ey(int tc);
263 #ifdef FEAT_SMARTINDENT
264 static void ins_try_si(int c);
265 #endif
266 #if defined(FEAT_EVAL)
267 static char_u *do_insert_char_pre(int c);
268 #endif
269 static int ins_apply_autocmds(event_T event);
270 
271 static colnr_T	Insstart_textlen;	/* length of line when insert started */
272 static colnr_T	Insstart_blank_vcol;	/* vcol for first inserted blank */
273 static int	update_Insstart_orig = TRUE; /* set Insstart_orig to Insstart */
274 
275 static char_u	*last_insert = NULL;	/* the text of the previous insert,
276 					   K_SPECIAL and CSI are escaped */
277 static int	last_insert_skip; /* nr of chars in front of previous insert */
278 static int	new_insert_skip;  /* nr of chars in front of current insert */
279 static int	did_restart_edit;	/* "restart_edit" when calling edit() */
280 
281 #ifdef FEAT_CINDENT
282 static int	can_cindent;		/* may do cindenting on this line */
283 #endif
284 
285 static int	old_indent = 0;		/* for ^^D command in insert mode */
286 
287 #ifdef FEAT_RIGHTLEFT
288 static int	revins_on;		/* reverse insert mode on */
289 static int	revins_chars;		/* how much to skip after edit */
290 static int	revins_legal;		/* was the last char 'legal'? */
291 static int	revins_scol;		/* start column of revins session */
292 #endif
293 
294 static int	ins_need_undo;		/* call u_save() before inserting a
295 					   char.  Set when edit() is called.
296 					   after that arrow_used is used. */
297 
298 static int	did_add_space = FALSE;	/* auto_format() added an extra space
299 					   under the cursor */
300 static int	dont_sync_undo = FALSE;	/* CTRL-G U prevents syncing undo for
301 					   the next left/right cursor */
302 
303 /*
304  * edit(): Start inserting text.
305  *
306  * "cmdchar" can be:
307  * 'i'	normal insert command
308  * 'a'	normal append command
309  * K_PS bracketed paste
310  * 'R'	replace command
311  * 'r'	"r<CR>" command: insert one <CR>.  Note: count can be > 1, for redo,
312  *	but still only one <CR> is inserted.  The <Esc> is not used for redo.
313  * 'g'	"gI" command.
314  * 'V'	"gR" command for Virtual Replace mode.
315  * 'v'	"gr" command for single character Virtual Replace mode.
316  *
317  * This function is not called recursively.  For CTRL-O commands, it returns
318  * and lets the caller handle the Normal-mode command.
319  *
320  * Return TRUE if a CTRL-O command caused the return (insert mode pending).
321  */
322     int
323 edit(
324     int		cmdchar,
325     int		startln,	/* if set, insert at start of line */
326     long	count)
327 {
328     int		c = 0;
329     char_u	*ptr;
330     int		lastc = 0;
331     int		mincol;
332     static linenr_T o_lnum = 0;
333     int		i;
334     int		did_backspace = TRUE;	    /* previous char was backspace */
335 #ifdef FEAT_CINDENT
336     int		line_is_white = FALSE;	    /* line is empty before insert */
337 #endif
338     linenr_T	old_topline = 0;	    /* topline before insertion */
339 #ifdef FEAT_DIFF
340     int		old_topfill = -1;
341 #endif
342     int		inserted_space = FALSE;     /* just inserted a space */
343     int		replaceState = REPLACE;
344     int		nomove = FALSE;		    /* don't move cursor on return */
345 #ifdef FEAT_JOB_CHANNEL
346     int		cmdchar_todo = cmdchar;
347 #endif
348 
349     /* Remember whether editing was restarted after CTRL-O. */
350     did_restart_edit = restart_edit;
351 
352     /* sleep before redrawing, needed for "CTRL-O :" that results in an
353      * error message */
354     check_for_delay(TRUE);
355 
356     /* set Insstart_orig to Insstart */
357     update_Insstart_orig = TRUE;
358 
359 #ifdef HAVE_SANDBOX
360     /* Don't allow inserting in the sandbox. */
361     if (sandbox != 0)
362     {
363 	emsg(_(e_sandbox));
364 	return FALSE;
365     }
366 #endif
367     /* Don't allow changes in the buffer while editing the cmdline.  The
368      * caller of getcmdline() may get confused. */
369     if (textlock != 0)
370     {
371 	emsg(_(e_secure));
372 	return FALSE;
373     }
374 
375 #ifdef FEAT_INS_EXPAND
376     /* Don't allow recursive insert mode when busy with completion. */
377     if (compl_started || compl_busy || pum_visible())
378     {
379 	emsg(_(e_secure));
380 	return FALSE;
381     }
382     ins_compl_clear();	    /* clear stuff for CTRL-X mode */
383 #endif
384 
385     /*
386      * Trigger InsertEnter autocommands.  Do not do this for "r<CR>" or "grx".
387      */
388     if (cmdchar != 'r' && cmdchar != 'v')
389     {
390 	pos_T   save_cursor = curwin->w_cursor;
391 
392 #ifdef FEAT_EVAL
393 	if (cmdchar == 'R')
394 	    ptr = (char_u *)"r";
395 	else if (cmdchar == 'V')
396 	    ptr = (char_u *)"v";
397 	else
398 	    ptr = (char_u *)"i";
399 	set_vim_var_string(VV_INSERTMODE, ptr, 1);
400 	set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
401 #endif
402 	ins_apply_autocmds(EVENT_INSERTENTER);
403 
404 	/* Make sure the cursor didn't move.  Do call check_cursor_col() in
405 	 * case the text was modified.  Since Insert mode was not started yet
406 	 * a call to check_cursor_col() may move the cursor, especially with
407 	 * the "A" command, thus set State to avoid that. Also check that the
408 	 * line number is still valid (lines may have been deleted).
409 	 * Do not restore if v:char was set to a non-empty string. */
410 	if (!EQUAL_POS(curwin->w_cursor, save_cursor)
411 #ifdef FEAT_EVAL
412 		&& *get_vim_var_str(VV_CHAR) == NUL
413 #endif
414 		&& save_cursor.lnum <= curbuf->b_ml.ml_line_count)
415 	{
416 	    int save_state = State;
417 
418 	    curwin->w_cursor = save_cursor;
419 	    State = INSERT;
420 	    check_cursor_col();
421 	    State = save_state;
422 	}
423     }
424 
425 #ifdef FEAT_CONCEAL
426     /* Check if the cursor line needs redrawing before changing State.  If
427      * 'concealcursor' is "n" it needs to be redrawn without concealing. */
428     conceal_check_cursor_line();
429 #endif
430 
431 #ifdef FEAT_MOUSE
432     /*
433      * When doing a paste with the middle mouse button, Insstart is set to
434      * where the paste started.
435      */
436     if (where_paste_started.lnum != 0)
437 	Insstart = where_paste_started;
438     else
439 #endif
440     {
441 	Insstart = curwin->w_cursor;
442 	if (startln)
443 	    Insstart.col = 0;
444     }
445     Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
446     Insstart_blank_vcol = MAXCOL;
447     if (!did_ai)
448 	ai_col = 0;
449 
450     if (cmdchar != NUL && restart_edit == 0)
451     {
452 	ResetRedobuff();
453 	AppendNumberToRedobuff(count);
454 	if (cmdchar == 'V' || cmdchar == 'v')
455 	{
456 	    /* "gR" or "gr" command */
457 	    AppendCharToRedobuff('g');
458 	    AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R');
459 	}
460 	else
461 	{
462 	    if (cmdchar == K_PS)
463 		AppendCharToRedobuff('a');
464 	    else
465 		AppendCharToRedobuff(cmdchar);
466 	    if (cmdchar == 'g')		    /* "gI" command */
467 		AppendCharToRedobuff('I');
468 	    else if (cmdchar == 'r')	    /* "r<CR>" command */
469 		count = 1;		    /* insert only one <CR> */
470 	}
471     }
472 
473     if (cmdchar == 'R')
474     {
475 #ifdef FEAT_FKMAP
476 	if (p_fkmap && p_ri)
477 	{
478 	    beep_flush();
479 	    emsg(farsi_text_3);	    /* encoded in Farsi */
480 	    State = INSERT;
481 	}
482 	else
483 #endif
484 	State = REPLACE;
485     }
486     else if (cmdchar == 'V' || cmdchar == 'v')
487     {
488 	State = VREPLACE;
489 	replaceState = VREPLACE;
490 	orig_line_count = curbuf->b_ml.ml_line_count;
491 	vr_lines_changed = 1;
492     }
493     else
494 	State = INSERT;
495 
496     stop_insert_mode = FALSE;
497 
498     /*
499      * Need to recompute the cursor position, it might move when the cursor is
500      * on a TAB or special character.
501      */
502     curs_columns(TRUE);
503 
504     /*
505      * Enable langmap or IME, indicated by 'iminsert'.
506      * Note that IME may enabled/disabled without us noticing here, thus the
507      * 'iminsert' value may not reflect what is actually used.  It is updated
508      * when hitting <Esc>.
509      */
510     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
511 	State |= LANGMAP;
512 #ifdef HAVE_INPUT_METHOD
513     im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
514 #endif
515 
516 #ifdef FEAT_MOUSE
517     setmouse();
518 #endif
519 #ifdef FEAT_CMDL_INFO
520     clear_showcmd();
521 #endif
522 #ifdef FEAT_RIGHTLEFT
523     /* there is no reverse replace mode */
524     revins_on = (State == INSERT && p_ri);
525     if (revins_on)
526 	undisplay_dollar();
527     revins_chars = 0;
528     revins_legal = 0;
529     revins_scol = -1;
530 #endif
531     if (!p_ek)
532 	/* Disable bracketed paste mode, we won't recognize the escape
533 	 * sequences. */
534 	out_str(T_BD);
535 
536     /*
537      * Handle restarting Insert mode.
538      * Don't do this for "CTRL-O ." (repeat an insert): In that case we get
539      * here with something in the stuff buffer.
540      */
541     if (restart_edit != 0 && stuff_empty())
542     {
543 #ifdef FEAT_MOUSE
544 	/*
545 	 * After a paste we consider text typed to be part of the insert for
546 	 * the pasted text. You can backspace over the pasted text too.
547 	 */
548 	if (where_paste_started.lnum)
549 	    arrow_used = FALSE;
550 	else
551 #endif
552 	    arrow_used = TRUE;
553 	restart_edit = 0;
554 
555 	/*
556 	 * If the cursor was after the end-of-line before the CTRL-O and it is
557 	 * now at the end-of-line, put it after the end-of-line (this is not
558 	 * correct in very rare cases).
559 	 * Also do this if curswant is greater than the current virtual
560 	 * column.  Eg after "^O$" or "^O80|".
561 	 */
562 	validate_virtcol();
563 	update_curswant();
564 	if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum)
565 		    || curwin->w_curswant > curwin->w_virtcol)
566 		&& *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL)
567 	{
568 	    if (ptr[1] == NUL)
569 		++curwin->w_cursor.col;
570 #ifdef FEAT_MBYTE
571 	    else if (has_mbyte)
572 	    {
573 		i = (*mb_ptr2len)(ptr);
574 		if (ptr[i] == NUL)
575 		    curwin->w_cursor.col += i;
576 	    }
577 #endif
578 	}
579 	ins_at_eol = FALSE;
580     }
581     else
582 	arrow_used = FALSE;
583 
584     /* we are in insert mode now, don't need to start it anymore */
585     need_start_insertmode = FALSE;
586 
587     /* Need to save the line for undo before inserting the first char. */
588     ins_need_undo = TRUE;
589 
590 #ifdef FEAT_MOUSE
591     where_paste_started.lnum = 0;
592 #endif
593 #ifdef FEAT_CINDENT
594     can_cindent = TRUE;
595 #endif
596 #ifdef FEAT_FOLDING
597     /* The cursor line is not in a closed fold, unless 'insertmode' is set or
598      * restarting. */
599     if (!p_im && did_restart_edit == 0)
600 	foldOpenCursor();
601 #endif
602 
603     /*
604      * If 'showmode' is set, show the current (insert/replace/..) mode.
605      * A warning message for changing a readonly file is given here, before
606      * actually changing anything.  It's put after the mode, if any.
607      */
608     i = 0;
609     if (p_smd && msg_silent == 0)
610 	i = showmode();
611 
612     if (!p_im && did_restart_edit == 0)
613 	change_warning(i == 0 ? 0 : i + 1);
614 
615 #ifdef CURSOR_SHAPE
616     ui_cursor_shape();		/* may show different cursor shape */
617 #endif
618 #ifdef FEAT_DIGRAPHS
619     do_digraph(-1);		/* clear digraphs */
620 #endif
621 
622     /*
623      * Get the current length of the redo buffer, those characters have to be
624      * skipped if we want to get to the inserted characters.
625      */
626     ptr = get_inserted();
627     if (ptr == NULL)
628 	new_insert_skip = 0;
629     else
630     {
631 	new_insert_skip = (int)STRLEN(ptr);
632 	vim_free(ptr);
633     }
634 
635     old_indent = 0;
636 
637     /*
638      * Main loop in Insert mode: repeat until Insert mode is left.
639      */
640     for (;;)
641     {
642 #ifdef FEAT_RIGHTLEFT
643 	if (!revins_legal)
644 	    revins_scol = -1;	    /* reset on illegal motions */
645 	else
646 	    revins_legal = 0;
647 #endif
648 	if (arrow_used)	    /* don't repeat insert when arrow key used */
649 	    count = 0;
650 
651 	if (update_Insstart_orig)
652 	    Insstart_orig = Insstart;
653 
654 	if (stop_insert_mode
655 #ifdef FEAT_INS_EXPAND
656 		&& !pum_visible()
657 #endif
658 		)
659 	{
660 	    /* ":stopinsert" used or 'insertmode' reset */
661 	    count = 0;
662 	    goto doESCkey;
663 	}
664 
665 	/* set curwin->w_curswant for next K_DOWN or K_UP */
666 	if (!arrow_used)
667 	    curwin->w_set_curswant = TRUE;
668 
669 	/* If there is no typeahead may check for timestamps (e.g., for when a
670 	 * menu invoked a shell command). */
671 	if (stuff_empty())
672 	{
673 	    did_check_timestamps = FALSE;
674 	    if (need_check_timestamps)
675 		check_timestamps(FALSE);
676 	}
677 
678 	/*
679 	 * When emsg() was called msg_scroll will have been set.
680 	 */
681 	msg_scroll = FALSE;
682 
683 #ifdef FEAT_GUI
684 	/* When 'mousefocus' is set a mouse movement may have taken us to
685 	 * another window.  "need_mouse_correct" may then be set because of an
686 	 * autocommand. */
687 	if (need_mouse_correct)
688 	    gui_mouse_correct();
689 #endif
690 
691 #ifdef FEAT_FOLDING
692 	/* Open fold at the cursor line, according to 'foldopen'. */
693 	if (fdo_flags & FDO_INSERT)
694 	    foldOpenCursor();
695 	/* Close folds where the cursor isn't, according to 'foldclose' */
696 	if (!char_avail())
697 	    foldCheckClose();
698 #endif
699 
700 #ifdef FEAT_JOB_CHANNEL
701 	if (bt_prompt(curbuf))
702 	{
703 	    init_prompt(cmdchar_todo);
704 	    cmdchar_todo = NUL;
705 	}
706 #endif
707 
708 	/*
709 	 * If we inserted a character at the last position of the last line in
710 	 * the window, scroll the window one line up. This avoids an extra
711 	 * redraw.
712 	 * This is detected when the cursor column is smaller after inserting
713 	 * something.
714 	 * Don't do this when the topline changed already, it has
715 	 * already been adjusted (by insertchar() calling open_line())).
716 	 */
717 	if (curbuf->b_mod_set
718 		&& curwin->w_p_wrap
719 		&& !did_backspace
720 		&& curwin->w_topline == old_topline
721 #ifdef FEAT_DIFF
722 		&& curwin->w_topfill == old_topfill
723 #endif
724 		)
725 	{
726 	    mincol = curwin->w_wcol;
727 	    validate_cursor_col();
728 
729 	    if (
730 #ifdef FEAT_VARTABS
731 		(int)curwin->w_wcol < mincol - tabstop_at(
732 					  get_nolist_virtcol(), curbuf->b_p_ts,
733 							 curbuf->b_p_vts_array)
734 #else
735 		(int)curwin->w_wcol < mincol - curbuf->b_p_ts
736 #endif
737 		    && curwin->w_wrow == W_WINROW(curwin)
738 						 + curwin->w_height - 1 - p_so
739 		    && (curwin->w_cursor.lnum != curwin->w_topline
740 #ifdef FEAT_DIFF
741 			|| curwin->w_topfill > 0
742 #endif
743 		    ))
744 	    {
745 #ifdef FEAT_DIFF
746 		if (curwin->w_topfill > 0)
747 		    --curwin->w_topfill;
748 		else
749 #endif
750 #ifdef FEAT_FOLDING
751 		if (hasFolding(curwin->w_topline, NULL, &old_topline))
752 		    set_topline(curwin, old_topline + 1);
753 		else
754 #endif
755 		    set_topline(curwin, curwin->w_topline + 1);
756 	    }
757 	}
758 
759 	/* May need to adjust w_topline to show the cursor. */
760 	update_topline();
761 
762 	did_backspace = FALSE;
763 
764 	validate_cursor();		/* may set must_redraw */
765 
766 	/*
767 	 * Redraw the display when no characters are waiting.
768 	 * Also shows mode, ruler and positions cursor.
769 	 */
770 	ins_redraw(TRUE);
771 
772 	if (curwin->w_p_scb)
773 	    do_check_scrollbind(TRUE);
774 
775 	if (curwin->w_p_crb)
776 	    do_check_cursorbind();
777 	update_curswant();
778 	old_topline = curwin->w_topline;
779 #ifdef FEAT_DIFF
780 	old_topfill = curwin->w_topfill;
781 #endif
782 
783 #ifdef USE_ON_FLY_SCROLL
784 	dont_scroll = FALSE;		/* allow scrolling here */
785 #endif
786 
787 	/*
788 	 * Get a character for Insert mode.  Ignore K_IGNORE and K_NOP.
789 	 */
790 	if (c != K_CURSORHOLD)
791 	    lastc = c;		/* remember the previous char for CTRL-D */
792 
793 	/* After using CTRL-G U the next cursor key will not break undo. */
794 	if (dont_sync_undo == MAYBE)
795 	    dont_sync_undo = TRUE;
796 	else
797 	    dont_sync_undo = FALSE;
798 	if (cmdchar == K_PS)
799 	    /* Got here from normal mode when bracketed paste started. */
800 	    c = K_PS;
801 	else
802 	    do
803 	    {
804 		c = safe_vgetc();
805 
806 		if (stop_insert_mode)
807 		{
808 		    // Insert mode ended, possibly from a callback.
809 		    count = 0;
810 		    nomove = TRUE;
811 		    goto doESCkey;
812 		}
813 	    } while (c == K_IGNORE || c == K_NOP);
814 
815 	/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
816 	did_cursorhold = TRUE;
817 
818 #ifdef FEAT_RIGHTLEFT
819 	if (p_hkmap && KeyTyped)
820 	    c = hkmap(c);		/* Hebrew mode mapping */
821 #endif
822 #ifdef FEAT_FKMAP
823 	if (p_fkmap && KeyTyped)
824 	    c = fkmap(c);		/* Farsi mode mapping */
825 #endif
826 
827 #ifdef FEAT_INS_EXPAND
828 	/*
829 	 * Special handling of keys while the popup menu is visible or wanted
830 	 * and the cursor is still in the completed word.  Only when there is
831 	 * a match, skip this when no matches were found.
832 	 */
833 	if (compl_started
834 		&& pum_wanted()
835 		&& curwin->w_cursor.col >= compl_col
836 		&& (compl_shown_match == NULL
837 		    || compl_shown_match != compl_shown_match->cp_next))
838 	{
839 	    /* BS: Delete one character from "compl_leader". */
840 	    if ((c == K_BS || c == Ctrl_H)
841 			&& curwin->w_cursor.col > compl_col
842 			&& (c = ins_compl_bs()) == NUL)
843 		continue;
844 
845 	    /* When no match was selected or it was edited. */
846 	    if (!compl_used_match)
847 	    {
848 		/* CTRL-L: Add one character from the current match to
849 		 * "compl_leader".  Except when at the original match and
850 		 * there is nothing to add, CTRL-L works like CTRL-P then. */
851 		if (c == Ctrl_L
852 			&& (!CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
853 			    || (int)STRLEN(compl_shown_match->cp_str)
854 					  > curwin->w_cursor.col - compl_col))
855 		{
856 		    ins_compl_addfrommatch();
857 		    continue;
858 		}
859 
860 		/* A non-white character that fits in with the current
861 		 * completion: Add to "compl_leader". */
862 		if (ins_compl_accept_char(c))
863 		{
864 #if defined(FEAT_EVAL)
865 		    /* Trigger InsertCharPre. */
866 		    char_u *str = do_insert_char_pre(c);
867 		    char_u *p;
868 
869 		    if (str != NULL)
870 		    {
871 			for (p = str; *p != NUL; MB_PTR_ADV(p))
872 			    ins_compl_addleader(PTR2CHAR(p));
873 			vim_free(str);
874 		    }
875 		    else
876 #endif
877 			ins_compl_addleader(c);
878 		    continue;
879 		}
880 
881 		/* Pressing CTRL-Y selects the current match.  When
882 		 * compl_enter_selects is set the Enter key does the same. */
883 		if ((c == Ctrl_Y || (compl_enter_selects
884 				    && (c == CAR || c == K_KENTER || c == NL)))
885 			&& stop_arrow() == OK)
886 		{
887 		    ins_compl_delete();
888 		    ins_compl_insert(FALSE);
889 		}
890 	    }
891 	}
892 
893 	/* Prepare for or stop CTRL-X mode.  This doesn't do completion, but
894 	 * it does fix up the text when finishing completion. */
895 	compl_get_longest = FALSE;
896 	if (ins_compl_prep(c))
897 	    continue;
898 #endif
899 
900 	/* CTRL-\ CTRL-N goes to Normal mode,
901 	 * CTRL-\ CTRL-G goes to mode selected with 'insertmode',
902 	 * CTRL-\ CTRL-O is like CTRL-O but without moving the cursor.  */
903 	if (c == Ctrl_BSL)
904 	{
905 	    /* may need to redraw when no more chars available now */
906 	    ins_redraw(FALSE);
907 	    ++no_mapping;
908 	    ++allow_keys;
909 	    c = plain_vgetc();
910 	    --no_mapping;
911 	    --allow_keys;
912 	    if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O)
913 	    {
914 		/* it's something else */
915 		vungetc(c);
916 		c = Ctrl_BSL;
917 	    }
918 	    else if (c == Ctrl_G && p_im)
919 		continue;
920 	    else
921 	    {
922 		if (c == Ctrl_O)
923 		{
924 		    ins_ctrl_o();
925 		    ins_at_eol = FALSE;	/* cursor keeps its column */
926 		    nomove = TRUE;
927 		}
928 		count = 0;
929 		goto doESCkey;
930 	    }
931 	}
932 
933 #ifdef FEAT_DIGRAPHS
934 	c = do_digraph(c);
935 #endif
936 
937 #ifdef FEAT_INS_EXPAND
938 	if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE)
939 	    goto docomplete;
940 #endif
941 	if (c == Ctrl_V || c == Ctrl_Q)
942 	{
943 	    ins_ctrl_v();
944 	    c = Ctrl_V;	/* pretend CTRL-V is last typed character */
945 	    continue;
946 	}
947 
948 #ifdef FEAT_CINDENT
949 	if (cindent_on()
950 # ifdef FEAT_INS_EXPAND
951 		&& ctrl_x_mode == 0
952 # endif
953 	   )
954 	{
955 	    /* A key name preceded by a bang means this key is not to be
956 	     * inserted.  Skip ahead to the re-indenting below.
957 	     * A key name preceded by a star means that indenting has to be
958 	     * done before inserting the key. */
959 	    line_is_white = inindent(0);
960 	    if (in_cinkeys(c, '!', line_is_white))
961 		goto force_cindent;
962 	    if (can_cindent && in_cinkeys(c, '*', line_is_white)
963 							&& stop_arrow() == OK)
964 		do_c_expr_indent();
965 	}
966 #endif
967 
968 #ifdef FEAT_RIGHTLEFT
969 	if (curwin->w_p_rl)
970 	    switch (c)
971 	    {
972 		case K_LEFT:	c = K_RIGHT; break;
973 		case K_S_LEFT:	c = K_S_RIGHT; break;
974 		case K_C_LEFT:	c = K_C_RIGHT; break;
975 		case K_RIGHT:	c = K_LEFT; break;
976 		case K_S_RIGHT: c = K_S_LEFT; break;
977 		case K_C_RIGHT: c = K_C_LEFT; break;
978 	    }
979 #endif
980 
981 	/*
982 	 * If 'keymodel' contains "startsel", may start selection.  If it
983 	 * does, a CTRL-O and c will be stuffed, we need to get these
984 	 * characters.
985 	 */
986 	if (ins_start_select(c))
987 	    continue;
988 
989 	/*
990 	 * The big switch to handle a character in insert mode.
991 	 */
992 	switch (c)
993 	{
994 	case ESC:	/* End input mode */
995 	    if (echeck_abbr(ESC + ABBR_OFF))
996 		break;
997 	    /* FALLTHROUGH */
998 
999 	case Ctrl_C:	/* End input mode */
1000 #ifdef FEAT_CMDWIN
1001 	    if (c == Ctrl_C && cmdwin_type != 0)
1002 	    {
1003 		/* Close the cmdline window. */
1004 		cmdwin_result = K_IGNORE;
1005 		got_int = FALSE; /* don't stop executing autocommands et al. */
1006 		nomove = TRUE;
1007 		goto doESCkey;
1008 	    }
1009 #endif
1010 #ifdef FEAT_JOB_CHANNEL
1011 	    if (c == Ctrl_C && bt_prompt(curbuf))
1012 	    {
1013 		if (invoke_prompt_interrupt())
1014 		{
1015 		    if (!bt_prompt(curbuf))
1016 			// buffer changed to a non-prompt buffer, get out of
1017 			// Insert mode
1018 			goto doESCkey;
1019 		    break;
1020 		}
1021 	    }
1022 #endif
1023 
1024 #ifdef UNIX
1025 do_intr:
1026 #endif
1027 	    /* when 'insertmode' set, and not halfway a mapping, don't leave
1028 	     * Insert mode */
1029 	    if (goto_im())
1030 	    {
1031 		if (got_int)
1032 		{
1033 		    (void)vgetc();		/* flush all buffers */
1034 		    got_int = FALSE;
1035 		}
1036 		else
1037 		    vim_beep(BO_IM);
1038 		break;
1039 	    }
1040 doESCkey:
1041 	    /*
1042 	     * This is the ONLY return from edit()!
1043 	     */
1044 	    /* Always update o_lnum, so that a "CTRL-O ." that adds a line
1045 	     * still puts the cursor back after the inserted text. */
1046 	    if (ins_at_eol && gchar_cursor() == NUL)
1047 		o_lnum = curwin->w_cursor.lnum;
1048 
1049 	    if (ins_esc(&count, cmdchar, nomove))
1050 	    {
1051 		// When CTRL-C was typed got_int will be set, with the result
1052 		// that the autocommands won't be executed. When mapped got_int
1053 		// is not set, but let's keep the behavior the same.
1054 		if (cmdchar != 'r' && cmdchar != 'v' && c != Ctrl_C)
1055 		    ins_apply_autocmds(EVENT_INSERTLEAVE);
1056 		did_cursorhold = FALSE;
1057 		return (c == Ctrl_O);
1058 	    }
1059 	    continue;
1060 
1061 	case Ctrl_Z:	/* suspend when 'insertmode' set */
1062 	    if (!p_im)
1063 		goto normalchar;	/* insert CTRL-Z as normal char */
1064 	    do_cmdline_cmd((char_u *)"stop");
1065 #ifdef CURSOR_SHAPE
1066 	    ui_cursor_shape();		/* may need to update cursor shape */
1067 #endif
1068 	    continue;
1069 
1070 	case Ctrl_O:	/* execute one command */
1071 #ifdef FEAT_COMPL_FUNC
1072 	    if (ctrl_x_mode == CTRL_X_OMNI)
1073 		goto docomplete;
1074 #endif
1075 	    if (echeck_abbr(Ctrl_O + ABBR_OFF))
1076 		break;
1077 	    ins_ctrl_o();
1078 
1079 #ifdef FEAT_VIRTUALEDIT
1080 	    /* don't move the cursor left when 'virtualedit' has "onemore". */
1081 	    if (ve_flags & VE_ONEMORE)
1082 	    {
1083 		ins_at_eol = FALSE;
1084 		nomove = TRUE;
1085 	    }
1086 #endif
1087 	    count = 0;
1088 	    goto doESCkey;
1089 
1090 	case K_INS:	/* toggle insert/replace mode */
1091 	case K_KINS:
1092 	    ins_insert(replaceState);
1093 	    break;
1094 
1095 	case K_SELECT:	/* end of Select mode mapping - ignore */
1096 	    break;
1097 
1098 	case K_HELP:	/* Help key works like <ESC> <Help> */
1099 	case K_F1:
1100 	case K_XF1:
1101 	    stuffcharReadbuff(K_HELP);
1102 	    if (p_im)
1103 		need_start_insertmode = TRUE;
1104 	    goto doESCkey;
1105 
1106 #ifdef FEAT_NETBEANS_INTG
1107 	case K_F21:	/* NetBeans command */
1108 	    ++no_mapping;		/* don't map the next key hits */
1109 	    i = plain_vgetc();
1110 	    --no_mapping;
1111 	    netbeans_keycommand(i);
1112 	    break;
1113 #endif
1114 
1115 	case K_ZERO:	/* Insert the previously inserted text. */
1116 	case NUL:
1117 	case Ctrl_A:
1118 	    /* For ^@ the trailing ESC will end the insert, unless there is an
1119 	     * error.  */
1120 	    if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL
1121 						   && c != Ctrl_A && !p_im)
1122 		goto doESCkey;		/* quit insert mode */
1123 	    inserted_space = FALSE;
1124 	    break;
1125 
1126 	case Ctrl_R:	/* insert the contents of a register */
1127 	    ins_reg();
1128 	    auto_format(FALSE, TRUE);
1129 	    inserted_space = FALSE;
1130 	    break;
1131 
1132 	case Ctrl_G:	/* commands starting with CTRL-G */
1133 	    ins_ctrl_g();
1134 	    break;
1135 
1136 	case Ctrl_HAT:	/* switch input mode and/or langmap */
1137 	    ins_ctrl_hat();
1138 	    break;
1139 
1140 #ifdef FEAT_RIGHTLEFT
1141 	case Ctrl__:	/* switch between languages */
1142 	    if (!p_ari)
1143 		goto normalchar;
1144 	    ins_ctrl_();
1145 	    break;
1146 #endif
1147 
1148 	case Ctrl_D:	/* Make indent one shiftwidth smaller. */
1149 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
1150 	    if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
1151 		goto docomplete;
1152 #endif
1153 	    /* FALLTHROUGH */
1154 
1155 	case Ctrl_T:	/* Make indent one shiftwidth greater. */
1156 # ifdef FEAT_INS_EXPAND
1157 	    if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
1158 	    {
1159 		if (has_compl_option(FALSE))
1160 		    goto docomplete;
1161 		break;
1162 	    }
1163 # endif
1164 	    ins_shift(c, lastc);
1165 	    auto_format(FALSE, TRUE);
1166 	    inserted_space = FALSE;
1167 	    break;
1168 
1169 	case K_DEL:	/* delete character under the cursor */
1170 	case K_KDEL:
1171 	    ins_del();
1172 	    auto_format(FALSE, TRUE);
1173 	    break;
1174 
1175 	case K_BS:	/* delete character before the cursor */
1176 	case Ctrl_H:
1177 	    did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
1178 	    auto_format(FALSE, TRUE);
1179 	    break;
1180 
1181 	case Ctrl_W:	/* delete word before the cursor */
1182 #ifdef FEAT_JOB_CHANNEL
1183 	    if (bt_prompt(curbuf) && (mod_mask & MOD_MASK_SHIFT) == 0)
1184 	    {
1185 		// In a prompt window CTRL-W is used for window commands.
1186 		// Use Shift-CTRL-W to delete a word.
1187 		stuffcharReadbuff(Ctrl_W);
1188 		restart_edit = 'A';
1189 		nomove = TRUE;
1190 		count = 0;
1191 		goto doESCkey;
1192 	    }
1193 #endif
1194 	    did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
1195 	    auto_format(FALSE, TRUE);
1196 	    break;
1197 
1198 	case Ctrl_U:	/* delete all inserted text in current line */
1199 # ifdef FEAT_COMPL_FUNC
1200 	    /* CTRL-X CTRL-U completes with 'completefunc'. */
1201 	    if (ctrl_x_mode == CTRL_X_FUNCTION)
1202 		goto docomplete;
1203 # endif
1204 	    did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
1205 	    auto_format(FALSE, TRUE);
1206 	    inserted_space = FALSE;
1207 	    break;
1208 
1209 #ifdef FEAT_MOUSE
1210 	case K_LEFTMOUSE:   /* mouse keys */
1211 	case K_LEFTMOUSE_NM:
1212 	case K_LEFTDRAG:
1213 	case K_LEFTRELEASE:
1214 	case K_LEFTRELEASE_NM:
1215 	case K_MOUSEMOVE:
1216 	case K_MIDDLEMOUSE:
1217 	case K_MIDDLEDRAG:
1218 	case K_MIDDLERELEASE:
1219 	case K_RIGHTMOUSE:
1220 	case K_RIGHTDRAG:
1221 	case K_RIGHTRELEASE:
1222 	case K_X1MOUSE:
1223 	case K_X1DRAG:
1224 	case K_X1RELEASE:
1225 	case K_X2MOUSE:
1226 	case K_X2DRAG:
1227 	case K_X2RELEASE:
1228 	    ins_mouse(c);
1229 	    break;
1230 
1231 	case K_MOUSEDOWN: /* Default action for scroll wheel up: scroll up */
1232 	    ins_mousescroll(MSCR_DOWN);
1233 	    break;
1234 
1235 	case K_MOUSEUP:	/* Default action for scroll wheel down: scroll down */
1236 	    ins_mousescroll(MSCR_UP);
1237 	    break;
1238 
1239 	case K_MOUSELEFT: /* Scroll wheel left */
1240 	    ins_mousescroll(MSCR_LEFT);
1241 	    break;
1242 
1243 	case K_MOUSERIGHT: /* Scroll wheel right */
1244 	    ins_mousescroll(MSCR_RIGHT);
1245 	    break;
1246 #endif
1247 	case K_PS:
1248 	    bracketed_paste(PASTE_INSERT, FALSE, NULL);
1249 	    if (cmdchar == K_PS)
1250 		/* invoked from normal mode, bail out */
1251 		goto doESCkey;
1252 	    break;
1253 	case K_PE:
1254 	    /* Got K_PE without K_PS, ignore. */
1255 	    break;
1256 
1257 #ifdef FEAT_GUI_TABLINE
1258 	case K_TABLINE:
1259 	case K_TABMENU:
1260 	    ins_tabline(c);
1261 	    break;
1262 #endif
1263 
1264 	case K_IGNORE:	/* Something mapped to nothing */
1265 	    break;
1266 
1267 	case K_CURSORHOLD:	/* Didn't type something for a while. */
1268 	    ins_apply_autocmds(EVENT_CURSORHOLDI);
1269 	    did_cursorhold = TRUE;
1270 	    break;
1271 
1272 #ifdef FEAT_GUI_W32
1273 	    /* On Win32 ignore <M-F4>, we get it when closing the window was
1274 	     * cancelled. */
1275 	case K_F4:
1276 	    if (mod_mask != MOD_MASK_ALT)
1277 		goto normalchar;
1278 	    break;
1279 #endif
1280 
1281 #ifdef FEAT_GUI
1282 	case K_VER_SCROLLBAR:
1283 	    ins_scroll();
1284 	    break;
1285 
1286 	case K_HOR_SCROLLBAR:
1287 	    ins_horscroll();
1288 	    break;
1289 #endif
1290 
1291 	case K_HOME:	/* <Home> */
1292 	case K_KHOME:
1293 	case K_S_HOME:
1294 	case K_C_HOME:
1295 	    ins_home(c);
1296 	    break;
1297 
1298 	case K_END:	/* <End> */
1299 	case K_KEND:
1300 	case K_S_END:
1301 	case K_C_END:
1302 	    ins_end(c);
1303 	    break;
1304 
1305 	case K_LEFT:	/* <Left> */
1306 	    if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
1307 		ins_s_left();
1308 	    else
1309 		ins_left(dont_sync_undo == FALSE);
1310 	    break;
1311 
1312 	case K_S_LEFT:	/* <S-Left> */
1313 	case K_C_LEFT:
1314 	    ins_s_left();
1315 	    break;
1316 
1317 	case K_RIGHT:	/* <Right> */
1318 	    if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
1319 		ins_s_right();
1320 	    else
1321 		ins_right(dont_sync_undo == FALSE);
1322 	    break;
1323 
1324 	case K_S_RIGHT:	/* <S-Right> */
1325 	case K_C_RIGHT:
1326 	    ins_s_right();
1327 	    break;
1328 
1329 	case K_UP:	/* <Up> */
1330 #ifdef FEAT_INS_EXPAND
1331 	    if (pum_visible())
1332 		goto docomplete;
1333 #endif
1334 	    if (mod_mask & MOD_MASK_SHIFT)
1335 		ins_pageup();
1336 	    else
1337 		ins_up(FALSE);
1338 	    break;
1339 
1340 	case K_S_UP:	/* <S-Up> */
1341 	case K_PAGEUP:
1342 	case K_KPAGEUP:
1343 #ifdef FEAT_INS_EXPAND
1344 	    if (pum_visible())
1345 		goto docomplete;
1346 #endif
1347 	    ins_pageup();
1348 	    break;
1349 
1350 	case K_DOWN:	/* <Down> */
1351 #ifdef FEAT_INS_EXPAND
1352 	    if (pum_visible())
1353 		goto docomplete;
1354 #endif
1355 	    if (mod_mask & MOD_MASK_SHIFT)
1356 		ins_pagedown();
1357 	    else
1358 		ins_down(FALSE);
1359 	    break;
1360 
1361 	case K_S_DOWN:	/* <S-Down> */
1362 	case K_PAGEDOWN:
1363 	case K_KPAGEDOWN:
1364 #ifdef FEAT_INS_EXPAND
1365 	    if (pum_visible())
1366 		goto docomplete;
1367 #endif
1368 	    ins_pagedown();
1369 	    break;
1370 
1371 #ifdef FEAT_DND
1372 	case K_DROP:	/* drag-n-drop event */
1373 	    ins_drop();
1374 	    break;
1375 #endif
1376 
1377 	case K_S_TAB:	/* When not mapped, use like a normal TAB */
1378 	    c = TAB;
1379 	    /* FALLTHROUGH */
1380 
1381 	case TAB:	/* TAB or Complete patterns along path */
1382 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
1383 	    if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
1384 		goto docomplete;
1385 #endif
1386 	    inserted_space = FALSE;
1387 	    if (ins_tab())
1388 		goto normalchar;	/* insert TAB as a normal char */
1389 	    auto_format(FALSE, TRUE);
1390 	    break;
1391 
1392 	case K_KENTER:	/* <Enter> */
1393 	    c = CAR;
1394 	    /* FALLTHROUGH */
1395 	case CAR:
1396 	case NL:
1397 #if defined(FEAT_QUICKFIX)
1398 	    /* In a quickfix window a <CR> jumps to the error under the
1399 	     * cursor. */
1400 	    if (bt_quickfix(curbuf) && c == CAR)
1401 	    {
1402 		if (curwin->w_llist_ref == NULL)    /* quickfix window */
1403 		    do_cmdline_cmd((char_u *)".cc");
1404 		else				    /* location list window */
1405 		    do_cmdline_cmd((char_u *)".ll");
1406 		break;
1407 	    }
1408 #endif
1409 #ifdef FEAT_CMDWIN
1410 	    if (cmdwin_type != 0)
1411 	    {
1412 		/* Execute the command in the cmdline window. */
1413 		cmdwin_result = CAR;
1414 		goto doESCkey;
1415 	    }
1416 #endif
1417 #ifdef FEAT_JOB_CHANNEL
1418 	    if (bt_prompt(curbuf))
1419 	    {
1420 		invoke_prompt_callback();
1421 		if (!bt_prompt(curbuf))
1422 		    // buffer changed to a non-prompt buffer, get out of
1423 		    // Insert mode
1424 		    goto doESCkey;
1425 		break;
1426 	    }
1427 #endif
1428 	    if (ins_eol(c) == FAIL && !p_im)
1429 		goto doESCkey;	    /* out of memory */
1430 	    auto_format(FALSE, FALSE);
1431 	    inserted_space = FALSE;
1432 	    break;
1433 
1434 #if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND)
1435 	case Ctrl_K:	    /* digraph or keyword completion */
1436 # ifdef FEAT_INS_EXPAND
1437 	    if (ctrl_x_mode == CTRL_X_DICTIONARY)
1438 	    {
1439 		if (has_compl_option(TRUE))
1440 		    goto docomplete;
1441 		break;
1442 	    }
1443 # endif
1444 # ifdef FEAT_DIGRAPHS
1445 	    c = ins_digraph();
1446 	    if (c == NUL)
1447 		break;
1448 # endif
1449 	    goto normalchar;
1450 #endif
1451 
1452 #ifdef FEAT_INS_EXPAND
1453 	case Ctrl_X:	/* Enter CTRL-X mode */
1454 	    ins_ctrl_x();
1455 	    break;
1456 
1457 	case Ctrl_RSB:	/* Tag name completion after ^X */
1458 	    if (ctrl_x_mode != CTRL_X_TAGS)
1459 		goto normalchar;
1460 	    goto docomplete;
1461 
1462 	case Ctrl_F:	/* File name completion after ^X */
1463 	    if (ctrl_x_mode != CTRL_X_FILES)
1464 		goto normalchar;
1465 	    goto docomplete;
1466 
1467 	case 's':	/* Spelling completion after ^X */
1468 	case Ctrl_S:
1469 	    if (ctrl_x_mode != CTRL_X_SPELL)
1470 		goto normalchar;
1471 	    goto docomplete;
1472 #endif
1473 
1474 	case Ctrl_L:	/* Whole line completion after ^X */
1475 #ifdef FEAT_INS_EXPAND
1476 	    if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
1477 #endif
1478 	    {
1479 		/* CTRL-L with 'insertmode' set: Leave Insert mode */
1480 		if (p_im)
1481 		{
1482 		    if (echeck_abbr(Ctrl_L + ABBR_OFF))
1483 			break;
1484 		    goto doESCkey;
1485 		}
1486 		goto normalchar;
1487 	    }
1488 #ifdef FEAT_INS_EXPAND
1489 	    /* FALLTHROUGH */
1490 
1491 	case Ctrl_P:	/* Do previous/next pattern completion */
1492 	case Ctrl_N:
1493 	    /* if 'complete' is empty then plain ^P is no longer special,
1494 	     * but it is under other ^X modes */
1495 	    if (*curbuf->b_p_cpt == NUL
1496 		    && (ctrl_x_mode == CTRL_X_NORMAL
1497 			|| ctrl_x_mode == CTRL_X_WHOLE_LINE)
1498 		    && !(compl_cont_status & CONT_LOCAL))
1499 		goto normalchar;
1500 
1501 docomplete:
1502 	    compl_busy = TRUE;
1503 #ifdef FEAT_FOLDING
1504 	    disable_fold_update++;  /* don't redraw folds here */
1505 #endif
1506 	    if (ins_complete(c, TRUE) == FAIL)
1507 		compl_cont_status = 0;
1508 #ifdef FEAT_FOLDING
1509 	    disable_fold_update--;
1510 #endif
1511 	    compl_busy = FALSE;
1512 	    break;
1513 #endif /* FEAT_INS_EXPAND */
1514 
1515 	case Ctrl_Y:	/* copy from previous line or scroll down */
1516 	case Ctrl_E:	/* copy from next line	   or scroll up */
1517 	    c = ins_ctrl_ey(c);
1518 	    break;
1519 
1520 	  default:
1521 #ifdef UNIX
1522 	    if (c == intr_char)		/* special interrupt char */
1523 		goto do_intr;
1524 #endif
1525 
1526 normalchar:
1527 	    /*
1528 	     * Insert a normal character.
1529 	     */
1530 #if defined(FEAT_EVAL)
1531 	    if (!p_paste)
1532 	    {
1533 		/* Trigger InsertCharPre. */
1534 		char_u *str = do_insert_char_pre(c);
1535 		char_u *p;
1536 
1537 		if (str != NULL)
1538 		{
1539 		    if (*str != NUL && stop_arrow() != FAIL)
1540 		    {
1541 			/* Insert the new value of v:char literally. */
1542 			for (p = str; *p != NUL; MB_PTR_ADV(p))
1543 			{
1544 			    c = PTR2CHAR(p);
1545 			    if (c == CAR || c == K_KENTER || c == NL)
1546 				ins_eol(c);
1547 			    else
1548 				ins_char(c);
1549 			}
1550 			AppendToRedobuffLit(str, -1);
1551 		    }
1552 		    vim_free(str);
1553 		    c = NUL;
1554 		}
1555 
1556 		/* If the new value is already inserted or an empty string
1557 		 * then don't insert any character. */
1558 		if (c == NUL)
1559 		    break;
1560 	    }
1561 #endif
1562 #ifdef FEAT_SMARTINDENT
1563 	    /* Try to perform smart-indenting. */
1564 	    ins_try_si(c);
1565 #endif
1566 
1567 	    if (c == ' ')
1568 	    {
1569 		inserted_space = TRUE;
1570 #ifdef FEAT_CINDENT
1571 		if (inindent(0))
1572 		    can_cindent = FALSE;
1573 #endif
1574 		if (Insstart_blank_vcol == MAXCOL
1575 			&& curwin->w_cursor.lnum == Insstart.lnum)
1576 		    Insstart_blank_vcol = get_nolist_virtcol();
1577 	    }
1578 
1579 	    /* Insert a normal character and check for abbreviations on a
1580 	     * special character.  Let CTRL-] expand abbreviations without
1581 	     * inserting it. */
1582 	    if (vim_iswordc(c) || (!echeck_abbr(
1583 #ifdef FEAT_MBYTE
1584 			/* Add ABBR_OFF for characters above 0x100, this is
1585 			 * what check_abbr() expects. */
1586 			(has_mbyte && c >= 0x100) ? (c + ABBR_OFF) :
1587 #endif
1588 		       c) && c != Ctrl_RSB))
1589 	    {
1590 		insert_special(c, FALSE, FALSE);
1591 #ifdef FEAT_RIGHTLEFT
1592 		revins_legal++;
1593 		revins_chars++;
1594 #endif
1595 	    }
1596 
1597 	    auto_format(FALSE, TRUE);
1598 
1599 #ifdef FEAT_FOLDING
1600 	    /* When inserting a character the cursor line must never be in a
1601 	     * closed fold. */
1602 	    foldOpenCursor();
1603 #endif
1604 	    break;
1605 	}   /* end of switch (c) */
1606 
1607 	/* If typed something may trigger CursorHoldI again. */
1608 	if (c != K_CURSORHOLD
1609 #ifdef FEAT_COMPL_FUNC
1610 		/* but not in CTRL-X mode, a script can't restore the state */
1611 		&& ctrl_x_mode == CTRL_X_NORMAL
1612 #endif
1613 	       )
1614 	    did_cursorhold = FALSE;
1615 
1616 	/* If the cursor was moved we didn't just insert a space */
1617 	if (arrow_used)
1618 	    inserted_space = FALSE;
1619 
1620 #ifdef FEAT_CINDENT
1621 	if (can_cindent && cindent_on()
1622 # ifdef FEAT_INS_EXPAND
1623 		&& ctrl_x_mode == CTRL_X_NORMAL
1624 # endif
1625 	   )
1626 	{
1627 force_cindent:
1628 	    /*
1629 	     * Indent now if a key was typed that is in 'cinkeys'.
1630 	     */
1631 	    if (in_cinkeys(c, ' ', line_is_white))
1632 	    {
1633 		if (stop_arrow() == OK)
1634 		    /* re-indent the current line */
1635 		    do_c_expr_indent();
1636 	    }
1637 	}
1638 #endif /* FEAT_CINDENT */
1639 
1640     }	/* for (;;) */
1641     /* NOTREACHED */
1642 }
1643 
1644 /*
1645  * Redraw for Insert mode.
1646  * This is postponed until getting the next character to make '$' in the 'cpo'
1647  * option work correctly.
1648  * Only redraw when there are no characters available.  This speeds up
1649  * inserting sequences of characters (e.g., for CTRL-R).
1650  */
1651     static void
1652 ins_redraw(
1653     int		ready UNUSED)	    /* not busy with something */
1654 {
1655 #ifdef FEAT_CONCEAL
1656     linenr_T	conceal_old_cursor_line = 0;
1657     linenr_T	conceal_new_cursor_line = 0;
1658     int		conceal_update_lines = FALSE;
1659 #endif
1660 
1661     if (char_avail())
1662 	return;
1663 
1664 #if defined(FEAT_CONCEAL)
1665     /* Trigger CursorMoved if the cursor moved.  Not when the popup menu is
1666      * visible, the command might delete it. */
1667     if (ready && (has_cursormovedI()
1668 # if defined(FEAT_CONCEAL)
1669 		|| curwin->w_p_cole > 0
1670 # endif
1671 		)
1672 	    && !EQUAL_POS(last_cursormoved, curwin->w_cursor)
1673 # ifdef FEAT_INS_EXPAND
1674 	    && !pum_visible()
1675 # endif
1676        )
1677     {
1678 # ifdef FEAT_SYN_HL
1679 	/* Need to update the screen first, to make sure syntax
1680 	 * highlighting is correct after making a change (e.g., inserting
1681 	 * a "(".  The autocommand may also require a redraw, so it's done
1682 	 * again below, unfortunately. */
1683 	if (syntax_present(curwin) && must_redraw)
1684 	    update_screen(0);
1685 # endif
1686 	if (has_cursormovedI())
1687 	{
1688 	    /* Make sure curswant is correct, an autocommand may call
1689 	     * getcurpos(). */
1690 	    update_curswant();
1691 	    ins_apply_autocmds(EVENT_CURSORMOVEDI);
1692 	}
1693 # ifdef FEAT_CONCEAL
1694 	if (curwin->w_p_cole > 0)
1695 	{
1696 	    conceal_old_cursor_line = last_cursormoved.lnum;
1697 	    conceal_new_cursor_line = curwin->w_cursor.lnum;
1698 	    conceal_update_lines = TRUE;
1699 	}
1700 # endif
1701 	last_cursormoved = curwin->w_cursor;
1702     }
1703 #endif
1704 
1705     /* Trigger TextChangedI if b_changedtick differs. */
1706     if (ready && has_textchangedI()
1707 	    && curbuf->b_last_changedtick != CHANGEDTICK(curbuf)
1708 #ifdef FEAT_INS_EXPAND
1709 	    && !pum_visible()
1710 #endif
1711 	    )
1712     {
1713 	aco_save_T	aco;
1714 	varnumber_T	tick = CHANGEDTICK(curbuf);
1715 
1716 	// save and restore curwin and curbuf, in case the autocmd changes them
1717 	aucmd_prepbuf(&aco, curbuf);
1718 	apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
1719 	aucmd_restbuf(&aco);
1720 	curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
1721 	if (tick != CHANGEDTICK(curbuf))  // see ins_apply_autocmds()
1722 	    u_save(curwin->w_cursor.lnum,
1723 					(linenr_T)(curwin->w_cursor.lnum + 1));
1724     }
1725 
1726 #ifdef FEAT_INS_EXPAND
1727     /* Trigger TextChangedP if b_changedtick differs. When the popupmenu closes
1728      * TextChangedI will need to trigger for backwards compatibility, thus use
1729      * different b_last_changedtick* variables. */
1730     if (ready && has_textchangedP()
1731 	    && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf)
1732 	    && pum_visible())
1733     {
1734 	aco_save_T	aco;
1735 	varnumber_T	tick = CHANGEDTICK(curbuf);
1736 
1737 	// save and restore curwin and curbuf, in case the autocmd changes them
1738 	aucmd_prepbuf(&aco, curbuf);
1739 	apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
1740 	aucmd_restbuf(&aco);
1741 	curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf);
1742 	if (tick != CHANGEDTICK(curbuf))  // see ins_apply_autocmds()
1743 	    u_save(curwin->w_cursor.lnum,
1744 					(linenr_T)(curwin->w_cursor.lnum + 1));
1745     }
1746 #endif
1747 
1748 #if defined(FEAT_CONCEAL)
1749     if ((conceal_update_lines
1750 	    && (conceal_old_cursor_line != conceal_new_cursor_line
1751 		|| conceal_cursor_line(curwin)))
1752 	    || need_cursor_line_redraw)
1753     {
1754 	if (conceal_old_cursor_line != conceal_new_cursor_line)
1755 	    redrawWinline(curwin, conceal_old_cursor_line);
1756 	redrawWinline(curwin, conceal_new_cursor_line == 0
1757 			    ? curwin->w_cursor.lnum : conceal_new_cursor_line);
1758 	curwin->w_valid &= ~VALID_CROW;
1759 	need_cursor_line_redraw = FALSE;
1760     }
1761 #endif
1762     if (must_redraw)
1763 	update_screen(0);
1764     else if (clear_cmdline || redraw_cmdline)
1765 	showmode();		/* clear cmdline and show mode */
1766     showruler(FALSE);
1767     setcursor();
1768     emsg_on_display = FALSE;	/* may remove error message now */
1769 }
1770 
1771 /*
1772  * Handle a CTRL-V or CTRL-Q typed in Insert mode.
1773  */
1774     static void
1775 ins_ctrl_v(void)
1776 {
1777     int		c;
1778     int		did_putchar = FALSE;
1779 
1780     /* may need to redraw when no more chars available now */
1781     ins_redraw(FALSE);
1782 
1783     if (redrawing() && !char_avail())
1784     {
1785 	edit_putchar('^', TRUE);
1786 	did_putchar = TRUE;
1787     }
1788     AppendToRedobuff((char_u *)CTRL_V_STR);	/* CTRL-V */
1789 
1790 #ifdef FEAT_CMDL_INFO
1791     add_to_showcmd_c(Ctrl_V);
1792 #endif
1793 
1794     c = get_literal();
1795     if (did_putchar)
1796 	/* when the line fits in 'columns' the '^' is at the start of the next
1797 	 * line and will not removed by the redraw */
1798 	edit_unputchar();
1799 #ifdef FEAT_CMDL_INFO
1800     clear_showcmd();
1801 #endif
1802     insert_special(c, FALSE, TRUE);
1803 #ifdef FEAT_RIGHTLEFT
1804     revins_chars++;
1805     revins_legal++;
1806 #endif
1807 }
1808 
1809 /*
1810  * Put a character directly onto the screen.  It's not stored in a buffer.
1811  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
1812  */
1813 static int  pc_status;
1814 #define PC_STATUS_UNSET	0	/* pc_bytes was not set */
1815 #define PC_STATUS_RIGHT	1	/* right halve of double-wide char */
1816 #define PC_STATUS_LEFT	2	/* left halve of double-wide char */
1817 #define PC_STATUS_SET	3	/* pc_bytes was filled */
1818 static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */
1819 static int  pc_attr;
1820 static int  pc_row;
1821 static int  pc_col;
1822 
1823     void
1824 edit_putchar(int c, int highlight)
1825 {
1826     int	    attr;
1827 
1828     if (ScreenLines != NULL)
1829     {
1830 	update_topline();	/* just in case w_topline isn't valid */
1831 	validate_cursor();
1832 	if (highlight)
1833 	    attr = HL_ATTR(HLF_8);
1834 	else
1835 	    attr = 0;
1836 	pc_row = W_WINROW(curwin) + curwin->w_wrow;
1837 	pc_col = curwin->w_wincol;
1838 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
1839 	pc_status = PC_STATUS_UNSET;
1840 #endif
1841 #ifdef FEAT_RIGHTLEFT
1842 	if (curwin->w_p_rl)
1843 	{
1844 	    pc_col += curwin->w_width - 1 - curwin->w_wcol;
1845 # ifdef FEAT_MBYTE
1846 	    if (has_mbyte)
1847 	    {
1848 		int fix_col = mb_fix_col(pc_col, pc_row);
1849 
1850 		if (fix_col != pc_col)
1851 		{
1852 		    screen_putchar(' ', pc_row, fix_col, attr);
1853 		    --curwin->w_wcol;
1854 		    pc_status = PC_STATUS_RIGHT;
1855 		}
1856 	    }
1857 # endif
1858 	}
1859 	else
1860 #endif
1861 	{
1862 	    pc_col += curwin->w_wcol;
1863 #ifdef FEAT_MBYTE
1864 	    if (mb_lefthalve(pc_row, pc_col))
1865 		pc_status = PC_STATUS_LEFT;
1866 #endif
1867 	}
1868 
1869 	/* save the character to be able to put it back */
1870 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
1871 	if (pc_status == PC_STATUS_UNSET)
1872 #endif
1873 	{
1874 	    screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
1875 	    pc_status = PC_STATUS_SET;
1876 	}
1877 	screen_putchar(c, pc_row, pc_col, attr);
1878     }
1879 }
1880 
1881 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
1882 /*
1883  * Return the effective prompt for the current buffer.
1884  */
1885     char_u *
1886 prompt_text(void)
1887 {
1888     if (curbuf->b_prompt_text == NULL)
1889 	return (char_u *)"% ";
1890     return curbuf->b_prompt_text;
1891 }
1892 
1893 /*
1894  * Prepare for prompt mode: Make sure the last line has the prompt text.
1895  * Move the cursor to this line.
1896  */
1897     static void
1898 init_prompt(int cmdchar_todo)
1899 {
1900     char_u *prompt = prompt_text();
1901     char_u *text;
1902 
1903     curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
1904     text = ml_get_curline();
1905     if (STRNCMP(text, prompt, STRLEN(prompt)) != 0)
1906     {
1907 	// prompt is missing, insert it or append a line with it
1908 	if (*text == NUL)
1909 	    ml_replace(curbuf->b_ml.ml_line_count, prompt, TRUE);
1910 	else
1911 	    ml_append(curbuf->b_ml.ml_line_count, prompt, 0, FALSE);
1912 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
1913 	coladvance((colnr_T)MAXCOL);
1914 	changed_bytes(curbuf->b_ml.ml_line_count, 0);
1915     }
1916 
1917     // Insert always starts after the prompt, allow editing text after it.
1918     if (Insstart_orig.lnum != curwin->w_cursor.lnum
1919 				   || Insstart_orig.col != (int)STRLEN(prompt))
1920     {
1921 	Insstart.lnum = curwin->w_cursor.lnum;
1922 	Insstart.col = (int)STRLEN(prompt);
1923 	Insstart_orig = Insstart;
1924 	Insstart_textlen = Insstart.col;
1925 	Insstart_blank_vcol = MAXCOL;
1926 	arrow_used = FALSE;
1927     }
1928 
1929     if (cmdchar_todo == 'A')
1930 	coladvance((colnr_T)MAXCOL);
1931     if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt))
1932 	curwin->w_cursor.col = (int)STRLEN(prompt);
1933     /* Make sure the cursor is in a valid position. */
1934     check_cursor();
1935 }
1936 
1937 /*
1938  * Return TRUE if the cursor is in the editable position of the prompt line.
1939  */
1940     int
1941 prompt_curpos_editable()
1942 {
1943     return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
1944 	&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
1945 }
1946 #endif
1947 
1948 /*
1949  * Undo the previous edit_putchar().
1950  */
1951     void
1952 edit_unputchar(void)
1953 {
1954     if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled)
1955     {
1956 #if defined(FEAT_MBYTE)
1957 	if (pc_status == PC_STATUS_RIGHT)
1958 	    ++curwin->w_wcol;
1959 	if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT)
1960 	    redrawWinline(curwin, curwin->w_cursor.lnum);
1961 	else
1962 #endif
1963 	    screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
1964     }
1965 }
1966 
1967 /*
1968  * Called when p_dollar is set: display a '$' at the end of the changed text
1969  * Only works when cursor is in the line that changes.
1970  */
1971     void
1972 display_dollar(colnr_T col)
1973 {
1974     colnr_T save_col;
1975 
1976     if (!redrawing())
1977 	return;
1978 
1979     cursor_off();
1980     save_col = curwin->w_cursor.col;
1981     curwin->w_cursor.col = col;
1982 #ifdef FEAT_MBYTE
1983     if (has_mbyte)
1984     {
1985 	char_u *p;
1986 
1987 	/* If on the last byte of a multi-byte move to the first byte. */
1988 	p = ml_get_curline();
1989 	curwin->w_cursor.col -= (*mb_head_off)(p, p + col);
1990     }
1991 #endif
1992     curs_columns(FALSE);	    /* recompute w_wrow and w_wcol */
1993     if (curwin->w_wcol < curwin->w_width)
1994     {
1995 	edit_putchar('$', FALSE);
1996 	dollar_vcol = curwin->w_virtcol;
1997     }
1998     curwin->w_cursor.col = save_col;
1999 }
2000 
2001 /*
2002  * Call this function before moving the cursor from the normal insert position
2003  * in insert mode.
2004  */
2005     static void
2006 undisplay_dollar(void)
2007 {
2008     if (dollar_vcol >= 0)
2009     {
2010 	dollar_vcol = -1;
2011 	redrawWinline(curwin, curwin->w_cursor.lnum);
2012     }
2013 }
2014 
2015 /*
2016  * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
2017  * Keep the cursor on the same character.
2018  * type == INDENT_INC	increase indent (for CTRL-T or <Tab>)
2019  * type == INDENT_DEC	decrease indent (for CTRL-D)
2020  * type == INDENT_SET	set indent to "amount"
2021  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
2022  */
2023     void
2024 change_indent(
2025     int		type,
2026     int		amount,
2027     int		round,
2028     int		replaced,	/* replaced character, put on replace stack */
2029     int		call_changed_bytes)	/* call changed_bytes() */
2030 {
2031     int		vcol;
2032     int		last_vcol;
2033     int		insstart_less;		/* reduction for Insstart.col */
2034     int		new_cursor_col;
2035     int		i;
2036     char_u	*ptr;
2037     int		save_p_list;
2038     int		start_col;
2039     colnr_T	vc;
2040     colnr_T	orig_col = 0;		/* init for GCC */
2041     char_u	*new_line, *orig_line = NULL;	/* init for GCC */
2042 
2043     /* VREPLACE mode needs to know what the line was like before changing */
2044     if (State & VREPLACE_FLAG)
2045     {
2046 	orig_line = vim_strsave(ml_get_curline());  /* Deal with NULL below */
2047 	orig_col = curwin->w_cursor.col;
2048     }
2049 
2050     /* for the following tricks we don't want list mode */
2051     save_p_list = curwin->w_p_list;
2052     curwin->w_p_list = FALSE;
2053     vc = getvcol_nolist(&curwin->w_cursor);
2054     vcol = vc;
2055 
2056     /*
2057      * For Replace mode we need to fix the replace stack later, which is only
2058      * possible when the cursor is in the indent.  Remember the number of
2059      * characters before the cursor if it's possible.
2060      */
2061     start_col = curwin->w_cursor.col;
2062 
2063     /* determine offset from first non-blank */
2064     new_cursor_col = curwin->w_cursor.col;
2065     beginline(BL_WHITE);
2066     new_cursor_col -= curwin->w_cursor.col;
2067 
2068     insstart_less = curwin->w_cursor.col;
2069 
2070     /*
2071      * If the cursor is in the indent, compute how many screen columns the
2072      * cursor is to the left of the first non-blank.
2073      */
2074     if (new_cursor_col < 0)
2075 	vcol = get_indent() - vcol;
2076 
2077     if (new_cursor_col > 0)	    /* can't fix replace stack */
2078 	start_col = -1;
2079 
2080     /*
2081      * Set the new indent.  The cursor will be put on the first non-blank.
2082      */
2083     if (type == INDENT_SET)
2084 	(void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
2085     else
2086     {
2087 	int	save_State = State;
2088 
2089 	/* Avoid being called recursively. */
2090 	if (State & VREPLACE_FLAG)
2091 	    State = INSERT;
2092 	shift_line(type == INDENT_DEC, round, 1, call_changed_bytes);
2093 	State = save_State;
2094     }
2095     insstart_less -= curwin->w_cursor.col;
2096 
2097     /*
2098      * Try to put cursor on same character.
2099      * If the cursor is at or after the first non-blank in the line,
2100      * compute the cursor column relative to the column of the first
2101      * non-blank character.
2102      * If we are not in insert mode, leave the cursor on the first non-blank.
2103      * If the cursor is before the first non-blank, position it relative
2104      * to the first non-blank, counted in screen columns.
2105      */
2106     if (new_cursor_col >= 0)
2107     {
2108 	/*
2109 	 * When changing the indent while the cursor is touching it, reset
2110 	 * Insstart_col to 0.
2111 	 */
2112 	if (new_cursor_col == 0)
2113 	    insstart_less = MAXCOL;
2114 	new_cursor_col += curwin->w_cursor.col;
2115     }
2116     else if (!(State & INSERT))
2117 	new_cursor_col = curwin->w_cursor.col;
2118     else
2119     {
2120 	/*
2121 	 * Compute the screen column where the cursor should be.
2122 	 */
2123 	vcol = get_indent() - vcol;
2124 	curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
2125 
2126 	/*
2127 	 * Advance the cursor until we reach the right screen column.
2128 	 */
2129 	vcol = last_vcol = 0;
2130 	new_cursor_col = -1;
2131 	ptr = ml_get_curline();
2132 	while (vcol <= (int)curwin->w_virtcol)
2133 	{
2134 	    last_vcol = vcol;
2135 #ifdef FEAT_MBYTE
2136 	    if (has_mbyte && new_cursor_col >= 0)
2137 		new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col);
2138 	    else
2139 #endif
2140 		++new_cursor_col;
2141 	    vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
2142 	}
2143 	vcol = last_vcol;
2144 
2145 	/*
2146 	 * May need to insert spaces to be able to position the cursor on
2147 	 * the right screen column.
2148 	 */
2149 	if (vcol != (int)curwin->w_virtcol)
2150 	{
2151 	    curwin->w_cursor.col = (colnr_T)new_cursor_col;
2152 	    i = (int)curwin->w_virtcol - vcol;
2153 	    ptr = alloc((unsigned)(i + 1));
2154 	    if (ptr != NULL)
2155 	    {
2156 		new_cursor_col += i;
2157 		ptr[i] = NUL;
2158 		while (--i >= 0)
2159 		    ptr[i] = ' ';
2160 		ins_str(ptr);
2161 		vim_free(ptr);
2162 	    }
2163 	}
2164 
2165 	/*
2166 	 * When changing the indent while the cursor is in it, reset
2167 	 * Insstart_col to 0.
2168 	 */
2169 	insstart_less = MAXCOL;
2170     }
2171 
2172     curwin->w_p_list = save_p_list;
2173 
2174     if (new_cursor_col <= 0)
2175 	curwin->w_cursor.col = 0;
2176     else
2177 	curwin->w_cursor.col = (colnr_T)new_cursor_col;
2178     curwin->w_set_curswant = TRUE;
2179     changed_cline_bef_curs();
2180 
2181     /*
2182      * May have to adjust the start of the insert.
2183      */
2184     if (State & INSERT)
2185     {
2186 	if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
2187 	{
2188 	    if ((int)Insstart.col <= insstart_less)
2189 		Insstart.col = 0;
2190 	    else
2191 		Insstart.col -= insstart_less;
2192 	}
2193 	if ((int)ai_col <= insstart_less)
2194 	    ai_col = 0;
2195 	else
2196 	    ai_col -= insstart_less;
2197     }
2198 
2199     /*
2200      * For REPLACE mode, may have to fix the replace stack, if it's possible.
2201      * If the number of characters before the cursor decreased, need to pop a
2202      * few characters from the replace stack.
2203      * If the number of characters before the cursor increased, need to push a
2204      * few NULs onto the replace stack.
2205      */
2206     if (REPLACE_NORMAL(State) && start_col >= 0)
2207     {
2208 	while (start_col > (int)curwin->w_cursor.col)
2209 	{
2210 	    replace_join(0);	    /* remove a NUL from the replace stack */
2211 	    --start_col;
2212 	}
2213 	while (start_col < (int)curwin->w_cursor.col || replaced)
2214 	{
2215 	    replace_push(NUL);
2216 	    if (replaced)
2217 	    {
2218 		replace_push(replaced);
2219 		replaced = NUL;
2220 	    }
2221 	    ++start_col;
2222 	}
2223     }
2224 
2225     /*
2226      * For VREPLACE mode, we also have to fix the replace stack.  In this case
2227      * it is always possible because we backspace over the whole line and then
2228      * put it back again the way we wanted it.
2229      */
2230     if (State & VREPLACE_FLAG)
2231     {
2232 	/* If orig_line didn't allocate, just return.  At least we did the job,
2233 	 * even if you can't backspace. */
2234 	if (orig_line == NULL)
2235 	    return;
2236 
2237 	/* Save new line */
2238 	new_line = vim_strsave(ml_get_curline());
2239 	if (new_line == NULL)
2240 	    return;
2241 
2242 	/* We only put back the new line up to the cursor */
2243 	new_line[curwin->w_cursor.col] = NUL;
2244 
2245 	/* Put back original line */
2246 	ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
2247 	curwin->w_cursor.col = orig_col;
2248 
2249 	/* Backspace from cursor to start of line */
2250 	backspace_until_column(0);
2251 
2252 	/* Insert new stuff into line again */
2253 	ins_bytes(new_line);
2254 
2255 	vim_free(new_line);
2256     }
2257 }
2258 
2259 /*
2260  * Truncate the space at the end of a line.  This is to be used only in an
2261  * insert mode.  It handles fixing the replace stack for REPLACE and VREPLACE
2262  * modes.
2263  */
2264     void
2265 truncate_spaces(char_u *line)
2266 {
2267     int	    i;
2268 
2269     /* find start of trailing white space */
2270     for (i = (int)STRLEN(line) - 1; i >= 0 && VIM_ISWHITE(line[i]); i--)
2271     {
2272 	if (State & REPLACE_FLAG)
2273 	    replace_join(0);	    /* remove a NUL from the replace stack */
2274     }
2275     line[i + 1] = NUL;
2276 }
2277 
2278 /*
2279  * Backspace the cursor until the given column.  Handles REPLACE and VREPLACE
2280  * modes correctly.  May also be used when not in insert mode at all.
2281  * Will attempt not to go before "col" even when there is a composing
2282  * character.
2283  */
2284     void
2285 backspace_until_column(int col)
2286 {
2287     while ((int)curwin->w_cursor.col > col)
2288     {
2289 	curwin->w_cursor.col--;
2290 	if (State & REPLACE_FLAG)
2291 	    replace_do_bs(col);
2292 	else if (!del_char_after_col(col))
2293 	    break;
2294     }
2295 }
2296 
2297 /*
2298  * Like del_char(), but make sure not to go before column "limit_col".
2299  * Only matters when there are composing characters.
2300  * Return TRUE when something was deleted.
2301  */
2302    static int
2303 del_char_after_col(int limit_col UNUSED)
2304 {
2305 #ifdef FEAT_MBYTE
2306     if (enc_utf8 && limit_col >= 0)
2307     {
2308 	colnr_T ecol = curwin->w_cursor.col + 1;
2309 
2310 	/* Make sure the cursor is at the start of a character, but
2311 	 * skip forward again when going too far back because of a
2312 	 * composing character. */
2313 	mb_adjust_cursor();
2314 	while (curwin->w_cursor.col < (colnr_T)limit_col)
2315 	{
2316 	    int l = utf_ptr2len(ml_get_cursor());
2317 
2318 	    if (l == 0)  /* end of line */
2319 		break;
2320 	    curwin->w_cursor.col += l;
2321 	}
2322 	if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol)
2323 	    return FALSE;
2324 	del_bytes((long)((int)ecol - curwin->w_cursor.col), FALSE, TRUE);
2325     }
2326     else
2327 #endif
2328 	(void)del_char(FALSE);
2329     return TRUE;
2330 }
2331 
2332 #if defined(FEAT_INS_EXPAND) || defined(PROTO)
2333 /*
2334  * CTRL-X pressed in Insert mode.
2335  */
2336     static void
2337 ins_ctrl_x(void)
2338 {
2339     /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X
2340      * CTRL-V works like CTRL-N */
2341     if (ctrl_x_mode != CTRL_X_CMDLINE)
2342     {
2343 	/* if the next ^X<> won't ADD nothing, then reset
2344 	 * compl_cont_status */
2345 	if (compl_cont_status & CONT_N_ADDS)
2346 	    compl_cont_status |= CONT_INTRPT;
2347 	else
2348 	    compl_cont_status = 0;
2349 	/* We're not sure which CTRL-X mode it will be yet */
2350 	ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
2351 	edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
2352 	edit_submode_pre = NULL;
2353 	showmode();
2354     }
2355 }
2356 
2357 /*
2358  * Whether other than default completion has been selected.
2359  */
2360     int
2361 ctrl_x_mode_not_default(void)
2362 {
2363     return ctrl_x_mode != CTRL_X_NORMAL;
2364 }
2365 
2366 /*
2367  * Whether CTRL-X was typed without a following character.
2368  */
2369     int
2370 ctrl_x_mode_not_defined_yet(void)
2371 {
2372     return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
2373 }
2374 
2375 /*
2376  * Return TRUE if the 'dict' or 'tsr' option can be used.
2377  */
2378     static int
2379 has_compl_option(int dict_opt)
2380 {
2381     if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
2382 # ifdef FEAT_SPELL
2383 							&& !curwin->w_p_spell
2384 # endif
2385 							)
2386 		 : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL))
2387     {
2388 	ctrl_x_mode = CTRL_X_NORMAL;
2389 	edit_submode = NULL;
2390 	msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty")
2391 			  : (char_u *)_("'thesaurus' option is empty"),
2392 							      HL_ATTR(HLF_E));
2393 	if (emsg_silent == 0)
2394 	{
2395 	    vim_beep(BO_COMPL);
2396 	    setcursor();
2397 	    out_flush();
2398 #ifdef FEAT_EVAL
2399 	    if (!get_vim_var_nr(VV_TESTING))
2400 #endif
2401 		ui_delay(2000L, FALSE);
2402 	}
2403 	return FALSE;
2404     }
2405     return TRUE;
2406 }
2407 
2408 /*
2409  * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
2410  * This depends on the current mode.
2411  */
2412     int
2413 vim_is_ctrl_x_key(int c)
2414 {
2415     // Always allow ^R - let its results then be checked
2416     if (c == Ctrl_R)
2417 	return TRUE;
2418 
2419     /* Accept <PageUp> and <PageDown> if the popup menu is visible. */
2420     if (ins_compl_pum_key(c))
2421 	return TRUE;
2422 
2423     switch (ctrl_x_mode)
2424     {
2425 	case 0:		    /* Not in any CTRL-X mode */
2426 	    return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
2427 	case CTRL_X_NOT_DEFINED_YET:
2428 	    return (   c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
2429 		    || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
2430 		    || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
2431 		    || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
2432 		    || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
2433 		    || c == Ctrl_S || c == Ctrl_K || c == 's');
2434 	case CTRL_X_SCROLL:
2435 	    return (c == Ctrl_Y || c == Ctrl_E);
2436 	case CTRL_X_WHOLE_LINE:
2437 	    return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
2438 	case CTRL_X_FILES:
2439 	    return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
2440 	case CTRL_X_DICTIONARY:
2441 	    return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
2442 	case CTRL_X_THESAURUS:
2443 	    return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
2444 	case CTRL_X_TAGS:
2445 	    return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
2446 #ifdef FEAT_FIND_ID
2447 	case CTRL_X_PATH_PATTERNS:
2448 	    return (c == Ctrl_P || c == Ctrl_N);
2449 	case CTRL_X_PATH_DEFINES:
2450 	    return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
2451 #endif
2452 	case CTRL_X_CMDLINE:
2453 	    return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
2454 		    || c == Ctrl_X);
2455 #ifdef FEAT_COMPL_FUNC
2456 	case CTRL_X_FUNCTION:
2457 	    return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N);
2458 	case CTRL_X_OMNI:
2459 	    return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N);
2460 #endif
2461 	case CTRL_X_SPELL:
2462 	    return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N);
2463 	case CTRL_X_EVAL:
2464 	    return (c == Ctrl_P || c == Ctrl_N);
2465     }
2466     internal_error("vim_is_ctrl_x_key()");
2467     return FALSE;
2468 }
2469 
2470 /*
2471  * Return TRUE when character "c" is part of the item currently being
2472  * completed.  Used to decide whether to abandon complete mode when the menu
2473  * is visible.
2474  */
2475     static int
2476 ins_compl_accept_char(int c)
2477 {
2478     if (ctrl_x_mode & CTRL_X_WANT_IDENT)
2479 	/* When expanding an identifier only accept identifier chars. */
2480 	return vim_isIDc(c);
2481 
2482     switch (ctrl_x_mode)
2483     {
2484 	case CTRL_X_FILES:
2485 	    /* When expanding file name only accept file name chars. But not
2486 	     * path separators, so that "proto/<Tab>" expands files in
2487 	     * "proto", not "proto/" as a whole */
2488 	    return vim_isfilec(c) && !vim_ispathsep(c);
2489 
2490 	case CTRL_X_CMDLINE:
2491 	case CTRL_X_OMNI:
2492 	    /* Command line and Omni completion can work with just about any
2493 	     * printable character, but do stop at white space. */
2494 	    return vim_isprintc(c) && !VIM_ISWHITE(c);
2495 
2496 	case CTRL_X_WHOLE_LINE:
2497 	    /* For while line completion a space can be part of the line. */
2498 	    return vim_isprintc(c);
2499     }
2500     return vim_iswordc(c);
2501 }
2502 
2503 /*
2504  * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
2505  * case of the originally typed text is used, and the case of the completed
2506  * text is inferred, ie this tries to work out what case you probably wanted
2507  * the rest of the word to be in -- webb
2508  */
2509     int
2510 ins_compl_add_infercase(
2511     char_u	*str,
2512     int		len,
2513     int		icase,
2514     char_u	*fname,
2515     int		dir,
2516     int		flags)
2517 {
2518     char_u	*p;
2519     int		i, c;
2520     int		actual_len;		/* Take multi-byte characters */
2521     int		actual_compl_length;	/* into account. */
2522     int		min_len;
2523     int		*wca;			/* Wide character array. */
2524     int		has_lower = FALSE;
2525     int		was_letter = FALSE;
2526 
2527     if (p_ic && curbuf->b_p_inf && len > 0)
2528     {
2529 	/* Infer case of completed part. */
2530 
2531 	/* Find actual length of completion. */
2532 #ifdef FEAT_MBYTE
2533 	if (has_mbyte)
2534 	{
2535 	    p = str;
2536 	    actual_len = 0;
2537 	    while (*p != NUL)
2538 	    {
2539 		MB_PTR_ADV(p);
2540 		++actual_len;
2541 	    }
2542 	}
2543 	else
2544 #endif
2545 	    actual_len = len;
2546 
2547 	/* Find actual length of original text. */
2548 #ifdef FEAT_MBYTE
2549 	if (has_mbyte)
2550 	{
2551 	    p = compl_orig_text;
2552 	    actual_compl_length = 0;
2553 	    while (*p != NUL)
2554 	    {
2555 		MB_PTR_ADV(p);
2556 		++actual_compl_length;
2557 	    }
2558 	}
2559 	else
2560 #endif
2561 	    actual_compl_length = compl_length;
2562 
2563 	/* "actual_len" may be smaller than "actual_compl_length" when using
2564 	 * thesaurus, only use the minimum when comparing. */
2565 	min_len = actual_len < actual_compl_length
2566 					   ? actual_len : actual_compl_length;
2567 
2568 	/* Allocate wide character array for the completion and fill it. */
2569 	wca = (int *)alloc((unsigned)(actual_len * sizeof(int)));
2570 	if (wca != NULL)
2571 	{
2572 	    p = str;
2573 	    for (i = 0; i < actual_len; ++i)
2574 #ifdef FEAT_MBYTE
2575 		if (has_mbyte)
2576 		    wca[i] = mb_ptr2char_adv(&p);
2577 		else
2578 #endif
2579 		    wca[i] = *(p++);
2580 
2581 	    /* Rule 1: Were any chars converted to lower? */
2582 	    p = compl_orig_text;
2583 	    for (i = 0; i < min_len; ++i)
2584 	    {
2585 #ifdef FEAT_MBYTE
2586 		if (has_mbyte)
2587 		    c = mb_ptr2char_adv(&p);
2588 		else
2589 #endif
2590 		    c = *(p++);
2591 		if (MB_ISLOWER(c))
2592 		{
2593 		    has_lower = TRUE;
2594 		    if (MB_ISUPPER(wca[i]))
2595 		    {
2596 			/* Rule 1 is satisfied. */
2597 			for (i = actual_compl_length; i < actual_len; ++i)
2598 			    wca[i] = MB_TOLOWER(wca[i]);
2599 			break;
2600 		    }
2601 		}
2602 	    }
2603 
2604 	    /*
2605 	     * Rule 2: No lower case, 2nd consecutive letter converted to
2606 	     * upper case.
2607 	     */
2608 	    if (!has_lower)
2609 	    {
2610 		p = compl_orig_text;
2611 		for (i = 0; i < min_len; ++i)
2612 		{
2613 #ifdef FEAT_MBYTE
2614 		    if (has_mbyte)
2615 			c = mb_ptr2char_adv(&p);
2616 		    else
2617 #endif
2618 			c = *(p++);
2619 		    if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
2620 		    {
2621 			/* Rule 2 is satisfied. */
2622 			for (i = actual_compl_length; i < actual_len; ++i)
2623 			    wca[i] = MB_TOUPPER(wca[i]);
2624 			break;
2625 		    }
2626 		    was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
2627 		}
2628 	    }
2629 
2630 	    /* Copy the original case of the part we typed. */
2631 	    p = compl_orig_text;
2632 	    for (i = 0; i < min_len; ++i)
2633 	    {
2634 #ifdef FEAT_MBYTE
2635 		if (has_mbyte)
2636 		    c = mb_ptr2char_adv(&p);
2637 		else
2638 #endif
2639 		    c = *(p++);
2640 		if (MB_ISLOWER(c))
2641 		    wca[i] = MB_TOLOWER(wca[i]);
2642 		else if (MB_ISUPPER(c))
2643 		    wca[i] = MB_TOUPPER(wca[i]);
2644 	    }
2645 
2646 	    /*
2647 	     * Generate encoding specific output from wide character array.
2648 	     * Multi-byte characters can occupy up to five bytes more than
2649 	     * ASCII characters, and we also need one byte for NUL, so stay
2650 	     * six bytes away from the edge of IObuff.
2651 	     */
2652 	    p = IObuff;
2653 	    i = 0;
2654 	    while (i < actual_len && (p - IObuff + 6) < IOSIZE)
2655 #ifdef FEAT_MBYTE
2656 		if (has_mbyte)
2657 		    p += (*mb_char2bytes)(wca[i++], p);
2658 		else
2659 #endif
2660 		    *(p++) = wca[i++];
2661 	    *p = NUL;
2662 
2663 	    vim_free(wca);
2664 	}
2665 
2666 	return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
2667 								flags, FALSE);
2668     }
2669     return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
2670 }
2671 
2672 /*
2673  * Add a match to the list of matches.
2674  * If the given string is already in the list of completions, then return
2675  * NOTDONE, otherwise add it to the list and return OK.  If there is an error,
2676  * maybe because alloc() returns NULL, then FAIL is returned.
2677  */
2678     static int
2679 ins_compl_add(
2680     char_u	*str,
2681     int		len,
2682     int		icase,
2683     char_u	*fname,
2684     char_u	**cptext,   /* extra text for popup menu or NULL */
2685     int		cdir,
2686     int		flags,
2687     int		adup)	    /* accept duplicate match */
2688 {
2689     compl_T	*match;
2690     int		dir = (cdir == 0 ? compl_direction : cdir);
2691 
2692     ui_breakcheck();
2693     if (got_int)
2694 	return FAIL;
2695     if (len < 0)
2696 	len = (int)STRLEN(str);
2697 
2698     /*
2699      * If the same match is already present, don't add it.
2700      */
2701     if (compl_first_match != NULL && !adup)
2702     {
2703 	match = compl_first_match;
2704 	do
2705 	{
2706 	    if (    !(match->cp_flags & ORIGINAL_TEXT)
2707 		    && STRNCMP(match->cp_str, str, len) == 0
2708 		    && match->cp_str[len] == NUL)
2709 		return NOTDONE;
2710 	    match = match->cp_next;
2711 	} while (match != NULL && match != compl_first_match);
2712     }
2713 
2714     /* Remove any popup menu before changing the list of matches. */
2715     ins_compl_del_pum();
2716 
2717     /*
2718      * Allocate a new match structure.
2719      * Copy the values to the new match structure.
2720      */
2721     match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T));
2722     if (match == NULL)
2723 	return FAIL;
2724     match->cp_number = -1;
2725     if (flags & ORIGINAL_TEXT)
2726 	match->cp_number = 0;
2727     if ((match->cp_str = vim_strnsave(str, len)) == NULL)
2728     {
2729 	vim_free(match);
2730 	return FAIL;
2731     }
2732     match->cp_icase = icase;
2733 
2734     /* match-fname is:
2735      * - compl_curr_match->cp_fname if it is a string equal to fname.
2736      * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
2737      * - NULL otherwise.	--Acevedo */
2738     if (fname != NULL
2739 	    && compl_curr_match != NULL
2740 	    && compl_curr_match->cp_fname != NULL
2741 	    && STRCMP(fname, compl_curr_match->cp_fname) == 0)
2742 	match->cp_fname = compl_curr_match->cp_fname;
2743     else if (fname != NULL)
2744     {
2745 	match->cp_fname = vim_strsave(fname);
2746 	flags |= FREE_FNAME;
2747     }
2748     else
2749 	match->cp_fname = NULL;
2750     match->cp_flags = flags;
2751 
2752     if (cptext != NULL)
2753     {
2754 	int i;
2755 
2756 	for (i = 0; i < CPT_COUNT; ++i)
2757 	    if (cptext[i] != NULL && *cptext[i] != NUL)
2758 		match->cp_text[i] = vim_strsave(cptext[i]);
2759     }
2760 
2761     /*
2762      * Link the new match structure in the list of matches.
2763      */
2764     if (compl_first_match == NULL)
2765 	match->cp_next = match->cp_prev = NULL;
2766     else if (dir == FORWARD)
2767     {
2768 	match->cp_next = compl_curr_match->cp_next;
2769 	match->cp_prev = compl_curr_match;
2770     }
2771     else	/* BACKWARD */
2772     {
2773 	match->cp_next = compl_curr_match;
2774 	match->cp_prev = compl_curr_match->cp_prev;
2775     }
2776     if (match->cp_next)
2777 	match->cp_next->cp_prev = match;
2778     if (match->cp_prev)
2779 	match->cp_prev->cp_next = match;
2780     else	/* if there's nothing before, it is the first match */
2781 	compl_first_match = match;
2782     compl_curr_match = match;
2783 
2784     /*
2785      * Find the longest common string if still doing that.
2786      */
2787     if (compl_get_longest && (flags & ORIGINAL_TEXT) == 0)
2788 	ins_compl_longest_match(match);
2789 
2790     return OK;
2791 }
2792 
2793 /*
2794  * Return TRUE if "str[len]" matches with match->cp_str, considering
2795  * match->cp_icase.
2796  */
2797     static int
2798 ins_compl_equal(compl_T *match, char_u *str, int len)
2799 {
2800     if (match->cp_icase)
2801 	return STRNICMP(match->cp_str, str, (size_t)len) == 0;
2802     return STRNCMP(match->cp_str, str, (size_t)len) == 0;
2803 }
2804 
2805 /*
2806  * Reduce the longest common string for match "match".
2807  */
2808     static void
2809 ins_compl_longest_match(compl_T *match)
2810 {
2811     char_u	*p, *s;
2812     int		c1, c2;
2813     int		had_match;
2814 
2815     if (compl_leader == NULL)
2816     {
2817 	/* First match, use it as a whole. */
2818 	compl_leader = vim_strsave(match->cp_str);
2819 	if (compl_leader != NULL)
2820 	{
2821 	    had_match = (curwin->w_cursor.col > compl_col);
2822 	    ins_compl_delete();
2823 	    ins_bytes(compl_leader + ins_compl_len());
2824 	    ins_redraw(FALSE);
2825 
2826 	    /* When the match isn't there (to avoid matching itself) remove it
2827 	     * again after redrawing. */
2828 	    if (!had_match)
2829 		ins_compl_delete();
2830 	    compl_used_match = FALSE;
2831 	}
2832     }
2833     else
2834     {
2835 	/* Reduce the text if this match differs from compl_leader. */
2836 	p = compl_leader;
2837 	s = match->cp_str;
2838 	while (*p != NUL)
2839 	{
2840 #ifdef FEAT_MBYTE
2841 	    if (has_mbyte)
2842 	    {
2843 		c1 = mb_ptr2char(p);
2844 		c2 = mb_ptr2char(s);
2845 	    }
2846 	    else
2847 #endif
2848 	    {
2849 		c1 = *p;
2850 		c2 = *s;
2851 	    }
2852 	    if (match->cp_icase ? (MB_TOLOWER(c1) != MB_TOLOWER(c2))
2853 								 : (c1 != c2))
2854 		break;
2855 #ifdef FEAT_MBYTE
2856 	    if (has_mbyte)
2857 	    {
2858 		MB_PTR_ADV(p);
2859 		MB_PTR_ADV(s);
2860 	    }
2861 	    else
2862 #endif
2863 	    {
2864 		++p;
2865 		++s;
2866 	    }
2867 	}
2868 
2869 	if (*p != NUL)
2870 	{
2871 	    /* Leader was shortened, need to change the inserted text. */
2872 	    *p = NUL;
2873 	    had_match = (curwin->w_cursor.col > compl_col);
2874 	    ins_compl_delete();
2875 	    ins_bytes(compl_leader + ins_compl_len());
2876 	    ins_redraw(FALSE);
2877 
2878 	    /* When the match isn't there (to avoid matching itself) remove it
2879 	     * again after redrawing. */
2880 	    if (!had_match)
2881 		ins_compl_delete();
2882 	}
2883 
2884 	compl_used_match = FALSE;
2885     }
2886 }
2887 
2888 /*
2889  * Add an array of matches to the list of matches.
2890  * Frees matches[].
2891  */
2892     static void
2893 ins_compl_add_matches(
2894     int		num_matches,
2895     char_u	**matches,
2896     int		icase)
2897 {
2898     int		i;
2899     int		add_r = OK;
2900     int		dir = compl_direction;
2901 
2902     for (i = 0; i < num_matches && add_r != FAIL; i++)
2903 	if ((add_r = ins_compl_add(matches[i], -1, icase,
2904 					    NULL, NULL, dir, 0, FALSE)) == OK)
2905 	    /* if dir was BACKWARD then honor it just once */
2906 	    dir = FORWARD;
2907     FreeWild(num_matches, matches);
2908 }
2909 
2910 /* Make the completion list cyclic.
2911  * Return the number of matches (excluding the original).
2912  */
2913     static int
2914 ins_compl_make_cyclic(void)
2915 {
2916     compl_T *match;
2917     int	    count = 0;
2918 
2919     if (compl_first_match != NULL)
2920     {
2921 	/*
2922 	 * Find the end of the list.
2923 	 */
2924 	match = compl_first_match;
2925 	/* there's always an entry for the compl_orig_text, it doesn't count. */
2926 	while (match->cp_next != NULL && match->cp_next != compl_first_match)
2927 	{
2928 	    match = match->cp_next;
2929 	    ++count;
2930 	}
2931 	match->cp_next = compl_first_match;
2932 	compl_first_match->cp_prev = match;
2933     }
2934     return count;
2935 }
2936 
2937 /*
2938  * Set variables that store noselect and noinsert behavior from the
2939  * 'completeopt' value.
2940  */
2941     void
2942 completeopt_was_set(void)
2943 {
2944     compl_no_insert = FALSE;
2945     compl_no_select = FALSE;
2946     if (strstr((char *)p_cot, "noselect") != NULL)
2947 	compl_no_select = TRUE;
2948     if (strstr((char *)p_cot, "noinsert") != NULL)
2949 	compl_no_insert = TRUE;
2950 }
2951 
2952 /*
2953  * Start completion for the complete() function.
2954  * "startcol" is where the matched text starts (1 is first column).
2955  * "list" is the list of matches.
2956  */
2957     void
2958 set_completion(colnr_T startcol, list_T *list)
2959 {
2960     int save_w_wrow = curwin->w_wrow;
2961     int save_w_leftcol = curwin->w_leftcol;
2962 
2963     /* If already doing completions stop it. */
2964     if (ctrl_x_mode != CTRL_X_NORMAL)
2965 	ins_compl_prep(' ');
2966     ins_compl_clear();
2967     ins_compl_free();
2968 
2969     compl_direction = FORWARD;
2970     if (startcol > curwin->w_cursor.col)
2971 	startcol = curwin->w_cursor.col;
2972     compl_col = startcol;
2973     compl_length = (int)curwin->w_cursor.col - (int)startcol;
2974     /* compl_pattern doesn't need to be set */
2975     compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
2976     if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
2977 			-1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
2978 	return;
2979 
2980     ctrl_x_mode = CTRL_X_EVAL;
2981 
2982     ins_compl_add_list(list);
2983     compl_matches = ins_compl_make_cyclic();
2984     compl_started = TRUE;
2985     compl_used_match = TRUE;
2986     compl_cont_status = 0;
2987 
2988     compl_curr_match = compl_first_match;
2989     if (compl_no_insert || compl_no_select)
2990     {
2991 	ins_complete(K_DOWN, FALSE);
2992 	if (compl_no_select)
2993 	    /* Down/Up has no real effect. */
2994 	    ins_complete(K_UP, FALSE);
2995     }
2996     else
2997 	ins_complete(Ctrl_N, FALSE);
2998     compl_enter_selects = compl_no_insert;
2999 
3000     /* Lazily show the popup menu, unless we got interrupted. */
3001     if (!compl_interrupted)
3002 	show_pum(save_w_wrow, save_w_leftcol);
3003     out_flush();
3004 }
3005 
3006 
3007 /* "compl_match_array" points the currently displayed list of entries in the
3008  * popup menu.  It is NULL when there is no popup menu. */
3009 static pumitem_T *compl_match_array = NULL;
3010 static int compl_match_arraysize;
3011 
3012 /*
3013  * Update the screen and when there is any scrolling remove the popup menu.
3014  */
3015     static void
3016 ins_compl_upd_pum(void)
3017 {
3018     int		h;
3019 
3020     if (compl_match_array != NULL)
3021     {
3022 	h = curwin->w_cline_height;
3023 	// Update the screen later, before drawing the popup menu over it.
3024 	pum_call_update_screen();
3025 	if (h != curwin->w_cline_height)
3026 	    ins_compl_del_pum();
3027     }
3028 }
3029 
3030 /*
3031  * Remove any popup menu.
3032  */
3033     static void
3034 ins_compl_del_pum(void)
3035 {
3036     if (compl_match_array != NULL)
3037     {
3038 	pum_undisplay();
3039 	VIM_CLEAR(compl_match_array);
3040     }
3041 }
3042 
3043 /*
3044  * Return TRUE if the popup menu should be displayed.
3045  */
3046     static int
3047 pum_wanted(void)
3048 {
3049     /* 'completeopt' must contain "menu" or "menuone" */
3050     if (vim_strchr(p_cot, 'm') == NULL)
3051 	return FALSE;
3052 
3053     /* The display looks bad on a B&W display. */
3054     if (t_colors < 8
3055 #ifdef FEAT_GUI
3056 	    && !gui.in_use
3057 #endif
3058 	    )
3059 	return FALSE;
3060     return TRUE;
3061 }
3062 
3063 /*
3064  * Return TRUE if there are two or more matches to be shown in the popup menu.
3065  * One if 'completopt' contains "menuone".
3066  */
3067     static int
3068 pum_enough_matches(void)
3069 {
3070     compl_T     *compl;
3071     int		i;
3072 
3073     /* Don't display the popup menu if there are no matches or there is only
3074      * one (ignoring the original text). */
3075     compl = compl_first_match;
3076     i = 0;
3077     do
3078     {
3079 	if (compl == NULL
3080 		      || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2))
3081 	    break;
3082 	compl = compl->cp_next;
3083     } while (compl != compl_first_match);
3084 
3085     if (strstr((char *)p_cot, "menuone") != NULL)
3086 	return (i >= 1);
3087     return (i >= 2);
3088 }
3089 
3090 /*
3091  * Show the popup menu for the list of matches.
3092  * Also adjusts "compl_shown_match" to an entry that is actually displayed.
3093  */
3094     void
3095 ins_compl_show_pum(void)
3096 {
3097     compl_T     *compl;
3098     compl_T     *shown_compl = NULL;
3099     int		did_find_shown_match = FALSE;
3100     int		shown_match_ok = FALSE;
3101     int		i;
3102     int		cur = -1;
3103     colnr_T	col;
3104     int		lead_len = 0;
3105 
3106     if (!pum_wanted() || !pum_enough_matches())
3107 	return;
3108 
3109 #if defined(FEAT_EVAL)
3110     /* Dirty hard-coded hack: remove any matchparen highlighting. */
3111     do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif");
3112 #endif
3113 
3114     // Update the screen later, before drawing the popup menu over it.
3115     pum_call_update_screen();
3116 
3117     if (compl_match_array == NULL)
3118     {
3119 	/* Need to build the popup menu list. */
3120 	compl_match_arraysize = 0;
3121 	compl = compl_first_match;
3122 	if (compl_leader != NULL)
3123 	    lead_len = (int)STRLEN(compl_leader);
3124 	do
3125 	{
3126 	    if ((compl->cp_flags & ORIGINAL_TEXT) == 0
3127 		    && (compl_leader == NULL
3128 			|| ins_compl_equal(compl, compl_leader, lead_len)))
3129 		++compl_match_arraysize;
3130 	    compl = compl->cp_next;
3131 	} while (compl != NULL && compl != compl_first_match);
3132 	if (compl_match_arraysize == 0)
3133 	    return;
3134 	compl_match_array = (pumitem_T *)alloc_clear(
3135 				    (unsigned)(sizeof(pumitem_T)
3136 						    * compl_match_arraysize));
3137 	if (compl_match_array != NULL)
3138 	{
3139 	    /* If the current match is the original text don't find the first
3140 	     * match after it, don't highlight anything. */
3141 	    if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
3142 		shown_match_ok = TRUE;
3143 
3144 	    i = 0;
3145 	    compl = compl_first_match;
3146 	    do
3147 	    {
3148 		if ((compl->cp_flags & ORIGINAL_TEXT) == 0
3149 			&& (compl_leader == NULL
3150 			    || ins_compl_equal(compl, compl_leader, lead_len)))
3151 		{
3152 		    if (!shown_match_ok)
3153 		    {
3154 			if (compl == compl_shown_match || did_find_shown_match)
3155 			{
3156 			    /* This item is the shown match or this is the
3157 			     * first displayed item after the shown match. */
3158 			    compl_shown_match = compl;
3159 			    did_find_shown_match = TRUE;
3160 			    shown_match_ok = TRUE;
3161 			}
3162 			else
3163 			    /* Remember this displayed match for when the
3164 			     * shown match is just below it. */
3165 			    shown_compl = compl;
3166 			cur = i;
3167 		    }
3168 
3169 		    if (compl->cp_text[CPT_ABBR] != NULL)
3170 			compl_match_array[i].pum_text =
3171 						     compl->cp_text[CPT_ABBR];
3172 		    else
3173 			compl_match_array[i].pum_text = compl->cp_str;
3174 		    compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
3175 		    compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
3176 		    if (compl->cp_text[CPT_MENU] != NULL)
3177 			compl_match_array[i++].pum_extra =
3178 						     compl->cp_text[CPT_MENU];
3179 		    else
3180 			compl_match_array[i++].pum_extra = compl->cp_fname;
3181 		}
3182 
3183 		if (compl == compl_shown_match)
3184 		{
3185 		    did_find_shown_match = TRUE;
3186 
3187 		    /* When the original text is the shown match don't set
3188 		     * compl_shown_match. */
3189 		    if (compl->cp_flags & ORIGINAL_TEXT)
3190 			shown_match_ok = TRUE;
3191 
3192 		    if (!shown_match_ok && shown_compl != NULL)
3193 		    {
3194 			/* The shown match isn't displayed, set it to the
3195 			 * previously displayed match. */
3196 			compl_shown_match = shown_compl;
3197 			shown_match_ok = TRUE;
3198 		    }
3199 		}
3200 		compl = compl->cp_next;
3201 	    } while (compl != NULL && compl != compl_first_match);
3202 
3203 	    if (!shown_match_ok)    /* no displayed match at all */
3204 		cur = -1;
3205 	}
3206     }
3207     else
3208     {
3209 	/* popup menu already exists, only need to find the current item.*/
3210 	for (i = 0; i < compl_match_arraysize; ++i)
3211 	    if (compl_match_array[i].pum_text == compl_shown_match->cp_str
3212 		    || compl_match_array[i].pum_text
3213 				      == compl_shown_match->cp_text[CPT_ABBR])
3214 	    {
3215 		cur = i;
3216 		break;
3217 	    }
3218     }
3219 
3220     if (compl_match_array != NULL)
3221     {
3222 	/* In Replace mode when a $ is displayed at the end of the line only
3223 	 * part of the screen would be updated.  We do need to redraw here. */
3224 	dollar_vcol = -1;
3225 
3226 	/* Compute the screen column of the start of the completed text.
3227 	 * Use the cursor to get all wrapping and other settings right. */
3228 	col = curwin->w_cursor.col;
3229 	curwin->w_cursor.col = compl_col;
3230 	pum_display(compl_match_array, compl_match_arraysize, cur);
3231 	curwin->w_cursor.col = col;
3232     }
3233 }
3234 
3235 #define DICT_FIRST	(1)	/* use just first element in "dict" */
3236 #define DICT_EXACT	(2)	/* "dict" is the exact name of a file */
3237 
3238 /*
3239  * Add any identifiers that match the given pattern in the list of dictionary
3240  * files "dict_start" to the list of completions.
3241  */
3242     static void
3243 ins_compl_dictionaries(
3244     char_u	*dict_start,
3245     char_u	*pat,
3246     int		flags,		/* DICT_FIRST and/or DICT_EXACT */
3247     int		thesaurus)	/* Thesaurus completion */
3248 {
3249     char_u	*dict = dict_start;
3250     char_u	*ptr;
3251     char_u	*buf;
3252     regmatch_T	regmatch;
3253     char_u	**files;
3254     int		count;
3255     int		save_p_scs;
3256     int		dir = compl_direction;
3257 
3258     if (*dict == NUL)
3259     {
3260 #ifdef FEAT_SPELL
3261 	/* When 'dictionary' is empty and spell checking is enabled use
3262 	 * "spell". */
3263 	if (!thesaurus && curwin->w_p_spell)
3264 	    dict = (char_u *)"spell";
3265 	else
3266 #endif
3267 	    return;
3268     }
3269 
3270     buf = alloc(LSIZE);
3271     if (buf == NULL)
3272 	return;
3273     regmatch.regprog = NULL;	/* so that we can goto theend */
3274 
3275     /* If 'infercase' is set, don't use 'smartcase' here */
3276     save_p_scs = p_scs;
3277     if (curbuf->b_p_inf)
3278 	p_scs = FALSE;
3279 
3280     /* When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
3281      * to only match at the start of a line.  Otherwise just match the
3282      * pattern. Also need to double backslashes. */
3283     if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
3284     {
3285 	char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\");
3286 	size_t len;
3287 
3288 	if (pat_esc == NULL)
3289 	    goto theend;
3290 	len = STRLEN(pat_esc) + 10;
3291 	ptr = alloc((unsigned)len);
3292 	if (ptr == NULL)
3293 	{
3294 	    vim_free(pat_esc);
3295 	    goto theend;
3296 	}
3297 	vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc);
3298 	regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
3299 	vim_free(pat_esc);
3300 	vim_free(ptr);
3301     }
3302     else
3303     {
3304 	regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
3305 	if (regmatch.regprog == NULL)
3306 	    goto theend;
3307     }
3308 
3309     /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
3310     regmatch.rm_ic = ignorecase(pat);
3311     while (*dict != NUL && !got_int && !compl_interrupted)
3312     {
3313 	/* copy one dictionary file name into buf */
3314 	if (flags == DICT_EXACT)
3315 	{
3316 	    count = 1;
3317 	    files = &dict;
3318 	}
3319 	else
3320 	{
3321 	    /* Expand wildcards in the dictionary name, but do not allow
3322 	     * backticks (for security, the 'dict' option may have been set in
3323 	     * a modeline). */
3324 	    copy_option_part(&dict, buf, LSIZE, ",");
3325 # ifdef FEAT_SPELL
3326 	    if (!thesaurus && STRCMP(buf, "spell") == 0)
3327 		count = -1;
3328 	    else
3329 # endif
3330 		if (vim_strchr(buf, '`') != NULL
3331 		    || expand_wildcards(1, &buf, &count, &files,
3332 						     EW_FILE|EW_SILENT) != OK)
3333 		count = 0;
3334 	}
3335 
3336 # ifdef FEAT_SPELL
3337 	if (count == -1)
3338 	{
3339 	    /* Complete from active spelling.  Skip "\<" in the pattern, we
3340 	     * don't use it as a RE. */
3341 	    if (pat[0] == '\\' && pat[1] == '<')
3342 		ptr = pat + 2;
3343 	    else
3344 		ptr = pat;
3345 	    spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
3346 	}
3347 	else
3348 # endif
3349 	    if (count > 0)	/* avoid warning for using "files" uninit */
3350 	{
3351 	    ins_compl_files(count, files, thesaurus, flags,
3352 							&regmatch, buf, &dir);
3353 	    if (flags != DICT_EXACT)
3354 		FreeWild(count, files);
3355 	}
3356 	if (flags != 0)
3357 	    break;
3358     }
3359 
3360 theend:
3361     p_scs = save_p_scs;
3362     vim_regfree(regmatch.regprog);
3363     vim_free(buf);
3364 }
3365 
3366     static void
3367 ins_compl_files(
3368     int		count,
3369     char_u	**files,
3370     int		thesaurus,
3371     int		flags,
3372     regmatch_T	*regmatch,
3373     char_u	*buf,
3374     int		*dir)
3375 {
3376     char_u	*ptr;
3377     int		i;
3378     FILE	*fp;
3379     int		add_r;
3380 
3381     for (i = 0; i < count && !got_int && !compl_interrupted; i++)
3382     {
3383 	fp = mch_fopen((char *)files[i], "r");  /* open dictionary file */
3384 	if (flags != DICT_EXACT)
3385 	{
3386 	    vim_snprintf((char *)IObuff, IOSIZE,
3387 			      _("Scanning dictionary: %s"), (char *)files[i]);
3388 	    (void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R));
3389 	}
3390 
3391 	if (fp != NULL)
3392 	{
3393 	    /*
3394 	     * Read dictionary file line by line.
3395 	     * Check each line for a match.
3396 	     */
3397 	    while (!got_int && !compl_interrupted
3398 					    && !vim_fgets(buf, LSIZE, fp))
3399 	    {
3400 		ptr = buf;
3401 		while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf)))
3402 		{
3403 		    ptr = regmatch->startp[0];
3404 		    if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
3405 			ptr = find_line_end(ptr);
3406 		    else
3407 			ptr = find_word_end(ptr);
3408 		    add_r = ins_compl_add_infercase(regmatch->startp[0],
3409 					  (int)(ptr - regmatch->startp[0]),
3410 						     p_ic, files[i], *dir, 0);
3411 		    if (thesaurus)
3412 		    {
3413 			char_u *wstart;
3414 
3415 			/*
3416 			 * Add the other matches on the line
3417 			 */
3418 			ptr = buf;
3419 			while (!got_int)
3420 			{
3421 			    /* Find start of the next word.  Skip white
3422 			     * space and punctuation. */
3423 			    ptr = find_word_start(ptr);
3424 			    if (*ptr == NUL || *ptr == NL)
3425 				break;
3426 			    wstart = ptr;
3427 
3428 			    /* Find end of the word. */
3429 #ifdef FEAT_MBYTE
3430 			    if (has_mbyte)
3431 				/* Japanese words may have characters in
3432 				 * different classes, only separate words
3433 				 * with single-byte non-word characters. */
3434 				while (*ptr != NUL)
3435 				{
3436 				    int l = (*mb_ptr2len)(ptr);
3437 
3438 				    if (l < 2 && !vim_iswordc(*ptr))
3439 					break;
3440 				    ptr += l;
3441 				}
3442 			    else
3443 #endif
3444 				ptr = find_word_end(ptr);
3445 
3446 			    /* Add the word. Skip the regexp match. */
3447 			    if (wstart != regmatch->startp[0])
3448 				add_r = ins_compl_add_infercase(wstart,
3449 					(int)(ptr - wstart),
3450 					p_ic, files[i], *dir, 0);
3451 			}
3452 		    }
3453 		    if (add_r == OK)
3454 			/* if dir was BACKWARD then honor it just once */
3455 			*dir = FORWARD;
3456 		    else if (add_r == FAIL)
3457 			break;
3458 		    /* avoid expensive call to vim_regexec() when at end
3459 		     * of line */
3460 		    if (*ptr == '\n' || got_int)
3461 			break;
3462 		}
3463 		line_breakcheck();
3464 		ins_compl_check_keys(50, FALSE);
3465 	    }
3466 	    fclose(fp);
3467 	}
3468     }
3469 }
3470 
3471 /*
3472  * Find the start of the next word.
3473  * Returns a pointer to the first char of the word.  Also stops at a NUL.
3474  */
3475     char_u *
3476 find_word_start(char_u *ptr)
3477 {
3478 #ifdef FEAT_MBYTE
3479     if (has_mbyte)
3480 	while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
3481 	    ptr += (*mb_ptr2len)(ptr);
3482     else
3483 #endif
3484 	while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
3485 	    ++ptr;
3486     return ptr;
3487 }
3488 
3489 /*
3490  * Find the end of the word.  Assumes it starts inside a word.
3491  * Returns a pointer to just after the word.
3492  */
3493     char_u *
3494 find_word_end(char_u *ptr)
3495 {
3496 #ifdef FEAT_MBYTE
3497     int		start_class;
3498 
3499     if (has_mbyte)
3500     {
3501 	start_class = mb_get_class(ptr);
3502 	if (start_class > 1)
3503 	    while (*ptr != NUL)
3504 	    {
3505 		ptr += (*mb_ptr2len)(ptr);
3506 		if (mb_get_class(ptr) != start_class)
3507 		    break;
3508 	    }
3509     }
3510     else
3511 #endif
3512 	while (vim_iswordc(*ptr))
3513 	    ++ptr;
3514     return ptr;
3515 }
3516 
3517 /*
3518  * Find the end of the line, omitting CR and NL at the end.
3519  * Returns a pointer to just after the line.
3520  */
3521     static char_u *
3522 find_line_end(char_u *ptr)
3523 {
3524     char_u	*s;
3525 
3526     s = ptr + STRLEN(ptr);
3527     while (s > ptr && (s[-1] == CAR || s[-1] == NL))
3528 	--s;
3529     return s;
3530 }
3531 
3532 /*
3533  * Free the list of completions
3534  */
3535     static void
3536 ins_compl_free(void)
3537 {
3538     compl_T *match;
3539     int	    i;
3540 
3541     VIM_CLEAR(compl_pattern);
3542     VIM_CLEAR(compl_leader);
3543 
3544     if (compl_first_match == NULL)
3545 	return;
3546 
3547     ins_compl_del_pum();
3548     pum_clear();
3549 
3550     compl_curr_match = compl_first_match;
3551     do
3552     {
3553 	match = compl_curr_match;
3554 	compl_curr_match = compl_curr_match->cp_next;
3555 	vim_free(match->cp_str);
3556 	/* several entries may use the same fname, free it just once. */
3557 	if (match->cp_flags & FREE_FNAME)
3558 	    vim_free(match->cp_fname);
3559 	for (i = 0; i < CPT_COUNT; ++i)
3560 	    vim_free(match->cp_text[i]);
3561 	vim_free(match);
3562     } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
3563     compl_first_match = compl_curr_match = NULL;
3564     compl_shown_match = NULL;
3565     compl_old_match = NULL;
3566 }
3567 
3568     static void
3569 ins_compl_clear(void)
3570 {
3571     compl_cont_status = 0;
3572     compl_started = FALSE;
3573     compl_matches = 0;
3574     VIM_CLEAR(compl_pattern);
3575     VIM_CLEAR(compl_leader);
3576     edit_submode_extra = NULL;
3577     VIM_CLEAR(compl_orig_text);
3578     compl_enter_selects = FALSE;
3579     /* clear v:completed_item */
3580     set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
3581 }
3582 
3583 /*
3584  * Return TRUE when Insert completion is active.
3585  */
3586     int
3587 ins_compl_active(void)
3588 {
3589     return compl_started;
3590 }
3591 
3592 /*
3593  * Delete one character before the cursor and show the subset of the matches
3594  * that match the word that is now before the cursor.
3595  * Returns the character to be used, NUL if the work is done and another char
3596  * to be got from the user.
3597  */
3598     static int
3599 ins_compl_bs(void)
3600 {
3601     char_u	*line;
3602     char_u	*p;
3603 
3604     line = ml_get_curline();
3605     p = line + curwin->w_cursor.col;
3606     MB_PTR_BACK(line, p);
3607 
3608     /* Stop completion when the whole word was deleted.  For Omni completion
3609      * allow the word to be deleted, we won't match everything.
3610      * Respect the 'backspace' option. */
3611     if ((int)(p - line) - (int)compl_col < 0
3612 	    || ((int)(p - line) - (int)compl_col == 0
3613 		&& ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL
3614 	    || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
3615 							- compl_length < 0))
3616 	return K_BS;
3617 
3618     /* Deleted more than what was used to find matches or didn't finish
3619      * finding all matches: need to look for matches all over again. */
3620     if (curwin->w_cursor.col <= compl_col + compl_length
3621 						  || ins_compl_need_restart())
3622 	ins_compl_restart();
3623 
3624     vim_free(compl_leader);
3625     compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col);
3626     if (compl_leader != NULL)
3627     {
3628 	ins_compl_new_leader();
3629 	if (compl_shown_match != NULL)
3630 	    /* Make sure current match is not a hidden item. */
3631 	    compl_curr_match = compl_shown_match;
3632 	return NUL;
3633     }
3634     return K_BS;
3635 }
3636 
3637 /*
3638  * Return TRUE when we need to find matches again, ins_compl_restart() is to
3639  * be called.
3640  */
3641     static int
3642 ins_compl_need_restart(void)
3643 {
3644     /* Return TRUE if we didn't complete finding matches or when the
3645      * 'completefunc' returned "always" in the "refresh" dictionary item. */
3646     return compl_was_interrupted
3647 	|| ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
3648 						  && compl_opt_refresh_always);
3649 }
3650 
3651 /*
3652  * Called after changing "compl_leader".
3653  * Show the popup menu with a different set of matches.
3654  * May also search for matches again if the previous search was interrupted.
3655  */
3656     static void
3657 ins_compl_new_leader(void)
3658 {
3659     ins_compl_del_pum();
3660     ins_compl_delete();
3661     ins_bytes(compl_leader + ins_compl_len());
3662     compl_used_match = FALSE;
3663 
3664     if (compl_started)
3665 	ins_compl_set_original_text(compl_leader);
3666     else
3667     {
3668 #ifdef FEAT_SPELL
3669 	spell_bad_len = 0;	/* need to redetect bad word */
3670 #endif
3671 	/*
3672 	 * Matches were cleared, need to search for them now.  Befor drawing
3673 	 * the popup menu display the changed text before the cursor.  Set
3674 	 * "compl_restarting" to avoid that the first match is inserted.
3675 	 */
3676 	pum_call_update_screen();
3677 #ifdef FEAT_GUI
3678 	if (gui.in_use)
3679 	{
3680 	    /* Show the cursor after the match, not after the redrawn text. */
3681 	    setcursor();
3682 	    out_flush_cursor(FALSE, FALSE);
3683 	}
3684 #endif
3685 	compl_restarting = TRUE;
3686 	if (ins_complete(Ctrl_N, TRUE) == FAIL)
3687 	    compl_cont_status = 0;
3688 	compl_restarting = FALSE;
3689     }
3690 
3691     compl_enter_selects = !compl_used_match;
3692 
3693     /* Show the popup menu with a different set of matches. */
3694     ins_compl_show_pum();
3695 
3696     /* Don't let Enter select the original text when there is no popup menu. */
3697     if (compl_match_array == NULL)
3698 	compl_enter_selects = FALSE;
3699 }
3700 
3701 /*
3702  * Return the length of the completion, from the completion start column to
3703  * the cursor column.  Making sure it never goes below zero.
3704  */
3705     static int
3706 ins_compl_len(void)
3707 {
3708     int off = (int)curwin->w_cursor.col - (int)compl_col;
3709 
3710     if (off < 0)
3711 	return 0;
3712     return off;
3713 }
3714 
3715 /*
3716  * Append one character to the match leader.  May reduce the number of
3717  * matches.
3718  */
3719     static void
3720 ins_compl_addleader(int c)
3721 {
3722 #ifdef FEAT_MBYTE
3723     int		cc;
3724 #endif
3725 
3726     if (stop_arrow() == FAIL)
3727 	return;
3728 #ifdef FEAT_MBYTE
3729     if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
3730     {
3731 	char_u	buf[MB_MAXBYTES + 1];
3732 
3733 	(*mb_char2bytes)(c, buf);
3734 	buf[cc] = NUL;
3735 	ins_char_bytes(buf, cc);
3736 	if (compl_opt_refresh_always)
3737 	    AppendToRedobuff(buf);
3738     }
3739     else
3740 #endif
3741     {
3742 	ins_char(c);
3743 	if (compl_opt_refresh_always)
3744 	    AppendCharToRedobuff(c);
3745     }
3746 
3747     /* If we didn't complete finding matches we must search again. */
3748     if (ins_compl_need_restart())
3749 	ins_compl_restart();
3750 
3751     /* When 'always' is set, don't reset compl_leader. While completing,
3752      * cursor doesn't point original position, changing compl_leader would
3753      * break redo. */
3754     if (!compl_opt_refresh_always)
3755     {
3756 	vim_free(compl_leader);
3757 	compl_leader = vim_strnsave(ml_get_curline() + compl_col,
3758 				     (int)(curwin->w_cursor.col - compl_col));
3759 	if (compl_leader != NULL)
3760 	    ins_compl_new_leader();
3761     }
3762 }
3763 
3764 /*
3765  * Setup for finding completions again without leaving CTRL-X mode.  Used when
3766  * BS or a key was typed while still searching for matches.
3767  */
3768     static void
3769 ins_compl_restart(void)
3770 {
3771     ins_compl_free();
3772     compl_started = FALSE;
3773     compl_matches = 0;
3774     compl_cont_status = 0;
3775     compl_cont_mode = 0;
3776 }
3777 
3778 /*
3779  * Set the first match, the original text.
3780  */
3781     static void
3782 ins_compl_set_original_text(char_u *str)
3783 {
3784     char_u	*p;
3785 
3786     /* Replace the original text entry.
3787      * The ORIGINAL_TEXT flag is either at the first item or might possibly be
3788      * at the last item for backward completion */
3789     if (compl_first_match->cp_flags & ORIGINAL_TEXT)	/* safety check */
3790     {
3791 	p = vim_strsave(str);
3792 	if (p != NULL)
3793 	{
3794 	    vim_free(compl_first_match->cp_str);
3795 	    compl_first_match->cp_str = p;
3796 	}
3797     }
3798     else if (compl_first_match->cp_prev != NULL
3799 	    && (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT))
3800     {
3801        p = vim_strsave(str);
3802        if (p != NULL)
3803        {
3804            vim_free(compl_first_match->cp_prev->cp_str);
3805            compl_first_match->cp_prev->cp_str = p;
3806        }
3807     }
3808 }
3809 
3810 /*
3811  * Append one character to the match leader.  May reduce the number of
3812  * matches.
3813  */
3814     static void
3815 ins_compl_addfrommatch(void)
3816 {
3817     char_u	*p;
3818     int		len = (int)curwin->w_cursor.col - (int)compl_col;
3819     int		c;
3820     compl_T	*cp;
3821 
3822     p = compl_shown_match->cp_str;
3823     if ((int)STRLEN(p) <= len)   /* the match is too short */
3824     {
3825 	/* When still at the original match use the first entry that matches
3826 	 * the leader. */
3827 	if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
3828 	{
3829 	    p = NULL;
3830 	    for (cp = compl_shown_match->cp_next; cp != NULL
3831 				 && cp != compl_first_match; cp = cp->cp_next)
3832 	    {
3833 		if (compl_leader == NULL
3834 			|| ins_compl_equal(cp, compl_leader,
3835 						   (int)STRLEN(compl_leader)))
3836 		{
3837 		    p = cp->cp_str;
3838 		    break;
3839 		}
3840 	    }
3841 	    if (p == NULL || (int)STRLEN(p) <= len)
3842 		return;
3843 	}
3844 	else
3845 	    return;
3846     }
3847     p += len;
3848     c = PTR2CHAR(p);
3849     ins_compl_addleader(c);
3850 }
3851 
3852 /*
3853  * Prepare for Insert mode completion, or stop it.
3854  * Called just after typing a character in Insert mode.
3855  * Returns TRUE when the character is not to be inserted;
3856  */
3857     static int
3858 ins_compl_prep(int c)
3859 {
3860     char_u	*ptr;
3861     int		want_cindent;
3862     int		retval = FALSE;
3863 
3864     /* Forget any previous 'special' messages if this is actually
3865      * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
3866      */
3867     if (c != Ctrl_R && vim_is_ctrl_x_key(c))
3868 	edit_submode_extra = NULL;
3869 
3870     /* Ignore end of Select mode mapping and mouse scroll buttons. */
3871     if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
3872 	    || c == K_MOUSELEFT || c == K_MOUSERIGHT)
3873 	return retval;
3874 
3875     /* Set "compl_get_longest" when finding the first matches. */
3876     if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
3877 			   || (ctrl_x_mode == CTRL_X_NORMAL && !compl_started))
3878     {
3879 	compl_get_longest = (strstr((char *)p_cot, "longest") != NULL);
3880 	compl_used_match = TRUE;
3881 
3882     }
3883 
3884     if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
3885     {
3886 	/*
3887 	 * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
3888 	 * it will be yet.  Now we decide.
3889 	 */
3890 	switch (c)
3891 	{
3892 	    case Ctrl_E:
3893 	    case Ctrl_Y:
3894 		ctrl_x_mode = CTRL_X_SCROLL;
3895 		if (!(State & REPLACE_FLAG))
3896 		    edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
3897 		else
3898 		    edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
3899 		edit_submode_pre = NULL;
3900 		showmode();
3901 		break;
3902 	    case Ctrl_L:
3903 		ctrl_x_mode = CTRL_X_WHOLE_LINE;
3904 		break;
3905 	    case Ctrl_F:
3906 		ctrl_x_mode = CTRL_X_FILES;
3907 		break;
3908 	    case Ctrl_K:
3909 		ctrl_x_mode = CTRL_X_DICTIONARY;
3910 		break;
3911 	    case Ctrl_R:
3912 		/* Simply allow ^R to happen without affecting ^X mode */
3913 		break;
3914 	    case Ctrl_T:
3915 		ctrl_x_mode = CTRL_X_THESAURUS;
3916 		break;
3917 #ifdef FEAT_COMPL_FUNC
3918 	    case Ctrl_U:
3919 		ctrl_x_mode = CTRL_X_FUNCTION;
3920 		break;
3921 	    case Ctrl_O:
3922 		ctrl_x_mode = CTRL_X_OMNI;
3923 		break;
3924 #endif
3925 	    case 's':
3926 	    case Ctrl_S:
3927 		ctrl_x_mode = CTRL_X_SPELL;
3928 #ifdef FEAT_SPELL
3929 		++emsg_off;	/* Avoid getting the E756 error twice. */
3930 		spell_back_to_badword();
3931 		--emsg_off;
3932 #endif
3933 		break;
3934 	    case Ctrl_RSB:
3935 		ctrl_x_mode = CTRL_X_TAGS;
3936 		break;
3937 #ifdef FEAT_FIND_ID
3938 	    case Ctrl_I:
3939 	    case K_S_TAB:
3940 		ctrl_x_mode = CTRL_X_PATH_PATTERNS;
3941 		break;
3942 	    case Ctrl_D:
3943 		ctrl_x_mode = CTRL_X_PATH_DEFINES;
3944 		break;
3945 #endif
3946 	    case Ctrl_V:
3947 	    case Ctrl_Q:
3948 		ctrl_x_mode = CTRL_X_CMDLINE;
3949 		break;
3950 	    case Ctrl_P:
3951 	    case Ctrl_N:
3952 		/* ^X^P means LOCAL expansion if nothing interrupted (eg we
3953 		 * just started ^X mode, or there were enough ^X's to cancel
3954 		 * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
3955 		 * do normal expansion when interrupting a different mode (say
3956 		 * ^X^F^X^P or ^P^X^X^P, see below)
3957 		 * nothing changes if interrupting mode 0, (eg, the flag
3958 		 * doesn't change when going to ADDING mode  -- Acevedo */
3959 		if (!(compl_cont_status & CONT_INTRPT))
3960 		    compl_cont_status |= CONT_LOCAL;
3961 		else if (compl_cont_mode != 0)
3962 		    compl_cont_status &= ~CONT_LOCAL;
3963 		/* FALLTHROUGH */
3964 	    default:
3965 		/* If we have typed at least 2 ^X's... for modes != 0, we set
3966 		 * compl_cont_status = 0 (eg, as if we had just started ^X
3967 		 * mode).
3968 		 * For mode 0, we set "compl_cont_mode" to an impossible
3969 		 * value, in both cases ^X^X can be used to restart the same
3970 		 * mode (avoiding ADDING mode).
3971 		 * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
3972 		 * 'complete' and local ^P expansions respectively.
3973 		 * In mode 0 an extra ^X is needed since ^X^P goes to ADDING
3974 		 * mode  -- Acevedo */
3975 		if (c == Ctrl_X)
3976 		{
3977 		    if (compl_cont_mode != 0)
3978 			compl_cont_status = 0;
3979 		    else
3980 			compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
3981 		}
3982 		ctrl_x_mode = CTRL_X_NORMAL;
3983 		edit_submode = NULL;
3984 		showmode();
3985 		break;
3986 	}
3987     }
3988     else if (ctrl_x_mode != CTRL_X_NORMAL)
3989     {
3990 	/* We're already in CTRL-X mode, do we stay in it? */
3991 	if (!vim_is_ctrl_x_key(c))
3992 	{
3993 	    if (ctrl_x_mode == CTRL_X_SCROLL)
3994 		ctrl_x_mode = CTRL_X_NORMAL;
3995 	    else
3996 		ctrl_x_mode = CTRL_X_FINISHED;
3997 	    edit_submode = NULL;
3998 	}
3999 	showmode();
4000     }
4001 
4002     if (compl_started || ctrl_x_mode == CTRL_X_FINISHED)
4003     {
4004 	/* Show error message from attempted keyword completion (probably
4005 	 * 'Pattern not found') until another key is hit, then go back to
4006 	 * showing what mode we are in. */
4007 	showmode();
4008 	if ((ctrl_x_mode == CTRL_X_NORMAL && c != Ctrl_N && c != Ctrl_P
4009 				       && c != Ctrl_R && !ins_compl_pum_key(c))
4010 		|| ctrl_x_mode == CTRL_X_FINISHED)
4011 	{
4012 	    /* Get here when we have finished typing a sequence of ^N and
4013 	     * ^P or other completion characters in CTRL-X mode.  Free up
4014 	     * memory that was used, and make sure we can redo the insert. */
4015 	    if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
4016 	    {
4017 		/*
4018 		 * If any of the original typed text has been changed, eg when
4019 		 * ignorecase is set, we must add back-spaces to the redo
4020 		 * buffer.  We add as few as necessary to delete just the part
4021 		 * of the original text that has changed.
4022 		 * When using the longest match, edited the match or used
4023 		 * CTRL-E then don't use the current match.
4024 		 */
4025 		if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
4026 		    ptr = compl_curr_match->cp_str;
4027 		else
4028 		    ptr = NULL;
4029 		ins_compl_fixRedoBufForLeader(ptr);
4030 	    }
4031 
4032 #ifdef FEAT_CINDENT
4033 	    want_cindent = (can_cindent && cindent_on());
4034 #endif
4035 	    /*
4036 	     * When completing whole lines: fix indent for 'cindent'.
4037 	     * Otherwise, break line if it's too long.
4038 	     */
4039 	    if (compl_cont_mode == CTRL_X_WHOLE_LINE)
4040 	    {
4041 #ifdef FEAT_CINDENT
4042 		/* re-indent the current line */
4043 		if (want_cindent)
4044 		{
4045 		    do_c_expr_indent();
4046 		    want_cindent = FALSE;	/* don't do it again */
4047 		}
4048 #endif
4049 	    }
4050 	    else
4051 	    {
4052 		int prev_col = curwin->w_cursor.col;
4053 
4054 		/* put the cursor on the last char, for 'tw' formatting */
4055 		if (prev_col > 0)
4056 		    dec_cursor();
4057 		/* only format when something was inserted */
4058 		if (!arrow_used && !ins_need_undo && c != Ctrl_E)
4059 		    insertchar(NUL, 0, -1);
4060 		if (prev_col > 0
4061 			     && ml_get_curline()[curwin->w_cursor.col] != NUL)
4062 		    inc_cursor();
4063 	    }
4064 
4065 	    /* If the popup menu is displayed pressing CTRL-Y means accepting
4066 	     * the selection without inserting anything.  When
4067 	     * compl_enter_selects is set the Enter key does the same. */
4068 	    if ((c == Ctrl_Y || (compl_enter_selects
4069 				   && (c == CAR || c == K_KENTER || c == NL)))
4070 		    && pum_visible())
4071 		retval = TRUE;
4072 
4073 	    /* CTRL-E means completion is Ended, go back to the typed text.
4074 	     * but only do this, if the Popup is still visible */
4075 	    if (c == Ctrl_E)
4076 	    {
4077 		ins_compl_delete();
4078 		if (compl_leader != NULL)
4079 		    ins_bytes(compl_leader + ins_compl_len());
4080 		else if (compl_first_match != NULL)
4081 		    ins_bytes(compl_orig_text + ins_compl_len());
4082 		retval = TRUE;
4083 	    }
4084 
4085 	    auto_format(FALSE, TRUE);
4086 
4087 	    ins_compl_free();
4088 	    compl_started = FALSE;
4089 	    compl_matches = 0;
4090 	    if (!shortmess(SHM_COMPLETIONMENU))
4091 		msg_clr_cmdline();	/* necessary for "noshowmode" */
4092 	    ctrl_x_mode = CTRL_X_NORMAL;
4093 	    compl_enter_selects = FALSE;
4094 	    if (edit_submode != NULL)
4095 	    {
4096 		edit_submode = NULL;
4097 		showmode();
4098 	    }
4099 
4100 #ifdef FEAT_CMDWIN
4101 	    if (c == Ctrl_C && cmdwin_type != 0)
4102 		/* Avoid the popup menu remains displayed when leaving the
4103 		 * command line window. */
4104 		update_screen(0);
4105 #endif
4106 #ifdef FEAT_CINDENT
4107 	    /*
4108 	     * Indent now if a key was typed that is in 'cinkeys'.
4109 	     */
4110 	    if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
4111 		do_c_expr_indent();
4112 #endif
4113 	    /* Trigger the CompleteDone event to give scripts a chance to act
4114 	     * upon the completion. */
4115 	    ins_apply_autocmds(EVENT_COMPLETEDONE);
4116 	}
4117     }
4118     else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
4119 	/* Trigger the CompleteDone event to give scripts a chance to act
4120 	 * upon the (possibly failed) completion. */
4121 	ins_apply_autocmds(EVENT_COMPLETEDONE);
4122 
4123     /* reset continue_* if we left expansion-mode, if we stay they'll be
4124      * (re)set properly in ins_complete() */
4125     if (!vim_is_ctrl_x_key(c))
4126     {
4127 	compl_cont_status = 0;
4128 	compl_cont_mode = 0;
4129     }
4130 
4131     return retval;
4132 }
4133 
4134 /*
4135  * Fix the redo buffer for the completion leader replacing some of the typed
4136  * text.  This inserts backspaces and appends the changed text.
4137  * "ptr" is the known leader text or NUL.
4138  */
4139     static void
4140 ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
4141 {
4142     int	    len;
4143     char_u  *p;
4144     char_u  *ptr = ptr_arg;
4145 
4146     if (ptr == NULL)
4147     {
4148 	if (compl_leader != NULL)
4149 	    ptr = compl_leader;
4150 	else
4151 	    return;  /* nothing to do */
4152     }
4153     if (compl_orig_text != NULL)
4154     {
4155 	p = compl_orig_text;
4156 	for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len)
4157 	    ;
4158 #ifdef FEAT_MBYTE
4159 	if (len > 0)
4160 	    len -= (*mb_head_off)(p, p + len);
4161 #endif
4162 	for (p += len; *p != NUL; MB_PTR_ADV(p))
4163 	    AppendCharToRedobuff(K_BS);
4164     }
4165     else
4166 	len = 0;
4167     if (ptr != NULL)
4168 	AppendToRedobuffLit(ptr + len, -1);
4169 }
4170 
4171 /*
4172  * Loops through the list of windows, loaded-buffers or non-loaded-buffers
4173  * (depending on flag) starting from buf and looking for a non-scanned
4174  * buffer (other than curbuf).	curbuf is special, if it is called with
4175  * buf=curbuf then it has to be the first call for a given flag/expansion.
4176  *
4177  * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
4178  */
4179     static buf_T *
4180 ins_compl_next_buf(buf_T *buf, int flag)
4181 {
4182     static win_T *wp;
4183 
4184     if (flag == 'w')		/* just windows */
4185     {
4186 	if (buf == curbuf)	/* first call for this flag/expansion */
4187 	    wp = curwin;
4188 	while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
4189 		&& wp->w_buffer->b_scanned)
4190 	    ;
4191 	buf = wp->w_buffer;
4192     }
4193     else
4194 	/* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
4195 	 * (unlisted buffers)
4196 	 * When completing whole lines skip unloaded buffers. */
4197 	while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf
4198 		&& ((flag == 'U'
4199 			? buf->b_p_bl
4200 			: (!buf->b_p_bl
4201 			    || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
4202 		    || buf->b_scanned))
4203 	    ;
4204     return buf;
4205 }
4206 
4207 #ifdef FEAT_COMPL_FUNC
4208 /*
4209  * Execute user defined complete function 'completefunc' or 'omnifunc', and
4210  * get matches in "matches".
4211  */
4212     static void
4213 expand_by_function(
4214     int		type,	    /* CTRL_X_OMNI or CTRL_X_FUNCTION */
4215     char_u	*base)
4216 {
4217     list_T      *matchlist = NULL;
4218     dict_T	*matchdict = NULL;
4219     typval_T	args[3];
4220     char_u	*funcname;
4221     pos_T	pos;
4222     win_T	*curwin_save;
4223     buf_T	*curbuf_save;
4224     typval_T	rettv;
4225     int		save_State = State;
4226 
4227     funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
4228     if (*funcname == NUL)
4229 	return;
4230 
4231     /* Call 'completefunc' to obtain the list of matches. */
4232     args[0].v_type = VAR_NUMBER;
4233     args[0].vval.v_number = 0;
4234     args[1].v_type = VAR_STRING;
4235     args[1].vval.v_string = base != NULL ? base : (char_u *)"";
4236     args[2].v_type = VAR_UNKNOWN;
4237 
4238     pos = curwin->w_cursor;
4239     curwin_save = curwin;
4240     curbuf_save = curbuf;
4241 
4242     /* Call a function, which returns a list or dict. */
4243     if (call_vim_function(funcname, 2, args, &rettv) == OK)
4244     {
4245 	switch (rettv.v_type)
4246 	{
4247 	    case VAR_LIST:
4248 		matchlist = rettv.vval.v_list;
4249 		break;
4250 	    case VAR_DICT:
4251 		matchdict = rettv.vval.v_dict;
4252 		break;
4253 	    case VAR_SPECIAL:
4254 		if (rettv.vval.v_number == VVAL_NONE)
4255 		    compl_opt_suppress_empty = TRUE;
4256 		// FALLTHROUGH
4257 	    default:
4258 		// TODO: Give error message?
4259 		clear_tv(&rettv);
4260 		break;
4261 	}
4262     }
4263 
4264     if (curwin_save != curwin || curbuf_save != curbuf)
4265     {
4266 	emsg(_(e_complwin));
4267 	goto theend;
4268     }
4269     curwin->w_cursor = pos;	/* restore the cursor position */
4270     validate_cursor();
4271     if (!EQUAL_POS(curwin->w_cursor, pos))
4272     {
4273 	emsg(_(e_compldel));
4274 	goto theend;
4275     }
4276 
4277     if (matchlist != NULL)
4278 	ins_compl_add_list(matchlist);
4279     else if (matchdict != NULL)
4280 	ins_compl_add_dict(matchdict);
4281 
4282 theend:
4283     // Restore State, it might have been changed.
4284     State = save_State;
4285 
4286     if (matchdict != NULL)
4287 	dict_unref(matchdict);
4288     if (matchlist != NULL)
4289 	list_unref(matchlist);
4290 }
4291 #endif /* FEAT_COMPL_FUNC */
4292 
4293 #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO)
4294 /*
4295  * Add completions from a list.
4296  */
4297     static void
4298 ins_compl_add_list(list_T *list)
4299 {
4300     listitem_T	*li;
4301     int		dir = compl_direction;
4302 
4303     /* Go through the List with matches and add each of them. */
4304     for (li = list->lv_first; li != NULL; li = li->li_next)
4305     {
4306 	if (ins_compl_add_tv(&li->li_tv, dir) == OK)
4307 	    /* if dir was BACKWARD then honor it just once */
4308 	    dir = FORWARD;
4309 	else if (did_emsg)
4310 	    break;
4311     }
4312 }
4313 
4314 /*
4315  * Add completions from a dict.
4316  */
4317     static void
4318 ins_compl_add_dict(dict_T *dict)
4319 {
4320     dictitem_T	*di_refresh;
4321     dictitem_T	*di_words;
4322 
4323     /* Check for optional "refresh" item. */
4324     compl_opt_refresh_always = FALSE;
4325     di_refresh = dict_find(dict, (char_u *)"refresh", 7);
4326     if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING)
4327     {
4328 	char_u	*v = di_refresh->di_tv.vval.v_string;
4329 
4330 	if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
4331 	    compl_opt_refresh_always = TRUE;
4332     }
4333 
4334     /* Add completions from a "words" list. */
4335     di_words = dict_find(dict, (char_u *)"words", 5);
4336     if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
4337 	ins_compl_add_list(di_words->di_tv.vval.v_list);
4338 }
4339 
4340 /*
4341  * Add a match to the list of matches from a typeval_T.
4342  * If the given string is already in the list of completions, then return
4343  * NOTDONE, otherwise add it to the list and return OK.  If there is an error,
4344  * maybe because alloc() returns NULL, then FAIL is returned.
4345  */
4346     int
4347 ins_compl_add_tv(typval_T *tv, int dir)
4348 {
4349     char_u	*word;
4350     int		icase = FALSE;
4351     int		adup = FALSE;
4352     int		aempty = FALSE;
4353     char_u	*(cptext[CPT_COUNT]);
4354 
4355     if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
4356     {
4357 	word = dict_get_string(tv->vval.v_dict, (char_u *)"word", FALSE);
4358 	cptext[CPT_ABBR] = dict_get_string(tv->vval.v_dict,
4359 						     (char_u *)"abbr", FALSE);
4360 	cptext[CPT_MENU] = dict_get_string(tv->vval.v_dict,
4361 						     (char_u *)"menu", FALSE);
4362 	cptext[CPT_KIND] = dict_get_string(tv->vval.v_dict,
4363 						     (char_u *)"kind", FALSE);
4364 	cptext[CPT_INFO] = dict_get_string(tv->vval.v_dict,
4365 						     (char_u *)"info", FALSE);
4366 	cptext[CPT_USER_DATA] = dict_get_string(tv->vval.v_dict,
4367 						 (char_u *)"user_data", FALSE);
4368 	if (dict_get_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL)
4369 	    icase = dict_get_number(tv->vval.v_dict, (char_u *)"icase");
4370 	if (dict_get_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
4371 	    adup = dict_get_number(tv->vval.v_dict, (char_u *)"dup");
4372 	if (dict_get_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL)
4373 	    aempty = dict_get_number(tv->vval.v_dict, (char_u *)"empty");
4374     }
4375     else
4376     {
4377 	word = tv_get_string_chk(tv);
4378 	vim_memset(cptext, 0, sizeof(cptext));
4379     }
4380     if (word == NULL || (!aempty && *word == NUL))
4381 	return FAIL;
4382     return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
4383 }
4384 #endif
4385 
4386 /*
4387  * Get the next expansion(s), using "compl_pattern".
4388  * The search starts at position "ini" in curbuf and in the direction
4389  * compl_direction.
4390  * When "compl_started" is FALSE start at that position, otherwise continue
4391  * where we stopped searching before.
4392  * This may return before finding all the matches.
4393  * Return the total number of matches or -1 if still unknown -- Acevedo
4394  */
4395     static int
4396 ins_compl_get_exp(pos_T *ini)
4397 {
4398     static pos_T	first_match_pos;
4399     static pos_T	last_match_pos;
4400     static char_u	*e_cpt = (char_u *)"";	/* curr. entry in 'complete' */
4401     static int		found_all = FALSE;	/* Found all matches of a
4402 						   certain type. */
4403     static buf_T	*ins_buf = NULL;	/* buffer being scanned */
4404 
4405     pos_T	*pos;
4406     char_u	**matches;
4407     int		save_p_scs;
4408     int		save_p_ws;
4409     int		save_p_ic;
4410     int		i;
4411     int		num_matches;
4412     int		len;
4413     int		found_new_match;
4414     int		type = ctrl_x_mode;
4415     char_u	*ptr;
4416     char_u	*dict = NULL;
4417     int		dict_f = 0;
4418     int		set_match_pos;
4419 
4420     if (!compl_started)
4421     {
4422 	FOR_ALL_BUFFERS(ins_buf)
4423 	    ins_buf->b_scanned = 0;
4424 	found_all = FALSE;
4425 	ins_buf = curbuf;
4426 	e_cpt = (compl_cont_status & CONT_LOCAL)
4427 					    ? (char_u *)"." : curbuf->b_p_cpt;
4428 	last_match_pos = first_match_pos = *ini;
4429     }
4430     else if (ins_buf != curbuf && !buf_valid(ins_buf))
4431 	ins_buf = curbuf;  // In case the buffer was wiped out.
4432 
4433     compl_old_match = compl_curr_match;	/* remember the last current match */
4434     pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
4435 
4436     /*
4437      * For ^N/^P loop over all the flags/windows/buffers in 'complete'.
4438      */
4439     for (;;)
4440     {
4441 	found_new_match = FAIL;
4442 	set_match_pos = FALSE;
4443 
4444 	/* For ^N/^P pick a new entry from e_cpt if compl_started is off,
4445 	 * or if found_all says this entry is done.  For ^X^L only use the
4446 	 * entries from 'complete' that look in loaded buffers. */
4447 	if ((ctrl_x_mode == CTRL_X_NORMAL
4448 		    || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4449 					&& (!compl_started || found_all))
4450 	{
4451 	    found_all = FALSE;
4452 	    while (*e_cpt == ',' || *e_cpt == ' ')
4453 		e_cpt++;
4454 	    if (*e_cpt == '.' && !curbuf->b_scanned)
4455 	    {
4456 		ins_buf = curbuf;
4457 		first_match_pos = *ini;
4458 		/* Move the cursor back one character so that ^N can match the
4459 		 * word immediately after the cursor. */
4460 		if (ctrl_x_mode == CTRL_X_NORMAL && dec(&first_match_pos) < 0)
4461 		{
4462 		    /* Move the cursor to after the last character in the
4463 		     * buffer, so that word at start of buffer is found
4464 		     * correctly. */
4465 		    first_match_pos.lnum = ins_buf->b_ml.ml_line_count;
4466 		    first_match_pos.col =
4467 				 (colnr_T)STRLEN(ml_get(first_match_pos.lnum));
4468 		}
4469 		last_match_pos = first_match_pos;
4470 		type = 0;
4471 
4472 		/* Remember the first match so that the loop stops when we
4473 		 * wrap and come back there a second time. */
4474 		set_match_pos = TRUE;
4475 	    }
4476 	    else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
4477 		 && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
4478 	    {
4479 		/* Scan a buffer, but not the current one. */
4480 		if (ins_buf->b_ml.ml_mfp != NULL)   /* loaded buffer */
4481 		{
4482 		    compl_started = TRUE;
4483 		    first_match_pos.col = last_match_pos.col = 0;
4484 		    first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
4485 		    last_match_pos.lnum = 0;
4486 		    type = 0;
4487 		}
4488 		else	/* unloaded buffer, scan like dictionary */
4489 		{
4490 		    found_all = TRUE;
4491 		    if (ins_buf->b_fname == NULL)
4492 			continue;
4493 		    type = CTRL_X_DICTIONARY;
4494 		    dict = ins_buf->b_fname;
4495 		    dict_f = DICT_EXACT;
4496 		}
4497 		vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
4498 			ins_buf->b_fname == NULL
4499 			    ? buf_spname(ins_buf)
4500 			    : ins_buf->b_sfname == NULL
4501 				? ins_buf->b_fname
4502 				: ins_buf->b_sfname);
4503 		(void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R));
4504 	    }
4505 	    else if (*e_cpt == NUL)
4506 		break;
4507 	    else
4508 	    {
4509 		if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4510 		    type = -1;
4511 		else if (*e_cpt == 'k' || *e_cpt == 's')
4512 		{
4513 		    if (*e_cpt == 'k')
4514 			type = CTRL_X_DICTIONARY;
4515 		    else
4516 			type = CTRL_X_THESAURUS;
4517 		    if (*++e_cpt != ',' && *e_cpt != NUL)
4518 		    {
4519 			dict = e_cpt;
4520 			dict_f = DICT_FIRST;
4521 		    }
4522 		}
4523 #ifdef FEAT_FIND_ID
4524 		else if (*e_cpt == 'i')
4525 		    type = CTRL_X_PATH_PATTERNS;
4526 		else if (*e_cpt == 'd')
4527 		    type = CTRL_X_PATH_DEFINES;
4528 #endif
4529 		else if (*e_cpt == ']' || *e_cpt == 't')
4530 		{
4531 		    type = CTRL_X_TAGS;
4532 		    vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags."));
4533 		    (void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R));
4534 		}
4535 		else
4536 		    type = -1;
4537 
4538 		/* in any case e_cpt is advanced to the next entry */
4539 		(void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
4540 
4541 		found_all = TRUE;
4542 		if (type == -1)
4543 		    continue;
4544 	    }
4545 	}
4546 
4547 	/* If complete() was called then compl_pattern has been reset.  The
4548 	 * following won't work then, bail out. */
4549 	if (compl_pattern == NULL)
4550 	    break;
4551 
4552 	switch (type)
4553 	{
4554 	case -1:
4555 	    break;
4556 #ifdef FEAT_FIND_ID
4557 	case CTRL_X_PATH_PATTERNS:
4558 	case CTRL_X_PATH_DEFINES:
4559 	    find_pattern_in_path(compl_pattern, compl_direction,
4560 				 (int)STRLEN(compl_pattern), FALSE, FALSE,
4561 				 (type == CTRL_X_PATH_DEFINES
4562 				  && !(compl_cont_status & CONT_SOL))
4563 				 ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
4564 				 (linenr_T)1, (linenr_T)MAXLNUM);
4565 	    break;
4566 #endif
4567 
4568 	case CTRL_X_DICTIONARY:
4569 	case CTRL_X_THESAURUS:
4570 	    ins_compl_dictionaries(
4571 		    dict != NULL ? dict
4572 			 : (type == CTRL_X_THESAURUS
4573 			     ? (*curbuf->b_p_tsr == NUL
4574 				 ? p_tsr
4575 				 : curbuf->b_p_tsr)
4576 			     : (*curbuf->b_p_dict == NUL
4577 				 ? p_dict
4578 				 : curbuf->b_p_dict)),
4579 			    compl_pattern,
4580 				 dict != NULL ? dict_f
4581 					       : 0, type == CTRL_X_THESAURUS);
4582 	    dict = NULL;
4583 	    break;
4584 
4585 	case CTRL_X_TAGS:
4586 	    /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
4587 	    save_p_ic = p_ic;
4588 	    p_ic = ignorecase(compl_pattern);
4589 
4590 	    /* Find up to TAG_MANY matches.  Avoids that an enormous number
4591 	     * of matches is found when compl_pattern is empty */
4592 	    if (find_tags(compl_pattern, &num_matches, &matches,
4593 		    TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
4594 		    | (ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
4595 		    TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
4596 	    {
4597 		ins_compl_add_matches(num_matches, matches, p_ic);
4598 	    }
4599 	    p_ic = save_p_ic;
4600 	    break;
4601 
4602 	case CTRL_X_FILES:
4603 	    if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
4604 				  EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
4605 	    {
4606 
4607 		/* May change home directory back to "~". */
4608 		tilde_replace(compl_pattern, num_matches, matches);
4609 		ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
4610 	    }
4611 	    break;
4612 
4613 	case CTRL_X_CMDLINE:
4614 	    if (expand_cmdline(&compl_xp, compl_pattern,
4615 			(int)STRLEN(compl_pattern),
4616 					 &num_matches, &matches) == EXPAND_OK)
4617 		ins_compl_add_matches(num_matches, matches, FALSE);
4618 	    break;
4619 
4620 #ifdef FEAT_COMPL_FUNC
4621 	case CTRL_X_FUNCTION:
4622 	case CTRL_X_OMNI:
4623 	    expand_by_function(type, compl_pattern);
4624 	    break;
4625 #endif
4626 
4627 	case CTRL_X_SPELL:
4628 #ifdef FEAT_SPELL
4629 	    num_matches = expand_spelling(first_match_pos.lnum,
4630 						     compl_pattern, &matches);
4631 	    if (num_matches > 0)
4632 		ins_compl_add_matches(num_matches, matches, p_ic);
4633 #endif
4634 	    break;
4635 
4636 	default:	/* normal ^P/^N and ^X^L */
4637 	    /*
4638 	     * If 'infercase' is set, don't use 'smartcase' here
4639 	     */
4640 	    save_p_scs = p_scs;
4641 	    if (ins_buf->b_p_inf)
4642 		p_scs = FALSE;
4643 
4644 	    /*	Buffers other than curbuf are scanned from the beginning or the
4645 	     *	end but never from the middle, thus setting nowrapscan in this
4646 	     *	buffers is a good idea, on the other hand, we always set
4647 	     *	wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
4648 	    save_p_ws = p_ws;
4649 	    if (ins_buf != curbuf)
4650 		p_ws = FALSE;
4651 	    else if (*e_cpt == '.')
4652 		p_ws = TRUE;
4653 	    for (;;)
4654 	    {
4655 		int	flags = 0;
4656 
4657 		++msg_silent;  /* Don't want messages for wrapscan. */
4658 
4659 		/* CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
4660 		 * || word-wise search that
4661 		 * has added a word that was at the beginning of the line */
4662 		if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
4663 			|| (compl_cont_status & CONT_SOL))
4664 		    found_new_match = search_for_exact_line(ins_buf, pos,
4665 					      compl_direction, compl_pattern);
4666 		else
4667 		    found_new_match = searchit(NULL, ins_buf, pos, NULL,
4668 							      compl_direction,
4669 				 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
4670 					     RE_LAST, (linenr_T)0, NULL, NULL);
4671 		--msg_silent;
4672 		if (!compl_started || set_match_pos)
4673 		{
4674 		    /* set "compl_started" even on fail */
4675 		    compl_started = TRUE;
4676 		    first_match_pos = *pos;
4677 		    last_match_pos = *pos;
4678 		    set_match_pos = FALSE;
4679 		}
4680 		else if (first_match_pos.lnum == last_match_pos.lnum
4681 				 && first_match_pos.col == last_match_pos.col)
4682 		    found_new_match = FAIL;
4683 		if (found_new_match == FAIL)
4684 		{
4685 		    if (ins_buf == curbuf)
4686 			found_all = TRUE;
4687 		    break;
4688 		}
4689 
4690 		/* when ADDING, the text before the cursor matches, skip it */
4691 		if (	(compl_cont_status & CONT_ADDING) && ins_buf == curbuf
4692 			&& ini->lnum == pos->lnum
4693 			&& ini->col  == pos->col)
4694 		    continue;
4695 		ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
4696 		if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4697 		{
4698 		    if (compl_cont_status & CONT_ADDING)
4699 		    {
4700 			if (pos->lnum >= ins_buf->b_ml.ml_line_count)
4701 			    continue;
4702 			ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
4703 			if (!p_paste)
4704 			    ptr = skipwhite(ptr);
4705 		    }
4706 		    len = (int)STRLEN(ptr);
4707 		}
4708 		else
4709 		{
4710 		    char_u	*tmp_ptr = ptr;
4711 
4712 		    if (compl_cont_status & CONT_ADDING)
4713 		    {
4714 			tmp_ptr += compl_length;
4715 			/* Skip if already inside a word. */
4716 			if (vim_iswordp(tmp_ptr))
4717 			    continue;
4718 			/* Find start of next word. */
4719 			tmp_ptr = find_word_start(tmp_ptr);
4720 		    }
4721 		    /* Find end of this word. */
4722 		    tmp_ptr = find_word_end(tmp_ptr);
4723 		    len = (int)(tmp_ptr - ptr);
4724 
4725 		    if ((compl_cont_status & CONT_ADDING)
4726 						       && len == compl_length)
4727 		    {
4728 			if (pos->lnum < ins_buf->b_ml.ml_line_count)
4729 			{
4730 			    /* Try next line, if any. the new word will be
4731 			     * "join" as if the normal command "J" was used.
4732 			     * IOSIZE is always greater than
4733 			     * compl_length, so the next STRNCPY always
4734 			     * works -- Acevedo */
4735 			    STRNCPY(IObuff, ptr, len);
4736 			    ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
4737 			    tmp_ptr = ptr = skipwhite(ptr);
4738 			    /* Find start of next word. */
4739 			    tmp_ptr = find_word_start(tmp_ptr);
4740 			    /* Find end of next word. */
4741 			    tmp_ptr = find_word_end(tmp_ptr);
4742 			    if (tmp_ptr > ptr)
4743 			    {
4744 				if (*ptr != ')' && IObuff[len - 1] != TAB)
4745 				{
4746 				    if (IObuff[len - 1] != ' ')
4747 					IObuff[len++] = ' ';
4748 				    /* IObuf =~ "\k.* ", thus len >= 2 */
4749 				    if (p_js
4750 					&& (IObuff[len - 2] == '.'
4751 					    || (vim_strchr(p_cpo, CPO_JOINSP)
4752 								       == NULL
4753 						&& (IObuff[len - 2] == '?'
4754 						 || IObuff[len - 2] == '!'))))
4755 					IObuff[len++] = ' ';
4756 				}
4757 				/* copy as much as possible of the new word */
4758 				if (tmp_ptr - ptr >= IOSIZE - len)
4759 				    tmp_ptr = ptr + IOSIZE - len - 1;
4760 				STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
4761 				len += (int)(tmp_ptr - ptr);
4762 				flags |= CONT_S_IPOS;
4763 			    }
4764 			    IObuff[len] = NUL;
4765 			    ptr = IObuff;
4766 			}
4767 			if (len == compl_length)
4768 			    continue;
4769 		    }
4770 		}
4771 		if (ins_compl_add_infercase(ptr, len, p_ic,
4772 				 ins_buf == curbuf ? NULL : ins_buf->b_sfname,
4773 					   0, flags) != NOTDONE)
4774 		{
4775 		    found_new_match = OK;
4776 		    break;
4777 		}
4778 	    }
4779 	    p_scs = save_p_scs;
4780 	    p_ws = save_p_ws;
4781 	}
4782 
4783 	/* check if compl_curr_match has changed, (e.g. other type of
4784 	 * expansion added something) */
4785 	if (type != 0 && compl_curr_match != compl_old_match)
4786 	    found_new_match = OK;
4787 
4788 	/* break the loop for specialized modes (use 'complete' just for the
4789 	 * generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new
4790 	 * match */
4791 	if ((ctrl_x_mode != CTRL_X_NORMAL
4792 		    && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4793 						   || found_new_match != FAIL)
4794 	{
4795 	    if (got_int)
4796 		break;
4797 	    /* Fill the popup menu as soon as possible. */
4798 	    if (type != -1)
4799 		ins_compl_check_keys(0, FALSE);
4800 
4801 	    if ((ctrl_x_mode != CTRL_X_NORMAL
4802 			&& !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4803 							 || compl_interrupted)
4804 		break;
4805 	    compl_started = TRUE;
4806 	}
4807 	else
4808 	{
4809 	    /* Mark a buffer scanned when it has been scanned completely */
4810 	    if (type == 0 || type == CTRL_X_PATH_PATTERNS)
4811 		ins_buf->b_scanned = TRUE;
4812 
4813 	    compl_started = FALSE;
4814 	}
4815     }
4816     compl_started = TRUE;
4817 
4818     if ((ctrl_x_mode == CTRL_X_NORMAL || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
4819 	    && *e_cpt == NUL)		/* Got to end of 'complete' */
4820 	found_new_match = FAIL;
4821 
4822     i = -1;		/* total of matches, unknown */
4823     if (found_new_match == FAIL || (ctrl_x_mode != CTRL_X_NORMAL
4824 				    && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)))
4825 	i = ins_compl_make_cyclic();
4826 
4827     if (compl_old_match != NULL)
4828     {
4829 	/* If several matches were added (FORWARD) or the search failed and has
4830 	 * just been made cyclic then we have to move compl_curr_match to the
4831 	 * next or previous entry (if any) -- Acevedo */
4832 	compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next
4833 						    : compl_old_match->cp_prev;
4834 	if (compl_curr_match == NULL)
4835 	    compl_curr_match = compl_old_match;
4836     }
4837     return i;
4838 }
4839 
4840 /* Delete the old text being completed. */
4841     static void
4842 ins_compl_delete(void)
4843 {
4844     int	    col;
4845 
4846     /*
4847      * In insert mode: Delete the typed part.
4848      * In replace mode: Put the old characters back, if any.
4849      */
4850     col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
4851     if ((int)curwin->w_cursor.col > col)
4852     {
4853 	if (stop_arrow() == FAIL)
4854 	    return;
4855 	backspace_until_column(col);
4856     }
4857 
4858     /* TODO: is this sufficient for redrawing?  Redrawing everything causes
4859      * flicker, thus we can't do that. */
4860     changed_cline_bef_curs();
4861     /* clear v:completed_item */
4862     set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
4863 }
4864 
4865 /*
4866  * Insert the new text being completed.
4867  * "in_compl_func" is TRUE when called from complete_check().
4868  */
4869     static void
4870 ins_compl_insert(int in_compl_func)
4871 {
4872     dict_T	*dict;
4873 
4874     ins_bytes(compl_shown_match->cp_str + ins_compl_len());
4875     if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
4876 	compl_used_match = FALSE;
4877     else
4878 	compl_used_match = TRUE;
4879 
4880     /* Set completed item. */
4881     /* { word, abbr, menu, kind, info } */
4882     dict = dict_alloc_lock(VAR_FIXED);
4883     if (dict != NULL)
4884     {
4885 	dict_add_string(dict, "word", compl_shown_match->cp_str);
4886 	dict_add_string(dict, "abbr", compl_shown_match->cp_text[CPT_ABBR]);
4887 	dict_add_string(dict, "menu", compl_shown_match->cp_text[CPT_MENU]);
4888 	dict_add_string(dict, "kind", compl_shown_match->cp_text[CPT_KIND]);
4889 	dict_add_string(dict, "info", compl_shown_match->cp_text[CPT_INFO]);
4890 	dict_add_string(dict, "user_data",
4891 				 compl_shown_match->cp_text[CPT_USER_DATA]);
4892     }
4893     set_vim_var_dict(VV_COMPLETED_ITEM, dict);
4894     if (!in_compl_func)
4895 	compl_curr_match = compl_shown_match;
4896 }
4897 
4898 /*
4899  * Fill in the next completion in the current direction.
4900  * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to
4901  * get more completions.  If it is FALSE, then we just do nothing when there
4902  * are no more completions in a given direction.  The latter case is used when
4903  * we are still in the middle of finding completions, to allow browsing
4904  * through the ones found so far.
4905  * Return the total number of matches, or -1 if still unknown -- webb.
4906  *
4907  * compl_curr_match is currently being used by ins_compl_get_exp(), so we use
4908  * compl_shown_match here.
4909  *
4910  * Note that this function may be called recursively once only.  First with
4911  * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn
4912  * calls this function with "allow_get_expansion" FALSE.
4913  */
4914     static int
4915 ins_compl_next(
4916     int	    allow_get_expansion,
4917     int	    count,		/* repeat completion this many times; should
4918 				   be at least 1 */
4919     int	    insert_match,	/* Insert the newly selected match */
4920     int	    in_compl_func)	/* called from complete_check() */
4921 {
4922     int	    num_matches = -1;
4923     int	    todo = count;
4924     compl_T *found_compl = NULL;
4925     int	    found_end = FALSE;
4926     int	    advance;
4927     int	    started = compl_started;
4928 
4929     /* When user complete function return -1 for findstart which is next
4930      * time of 'always', compl_shown_match become NULL. */
4931     if (compl_shown_match == NULL)
4932 	return -1;
4933 
4934     if (compl_leader != NULL
4935 			&& (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0)
4936     {
4937 	/* Set "compl_shown_match" to the actually shown match, it may differ
4938 	 * when "compl_leader" is used to omit some of the matches. */
4939 	while (!ins_compl_equal(compl_shown_match,
4940 				      compl_leader, (int)STRLEN(compl_leader))
4941 		&& compl_shown_match->cp_next != NULL
4942 		&& compl_shown_match->cp_next != compl_first_match)
4943 	    compl_shown_match = compl_shown_match->cp_next;
4944 
4945 	/* If we didn't find it searching forward, and compl_shows_dir is
4946 	 * backward, find the last match. */
4947 	if (compl_shows_dir == BACKWARD
4948 		&& !ins_compl_equal(compl_shown_match,
4949 				      compl_leader, (int)STRLEN(compl_leader))
4950 		&& (compl_shown_match->cp_next == NULL
4951 		    || compl_shown_match->cp_next == compl_first_match))
4952 	{
4953 	    while (!ins_compl_equal(compl_shown_match,
4954 				      compl_leader, (int)STRLEN(compl_leader))
4955 		    && compl_shown_match->cp_prev != NULL
4956 		    && compl_shown_match->cp_prev != compl_first_match)
4957 		compl_shown_match = compl_shown_match->cp_prev;
4958 	}
4959     }
4960 
4961     if (allow_get_expansion && insert_match
4962 	    && (!(compl_get_longest || compl_restarting) || compl_used_match))
4963 	/* Delete old text to be replaced */
4964 	ins_compl_delete();
4965 
4966     /* When finding the longest common text we stick at the original text,
4967      * don't let CTRL-N or CTRL-P move to the first match. */
4968     advance = count != 1 || !allow_get_expansion || !compl_get_longest;
4969 
4970     /* When restarting the search don't insert the first match either. */
4971     if (compl_restarting)
4972     {
4973 	advance = FALSE;
4974 	compl_restarting = FALSE;
4975     }
4976 
4977     /* Repeat this for when <PageUp> or <PageDown> is typed.  But don't wrap
4978      * around. */
4979     while (--todo >= 0)
4980     {
4981 	if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL)
4982 	{
4983 	    compl_shown_match = compl_shown_match->cp_next;
4984 	    found_end = (compl_first_match != NULL
4985 			   && (compl_shown_match->cp_next == compl_first_match
4986 			       || compl_shown_match == compl_first_match));
4987 	}
4988 	else if (compl_shows_dir == BACKWARD
4989 					&& compl_shown_match->cp_prev != NULL)
4990 	{
4991 	    found_end = (compl_shown_match == compl_first_match);
4992 	    compl_shown_match = compl_shown_match->cp_prev;
4993 	    found_end |= (compl_shown_match == compl_first_match);
4994 	}
4995 	else
4996 	{
4997 	    if (!allow_get_expansion)
4998 	    {
4999 		if (advance)
5000 		{
5001 		    if (compl_shows_dir == BACKWARD)
5002 			compl_pending -= todo + 1;
5003 		    else
5004 			compl_pending += todo + 1;
5005 		}
5006 		return -1;
5007 	    }
5008 
5009 	    if (!compl_no_select && advance)
5010 	    {
5011 		if (compl_shows_dir == BACKWARD)
5012 		    --compl_pending;
5013 		else
5014 		    ++compl_pending;
5015 	    }
5016 
5017 	    /* Find matches. */
5018 	    num_matches = ins_compl_get_exp(&compl_startpos);
5019 
5020 	    /* handle any pending completions */
5021 	    while (compl_pending != 0 && compl_direction == compl_shows_dir
5022 								   && advance)
5023 	    {
5024 		if (compl_pending > 0 && compl_shown_match->cp_next != NULL)
5025 		{
5026 		    compl_shown_match = compl_shown_match->cp_next;
5027 		    --compl_pending;
5028 		}
5029 		if (compl_pending < 0 && compl_shown_match->cp_prev != NULL)
5030 		{
5031 		    compl_shown_match = compl_shown_match->cp_prev;
5032 		    ++compl_pending;
5033 		}
5034 		else
5035 		    break;
5036 	    }
5037 	    found_end = FALSE;
5038 	}
5039 	if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0
5040 		&& compl_leader != NULL
5041 		&& !ins_compl_equal(compl_shown_match,
5042 				     compl_leader, (int)STRLEN(compl_leader)))
5043 	    ++todo;
5044 	else
5045 	    /* Remember a matching item. */
5046 	    found_compl = compl_shown_match;
5047 
5048 	/* Stop at the end of the list when we found a usable match. */
5049 	if (found_end)
5050 	{
5051 	    if (found_compl != NULL)
5052 	    {
5053 		compl_shown_match = found_compl;
5054 		break;
5055 	    }
5056 	    todo = 1;	    /* use first usable match after wrapping around */
5057 	}
5058     }
5059 
5060     /* Insert the text of the new completion, or the compl_leader. */
5061     if (compl_no_insert && !started)
5062     {
5063 	ins_bytes(compl_orig_text + ins_compl_len());
5064 	compl_used_match = FALSE;
5065     }
5066     else if (insert_match)
5067     {
5068 	if (!compl_get_longest || compl_used_match)
5069 	    ins_compl_insert(in_compl_func);
5070 	else
5071 	    ins_bytes(compl_leader + ins_compl_len());
5072     }
5073     else
5074 	compl_used_match = FALSE;
5075 
5076     if (!allow_get_expansion)
5077     {
5078 	/* may undisplay the popup menu first */
5079 	ins_compl_upd_pum();
5080 
5081 	// Redraw before showing the popup menu to show the user what was
5082 	// inserted.
5083 	pum_call_update_screen();
5084 
5085 	/* display the updated popup menu */
5086 	ins_compl_show_pum();
5087 #ifdef FEAT_GUI
5088 	if (gui.in_use)
5089 	{
5090 	    /* Show the cursor after the match, not after the redrawn text. */
5091 	    setcursor();
5092 	    out_flush_cursor(FALSE, FALSE);
5093 	}
5094 #endif
5095 
5096 	/* Delete old text to be replaced, since we're still searching and
5097 	 * don't want to match ourselves!  */
5098 	ins_compl_delete();
5099     }
5100 
5101     /* Enter will select a match when the match wasn't inserted and the popup
5102      * menu is visible. */
5103     if (compl_no_insert && !started)
5104 	compl_enter_selects = TRUE;
5105     else
5106 	compl_enter_selects = !insert_match && compl_match_array != NULL;
5107 
5108     /*
5109      * Show the file name for the match (if any)
5110      * Truncate the file name to avoid a wait for return.
5111      */
5112     if (compl_shown_match->cp_fname != NULL)
5113     {
5114 	char	*lead = _("match in file");
5115 	int	space = sc_col - vim_strsize((char_u *)lead) - 2;
5116 	char_u	*s;
5117 	char_u	*e;
5118 
5119 	if (space > 0)
5120 	{
5121 	    /* We need the tail that fits.  With double-byte encoding going
5122 	     * back from the end is very slow, thus go from the start and keep
5123 	     * the text that fits in "space" between "s" and "e". */
5124 	    for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e))
5125 	    {
5126 		space -= ptr2cells(e);
5127 		while (space < 0)
5128 		{
5129 		    space += ptr2cells(s);
5130 		    MB_PTR_ADV(s);
5131 		}
5132 	    }
5133 	    vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
5134 				s > compl_shown_match->cp_fname ? "<" : "", s);
5135 	    msg(IObuff);
5136 	    redraw_cmdline = FALSE;	    /* don't overwrite! */
5137 	}
5138     }
5139 
5140     return num_matches;
5141 }
5142 
5143 /*
5144  * Call this while finding completions, to check whether the user has hit a key
5145  * that should change the currently displayed completion, or exit completion
5146  * mode.  Also, when compl_pending is not zero, show a completion as soon as
5147  * possible. -- webb
5148  * "frequency" specifies out of how many calls we actually check.
5149  * "in_compl_func" is TRUE when called from complete_check(), don't set
5150  * compl_curr_match.
5151  */
5152     void
5153 ins_compl_check_keys(int frequency, int in_compl_func)
5154 {
5155     static int	count = 0;
5156     int		c;
5157 
5158     /* Don't check when reading keys from a script, :normal or feedkeys().
5159      * That would break the test scripts.  But do check for keys when called
5160      * from complete_check(). */
5161     if (!in_compl_func && (using_script() || ex_normal_busy))
5162 	return;
5163 
5164     /* Only do this at regular intervals */
5165     if (++count < frequency)
5166 	return;
5167     count = 0;
5168 
5169     /* Check for a typed key.  Do use mappings, otherwise vim_is_ctrl_x_key()
5170      * can't do its work correctly. */
5171     c = vpeekc_any();
5172     if (c != NUL)
5173     {
5174 	if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
5175 	{
5176 	    c = safe_vgetc();	/* Eat the character */
5177 	    compl_shows_dir = ins_compl_key2dir(c);
5178 	    (void)ins_compl_next(FALSE, ins_compl_key2count(c),
5179 				      c != K_UP && c != K_DOWN, in_compl_func);
5180 	}
5181 	else
5182 	{
5183 	    /* Need to get the character to have KeyTyped set.  We'll put it
5184 	     * back with vungetc() below.  But skip K_IGNORE. */
5185 	    c = safe_vgetc();
5186 	    if (c != K_IGNORE)
5187 	    {
5188 		/* Don't interrupt completion when the character wasn't typed,
5189 		 * e.g., when doing @q to replay keys. */
5190 		if (c != Ctrl_R && KeyTyped)
5191 		    compl_interrupted = TRUE;
5192 
5193 		vungetc(c);
5194 	    }
5195 	}
5196     }
5197     if (compl_pending != 0 && !got_int && !compl_no_insert)
5198     {
5199 	int todo = compl_pending > 0 ? compl_pending : -compl_pending;
5200 
5201 	compl_pending = 0;
5202 	(void)ins_compl_next(FALSE, todo, TRUE, in_compl_func);
5203     }
5204 }
5205 
5206 /*
5207  * Decide the direction of Insert mode complete from the key typed.
5208  * Returns BACKWARD or FORWARD.
5209  */
5210     static int
5211 ins_compl_key2dir(int c)
5212 {
5213     if (c == Ctrl_P || c == Ctrl_L
5214 	    || c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP || c == K_UP)
5215 	return BACKWARD;
5216     return FORWARD;
5217 }
5218 
5219 /*
5220  * Return TRUE for keys that are used for completion only when the popup menu
5221  * is visible.
5222  */
5223     static int
5224 ins_compl_pum_key(int c)
5225 {
5226     return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
5227 		     || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN
5228 		     || c == K_UP || c == K_DOWN);
5229 }
5230 
5231 /*
5232  * Decide the number of completions to move forward.
5233  * Returns 1 for most keys, height of the popup menu for page-up/down keys.
5234  */
5235     static int
5236 ins_compl_key2count(int c)
5237 {
5238     int		h;
5239 
5240     if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN)
5241     {
5242 	h = pum_get_height();
5243 	if (h > 3)
5244 	    h -= 2; /* keep some context */
5245 	return h;
5246     }
5247     return 1;
5248 }
5249 
5250 /*
5251  * Return TRUE if completion with "c" should insert the match, FALSE if only
5252  * to change the currently selected completion.
5253  */
5254     static int
5255 ins_compl_use_match(int c)
5256 {
5257     switch (c)
5258     {
5259 	case K_UP:
5260 	case K_DOWN:
5261 	case K_PAGEDOWN:
5262 	case K_KPAGEDOWN:
5263 	case K_S_DOWN:
5264 	case K_PAGEUP:
5265 	case K_KPAGEUP:
5266 	case K_S_UP:
5267 	    return FALSE;
5268     }
5269     return TRUE;
5270 }
5271 
5272 /*
5273  * Do Insert mode completion.
5274  * Called when character "c" was typed, which has a meaning for completion.
5275  * Returns OK if completion was done, FAIL if something failed (out of mem).
5276  */
5277     static int
5278 ins_complete(int c, int enable_pum)
5279 {
5280     char_u	*line;
5281     int		startcol = 0;	    /* column where searched text starts */
5282     colnr_T	curs_col;	    /* cursor column */
5283     int		n;
5284     int		save_w_wrow;
5285     int		save_w_leftcol;
5286     int		insert_match;
5287     int		save_did_ai = did_ai;
5288 
5289     compl_direction = ins_compl_key2dir(c);
5290     insert_match = ins_compl_use_match(c);
5291 
5292     if (!compl_started)
5293     {
5294 	/* First time we hit ^N or ^P (in a row, I mean) */
5295 
5296 	did_ai = FALSE;
5297 #ifdef FEAT_SMARTINDENT
5298 	did_si = FALSE;
5299 	can_si = FALSE;
5300 	can_si_back = FALSE;
5301 #endif
5302 	if (stop_arrow() == FAIL)
5303 	    return FAIL;
5304 
5305 	line = ml_get(curwin->w_cursor.lnum);
5306 	curs_col = curwin->w_cursor.col;
5307 	compl_pending = 0;
5308 
5309 	/* If this same ctrl_x_mode has been interrupted use the text from
5310 	 * "compl_startpos" to the cursor as a pattern to add a new word
5311 	 * instead of expand the one before the cursor, in word-wise if
5312 	 * "compl_startpos" is not in the same line as the cursor then fix it
5313 	 * (the line has been split because it was longer than 'tw').  if SOL
5314 	 * is set then skip the previous pattern, a word at the beginning of
5315 	 * the line has been inserted, we'll look for that  -- Acevedo. */
5316 	if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
5317 					    && compl_cont_mode == ctrl_x_mode)
5318 	{
5319 	    /*
5320 	     * it is a continued search
5321 	     */
5322 	    compl_cont_status &= ~CONT_INTRPT;	/* remove INTRPT */
5323 	    if (ctrl_x_mode == CTRL_X_NORMAL
5324 		    || ctrl_x_mode == CTRL_X_PATH_PATTERNS
5325 		    || ctrl_x_mode == CTRL_X_PATH_DEFINES)
5326 	    {
5327 		if (compl_startpos.lnum != curwin->w_cursor.lnum)
5328 		{
5329 		    /* line (probably) wrapped, set compl_startpos to the
5330 		     * first non_blank in the line, if it is not a wordchar
5331 		     * include it to get a better pattern, but then we don't
5332 		     * want the "\\<" prefix, check it bellow */
5333 		    compl_col = (colnr_T)getwhitecols(line);
5334 		    compl_startpos.col = compl_col;
5335 		    compl_startpos.lnum = curwin->w_cursor.lnum;
5336 		    compl_cont_status &= ~CONT_SOL;   /* clear SOL if present */
5337 		}
5338 		else
5339 		{
5340 		    /* S_IPOS was set when we inserted a word that was at the
5341 		     * beginning of the line, which means that we'll go to SOL
5342 		     * mode but first we need to redefine compl_startpos */
5343 		    if (compl_cont_status & CONT_S_IPOS)
5344 		    {
5345 			compl_cont_status |= CONT_SOL;
5346 			compl_startpos.col = (colnr_T)(skipwhite(
5347 						line + compl_length
5348 						+ compl_startpos.col) - line);
5349 		    }
5350 		    compl_col = compl_startpos.col;
5351 		}
5352 		compl_length = curwin->w_cursor.col - (int)compl_col;
5353 		/* IObuff is used to add a "word from the next line" would we
5354 		 * have enough space?  just being paranoid */
5355 #define	MIN_SPACE 75
5356 		if (compl_length > (IOSIZE - MIN_SPACE))
5357 		{
5358 		    compl_cont_status &= ~CONT_SOL;
5359 		    compl_length = (IOSIZE - MIN_SPACE);
5360 		    compl_col = curwin->w_cursor.col - compl_length;
5361 		}
5362 		compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
5363 		if (compl_length < 1)
5364 		    compl_cont_status &= CONT_LOCAL;
5365 	    }
5366 	    else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
5367 		compl_cont_status = CONT_ADDING | CONT_N_ADDS;
5368 	    else
5369 		compl_cont_status = 0;
5370 	}
5371 	else
5372 	    compl_cont_status &= CONT_LOCAL;
5373 
5374 	if (!(compl_cont_status & CONT_ADDING))	/* normal expansion */
5375 	{
5376 	    compl_cont_mode = ctrl_x_mode;
5377 	    if (ctrl_x_mode != CTRL_X_NORMAL)
5378 		/* Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL */
5379 		compl_cont_status = 0;
5380 	    compl_cont_status |= CONT_N_ADDS;
5381 	    compl_startpos = curwin->w_cursor;
5382 	    startcol = (int)curs_col;
5383 	    compl_col = 0;
5384 	}
5385 
5386 	/* Work out completion pattern and original text -- webb */
5387 	if (ctrl_x_mode == CTRL_X_NORMAL || (ctrl_x_mode & CTRL_X_WANT_IDENT))
5388 	{
5389 	    if ((compl_cont_status & CONT_SOL)
5390 		    || ctrl_x_mode == CTRL_X_PATH_DEFINES)
5391 	    {
5392 		if (!(compl_cont_status & CONT_ADDING))
5393 		{
5394 		    while (--startcol >= 0 && vim_isIDc(line[startcol]))
5395 			;
5396 		    compl_col += ++startcol;
5397 		    compl_length = curs_col - startcol;
5398 		}
5399 		if (p_ic)
5400 		    compl_pattern = str_foldcase(line + compl_col,
5401 						       compl_length, NULL, 0);
5402 		else
5403 		    compl_pattern = vim_strnsave(line + compl_col,
5404 								compl_length);
5405 		if (compl_pattern == NULL)
5406 		    return FAIL;
5407 	    }
5408 	    else if (compl_cont_status & CONT_ADDING)
5409 	    {
5410 		char_u	    *prefix = (char_u *)"\\<";
5411 
5412 		/* we need up to 2 extra chars for the prefix */
5413 		compl_pattern = alloc(quote_meta(NULL, line + compl_col,
5414 							   compl_length) + 2);
5415 		if (compl_pattern == NULL)
5416 		    return FAIL;
5417 		if (!vim_iswordp(line + compl_col)
5418 			|| (compl_col > 0
5419 			    && (
5420 #ifdef FEAT_MBYTE
5421 				vim_iswordp(mb_prevptr(line, line + compl_col))
5422 #else
5423 				vim_iswordc(line[compl_col - 1])
5424 #endif
5425 				)))
5426 		    prefix = (char_u *)"";
5427 		STRCPY((char *)compl_pattern, prefix);
5428 		(void)quote_meta(compl_pattern + STRLEN(prefix),
5429 					      line + compl_col, compl_length);
5430 	    }
5431 	    else if (--startcol < 0 ||
5432 #ifdef FEAT_MBYTE
5433 			   !vim_iswordp(mb_prevptr(line, line + startcol + 1))
5434 #else
5435 			   !vim_iswordc(line[startcol])
5436 #endif
5437 		    )
5438 	    {
5439 		/* Match any word of at least two chars */
5440 		compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
5441 		if (compl_pattern == NULL)
5442 		    return FAIL;
5443 		compl_col += curs_col;
5444 		compl_length = 0;
5445 	    }
5446 	    else
5447 	    {
5448 #ifdef FEAT_MBYTE
5449 		/* Search the point of change class of multibyte character
5450 		 * or not a word single byte character backward.  */
5451 		if (has_mbyte)
5452 		{
5453 		    int base_class;
5454 		    int head_off;
5455 
5456 		    startcol -= (*mb_head_off)(line, line + startcol);
5457 		    base_class = mb_get_class(line + startcol);
5458 		    while (--startcol >= 0)
5459 		    {
5460 			head_off = (*mb_head_off)(line, line + startcol);
5461 			if (base_class != mb_get_class(line + startcol
5462 								  - head_off))
5463 			    break;
5464 			startcol -= head_off;
5465 		    }
5466 		}
5467 		else
5468 #endif
5469 		    while (--startcol >= 0 && vim_iswordc(line[startcol]))
5470 			;
5471 		compl_col += ++startcol;
5472 		compl_length = (int)curs_col - startcol;
5473 		if (compl_length == 1)
5474 		{
5475 		    /* Only match word with at least two chars -- webb
5476 		     * there's no need to call quote_meta,
5477 		     * alloc(7) is enough  -- Acevedo
5478 		     */
5479 		    compl_pattern = alloc(7);
5480 		    if (compl_pattern == NULL)
5481 			return FAIL;
5482 		    STRCPY((char *)compl_pattern, "\\<");
5483 		    (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
5484 		    STRCAT((char *)compl_pattern, "\\k");
5485 		}
5486 		else
5487 		{
5488 		    compl_pattern = alloc(quote_meta(NULL, line + compl_col,
5489 							   compl_length) + 2);
5490 		    if (compl_pattern == NULL)
5491 			return FAIL;
5492 		    STRCPY((char *)compl_pattern, "\\<");
5493 		    (void)quote_meta(compl_pattern + 2, line + compl_col,
5494 								compl_length);
5495 		}
5496 	    }
5497 	}
5498 	else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
5499 	{
5500 	    compl_col = (colnr_T)getwhitecols(line);
5501 	    compl_length = (int)curs_col - (int)compl_col;
5502 	    if (compl_length < 0)	/* cursor in indent: empty pattern */
5503 		compl_length = 0;
5504 	    if (p_ic)
5505 		compl_pattern = str_foldcase(line + compl_col, compl_length,
5506 								     NULL, 0);
5507 	    else
5508 		compl_pattern = vim_strnsave(line + compl_col, compl_length);
5509 	    if (compl_pattern == NULL)
5510 		return FAIL;
5511 	}
5512 	else if (ctrl_x_mode == CTRL_X_FILES)
5513 	{
5514 	    /* Go back to just before the first filename character. */
5515 	    if (startcol > 0)
5516 	    {
5517 		char_u	*p = line + startcol;
5518 
5519 		MB_PTR_BACK(line, p);
5520 		while (p > line && vim_isfilec(PTR2CHAR(p)))
5521 		    MB_PTR_BACK(line, p);
5522 		if (p == line && vim_isfilec(PTR2CHAR(p)))
5523 		    startcol = 0;
5524 		else
5525 		    startcol = (int)(p - line) + 1;
5526 	    }
5527 
5528 	    compl_col += startcol;
5529 	    compl_length = (int)curs_col - startcol;
5530 	    compl_pattern = addstar(line + compl_col, compl_length,
5531 								EXPAND_FILES);
5532 	    if (compl_pattern == NULL)
5533 		return FAIL;
5534 	}
5535 	else if (ctrl_x_mode == CTRL_X_CMDLINE)
5536 	{
5537 	    compl_pattern = vim_strnsave(line, curs_col);
5538 	    if (compl_pattern == NULL)
5539 		return FAIL;
5540 	    set_cmd_context(&compl_xp, compl_pattern,
5541 				  (int)STRLEN(compl_pattern), curs_col, FALSE);
5542 	    if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
5543 		    || compl_xp.xp_context == EXPAND_NOTHING)
5544 		/* No completion possible, use an empty pattern to get a
5545 		 * "pattern not found" message. */
5546 		compl_col = curs_col;
5547 	    else
5548 		compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
5549 	    compl_length = curs_col - compl_col;
5550 	}
5551 	else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
5552 	{
5553 #ifdef FEAT_COMPL_FUNC
5554 	    /*
5555 	     * Call user defined function 'completefunc' with "a:findstart"
5556 	     * set to 1 to obtain the length of text to use for completion.
5557 	     */
5558 	    typval_T	args[3];
5559 	    int		col;
5560 	    char_u	*funcname;
5561 	    pos_T	pos;
5562 	    win_T	*curwin_save;
5563 	    buf_T	*curbuf_save;
5564 	    int		save_State = State;
5565 
5566 	    /* Call 'completefunc' or 'omnifunc' and get pattern length as a
5567 	     * string */
5568 	    funcname = ctrl_x_mode == CTRL_X_FUNCTION
5569 					  ? curbuf->b_p_cfu : curbuf->b_p_ofu;
5570 	    if (*funcname == NUL)
5571 	    {
5572 		semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION
5573 					     ? "completefunc" : "omnifunc");
5574 		/* restore did_ai, so that adding comment leader works */
5575 		did_ai = save_did_ai;
5576 		return FAIL;
5577 	    }
5578 
5579 	    args[0].v_type = VAR_NUMBER;
5580 	    args[0].vval.v_number = 1;
5581 	    args[1].v_type = VAR_STRING;
5582 	    args[1].vval.v_string = (char_u *)"";
5583 	    args[2].v_type = VAR_UNKNOWN;
5584 	    pos = curwin->w_cursor;
5585 	    curwin_save = curwin;
5586 	    curbuf_save = curbuf;
5587 	    col = call_func_retnr(funcname, 2, args);
5588 
5589 	    State = save_State;
5590 	    if (curwin_save != curwin || curbuf_save != curbuf)
5591 	    {
5592 		emsg(_(e_complwin));
5593 		return FAIL;
5594 	    }
5595 	    curwin->w_cursor = pos;	/* restore the cursor position */
5596 	    validate_cursor();
5597 	    if (!EQUAL_POS(curwin->w_cursor, pos))
5598 	    {
5599 		emsg(_(e_compldel));
5600 		return FAIL;
5601 	    }
5602 
5603 	    /* Return value -2 means the user complete function wants to
5604 	     * cancel the complete without an error.
5605 	     * Return value -3 does the same as -2 and leaves CTRL-X mode.*/
5606 	    if (col == -2)
5607 		return FAIL;
5608 	    if (col == -3)
5609 	    {
5610 		ctrl_x_mode = CTRL_X_NORMAL;
5611 		edit_submode = NULL;
5612 		if (!shortmess(SHM_COMPLETIONMENU))
5613 		    msg_clr_cmdline();
5614 		return FAIL;
5615 	    }
5616 
5617 	    /*
5618 	     * Reset extended parameters of completion, when start new
5619 	     * completion.
5620 	     */
5621 	    compl_opt_refresh_always = FALSE;
5622 	    compl_opt_suppress_empty = FALSE;
5623 
5624 	    if (col < 0)
5625 		col = curs_col;
5626 	    compl_col = col;
5627 	    if (compl_col > curs_col)
5628 		compl_col = curs_col;
5629 
5630 	    /* Setup variables for completion.  Need to obtain "line" again,
5631 	     * it may have become invalid. */
5632 	    line = ml_get(curwin->w_cursor.lnum);
5633 	    compl_length = curs_col - compl_col;
5634 	    compl_pattern = vim_strnsave(line + compl_col, compl_length);
5635 	    if (compl_pattern == NULL)
5636 #endif
5637 		return FAIL;
5638 	}
5639 	else if (ctrl_x_mode == CTRL_X_SPELL)
5640 	{
5641 #ifdef FEAT_SPELL
5642 	    if (spell_bad_len > 0)
5643 		compl_col = curs_col - spell_bad_len;
5644 	    else
5645 		compl_col = spell_word_start(startcol);
5646 	    if (compl_col >= (colnr_T)startcol)
5647 	    {
5648 		compl_length = 0;
5649 		compl_col = curs_col;
5650 	    }
5651 	    else
5652 	    {
5653 		spell_expand_check_cap(compl_col);
5654 		compl_length = (int)curs_col - compl_col;
5655 	    }
5656 	    /* Need to obtain "line" again, it may have become invalid. */
5657 	    line = ml_get(curwin->w_cursor.lnum);
5658 	    compl_pattern = vim_strnsave(line + compl_col, compl_length);
5659 	    if (compl_pattern == NULL)
5660 #endif
5661 		return FAIL;
5662 	}
5663 	else
5664 	{
5665 	    internal_error("ins_complete()");
5666 	    return FAIL;
5667 	}
5668 
5669 	if (compl_cont_status & CONT_ADDING)
5670 	{
5671 	    edit_submode_pre = (char_u *)_(" Adding");
5672 	    if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
5673 	    {
5674 		/* Insert a new line, keep indentation but ignore 'comments' */
5675 #ifdef FEAT_COMMENTS
5676 		char_u *old = curbuf->b_p_com;
5677 
5678 		curbuf->b_p_com = (char_u *)"";
5679 #endif
5680 		compl_startpos.lnum = curwin->w_cursor.lnum;
5681 		compl_startpos.col = compl_col;
5682 		ins_eol('\r');
5683 #ifdef FEAT_COMMENTS
5684 		curbuf->b_p_com = old;
5685 #endif
5686 		compl_length = 0;
5687 		compl_col = curwin->w_cursor.col;
5688 	    }
5689 	}
5690 	else
5691 	{
5692 	    edit_submode_pre = NULL;
5693 	    compl_startpos.col = compl_col;
5694 	}
5695 
5696 	if (compl_cont_status & CONT_LOCAL)
5697 	    edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
5698 	else
5699 	    edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
5700 
5701 	/* If any of the original typed text has been changed we need to fix
5702 	 * the redo buffer. */
5703 	ins_compl_fixRedoBufForLeader(NULL);
5704 
5705 	/* Always add completion for the original text. */
5706 	vim_free(compl_orig_text);
5707 	compl_orig_text = vim_strnsave(line + compl_col, compl_length);
5708 	if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
5709 			-1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
5710 	{
5711 	    VIM_CLEAR(compl_pattern);
5712 	    VIM_CLEAR(compl_orig_text);
5713 	    return FAIL;
5714 	}
5715 
5716 	/* showmode might reset the internal line pointers, so it must
5717 	 * be called before line = ml_get(), or when this address is no
5718 	 * longer needed.  -- Acevedo.
5719 	 */
5720 	edit_submode_extra = (char_u *)_("-- Searching...");
5721 	edit_submode_highl = HLF_COUNT;
5722 	showmode();
5723 	edit_submode_extra = NULL;
5724 	out_flush();
5725     }
5726     else if (insert_match && stop_arrow() == FAIL)
5727 	return FAIL;
5728 
5729     compl_shown_match = compl_curr_match;
5730     compl_shows_dir = compl_direction;
5731 
5732     /*
5733      * Find next match (and following matches).
5734      */
5735     save_w_wrow = curwin->w_wrow;
5736     save_w_leftcol = curwin->w_leftcol;
5737     n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
5738 
5739     /* may undisplay the popup menu */
5740     ins_compl_upd_pum();
5741 
5742     if (n > 1)		/* all matches have been found */
5743 	compl_matches = n;
5744     compl_curr_match = compl_shown_match;
5745     compl_direction = compl_shows_dir;
5746 
5747     /* Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
5748      * mode. */
5749     if (got_int && !global_busy)
5750     {
5751 	(void)vgetc();
5752 	got_int = FALSE;
5753     }
5754 
5755     /* we found no match if the list has only the "compl_orig_text"-entry */
5756     if (compl_first_match == compl_first_match->cp_next)
5757     {
5758 	edit_submode_extra = (compl_cont_status & CONT_ADDING)
5759 			&& compl_length > 1
5760 			     ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
5761 	edit_submode_highl = HLF_E;
5762 	/* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
5763 	 * because we couldn't expand anything at first place, but if we used
5764 	 * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
5765 	 * (such as M in M'exico) if not tried already.  -- Acevedo */
5766 	if (	   compl_length > 1
5767 		|| (compl_cont_status & CONT_ADDING)
5768 		|| (ctrl_x_mode != CTRL_X_NORMAL
5769 		    && ctrl_x_mode != CTRL_X_PATH_PATTERNS
5770 		    && ctrl_x_mode != CTRL_X_PATH_DEFINES))
5771 	    compl_cont_status &= ~CONT_N_ADDS;
5772     }
5773 
5774     if (compl_curr_match->cp_flags & CONT_S_IPOS)
5775 	compl_cont_status |= CONT_S_IPOS;
5776     else
5777 	compl_cont_status &= ~CONT_S_IPOS;
5778 
5779     if (edit_submode_extra == NULL)
5780     {
5781 	if (compl_curr_match->cp_flags & ORIGINAL_TEXT)
5782 	{
5783 	    edit_submode_extra = (char_u *)_("Back at original");
5784 	    edit_submode_highl = HLF_W;
5785 	}
5786 	else if (compl_cont_status & CONT_S_IPOS)
5787 	{
5788 	    edit_submode_extra = (char_u *)_("Word from other line");
5789 	    edit_submode_highl = HLF_COUNT;
5790 	}
5791 	else if (compl_curr_match->cp_next == compl_curr_match->cp_prev)
5792 	{
5793 	    edit_submode_extra = (char_u *)_("The only match");
5794 	    edit_submode_highl = HLF_COUNT;
5795 	}
5796 	else
5797 	{
5798 	    /* Update completion sequence number when needed. */
5799 	    if (compl_curr_match->cp_number == -1)
5800 	    {
5801 		int		number = 0;
5802 		compl_T		*match;
5803 
5804 		if (compl_direction == FORWARD)
5805 		{
5806 		    /* search backwards for the first valid (!= -1) number.
5807 		     * This should normally succeed already at the first loop
5808 		     * cycle, so it's fast! */
5809 		    for (match = compl_curr_match->cp_prev; match != NULL
5810 			    && match != compl_first_match;
5811 						       match = match->cp_prev)
5812 			if (match->cp_number != -1)
5813 			{
5814 			    number = match->cp_number;
5815 			    break;
5816 			}
5817 		    if (match != NULL)
5818 			/* go up and assign all numbers which are not assigned
5819 			 * yet */
5820 			for (match = match->cp_next;
5821 				match != NULL && match->cp_number == -1;
5822 						       match = match->cp_next)
5823 			    match->cp_number = ++number;
5824 		}
5825 		else /* BACKWARD */
5826 		{
5827 		    /* search forwards (upwards) for the first valid (!= -1)
5828 		     * number.  This should normally succeed already at the
5829 		     * first loop cycle, so it's fast! */
5830 		    for (match = compl_curr_match->cp_next; match != NULL
5831 			    && match != compl_first_match;
5832 						       match = match->cp_next)
5833 			if (match->cp_number != -1)
5834 			{
5835 			    number = match->cp_number;
5836 			    break;
5837 			}
5838 		    if (match != NULL)
5839 			/* go down and assign all numbers which are not
5840 			 * assigned yet */
5841 			for (match = match->cp_prev; match
5842 				&& match->cp_number == -1;
5843 						       match = match->cp_prev)
5844 			    match->cp_number = ++number;
5845 		}
5846 	    }
5847 
5848 	    /* The match should always have a sequence number now, this is
5849 	     * just a safety check. */
5850 	    if (compl_curr_match->cp_number != -1)
5851 	    {
5852 		/* Space for 10 text chars. + 2x10-digit no.s = 31.
5853 		 * Translations may need more than twice that. */
5854 		static char_u match_ref[81];
5855 
5856 		if (compl_matches > 0)
5857 		    vim_snprintf((char *)match_ref, sizeof(match_ref),
5858 				_("match %d of %d"),
5859 				compl_curr_match->cp_number, compl_matches);
5860 		else
5861 		    vim_snprintf((char *)match_ref, sizeof(match_ref),
5862 				_("match %d"),
5863 				compl_curr_match->cp_number);
5864 		edit_submode_extra = match_ref;
5865 		edit_submode_highl = HLF_R;
5866 		if (dollar_vcol >= 0)
5867 		    curs_columns(FALSE);
5868 	    }
5869 	}
5870     }
5871 
5872     // Show a message about what (completion) mode we're in.
5873     if (!compl_opt_suppress_empty)
5874     {
5875 	showmode();
5876 	if (!shortmess(SHM_COMPLETIONMENU))
5877 	{
5878 	    if (edit_submode_extra != NULL)
5879 	    {
5880 		if (!p_smd)
5881 		    msg_attr(edit_submode_extra,
5882 			    edit_submode_highl < HLF_COUNT
5883 			    ? HL_ATTR(edit_submode_highl) : 0);
5884 	    }
5885 	    else
5886 		msg_clr_cmdline();	// necessary for "noshowmode"
5887 	}
5888     }
5889 
5890     /* Show the popup menu, unless we got interrupted. */
5891     if (enable_pum && !compl_interrupted)
5892 	show_pum(save_w_wrow, save_w_leftcol);
5893 
5894     compl_was_interrupted = compl_interrupted;
5895     compl_interrupted = FALSE;
5896 
5897     return OK;
5898 }
5899 
5900     static void
5901 show_pum(int prev_w_wrow, int prev_w_leftcol)
5902 {
5903     /* RedrawingDisabled may be set when invoked through complete(). */
5904     int n = RedrawingDisabled;
5905 
5906     RedrawingDisabled = 0;
5907 
5908     /* If the cursor moved or the display scrolled we need to remove the pum
5909      * first. */
5910     setcursor();
5911     if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol)
5912 	ins_compl_del_pum();
5913 
5914     ins_compl_show_pum();
5915     setcursor();
5916     RedrawingDisabled = n;
5917 }
5918 
5919 /*
5920  * Looks in the first "len" chars. of "src" for search-metachars.
5921  * If dest is not NULL the chars. are copied there quoting (with
5922  * a backslash) the metachars, and dest would be NUL terminated.
5923  * Returns the length (needed) of dest
5924  */
5925     static unsigned
5926 quote_meta(char_u *dest, char_u *src, int len)
5927 {
5928     unsigned	m = (unsigned)len + 1;  /* one extra for the NUL */
5929 
5930     for ( ; --len >= 0; src++)
5931     {
5932 	switch (*src)
5933 	{
5934 	    case '.':
5935 	    case '*':
5936 	    case '[':
5937 		if (ctrl_x_mode == CTRL_X_DICTIONARY
5938 					   || ctrl_x_mode == CTRL_X_THESAURUS)
5939 		    break;
5940 		/* FALLTHROUGH */
5941 	    case '~':
5942 		if (!p_magic)	/* quote these only if magic is set */
5943 		    break;
5944 		/* FALLTHROUGH */
5945 	    case '\\':
5946 		if (ctrl_x_mode == CTRL_X_DICTIONARY
5947 					   || ctrl_x_mode == CTRL_X_THESAURUS)
5948 		    break;
5949 		/* FALLTHROUGH */
5950 	    case '^':		/* currently it's not needed. */
5951 	    case '$':
5952 		m++;
5953 		if (dest != NULL)
5954 		    *dest++ = '\\';
5955 		break;
5956 	}
5957 	if (dest != NULL)
5958 	    *dest++ = *src;
5959 # ifdef FEAT_MBYTE
5960 	/* Copy remaining bytes of a multibyte character. */
5961 	if (has_mbyte)
5962 	{
5963 	    int i, mb_len;
5964 
5965 	    mb_len = (*mb_ptr2len)(src) - 1;
5966 	    if (mb_len > 0 && len >= mb_len)
5967 		for (i = 0; i < mb_len; ++i)
5968 		{
5969 		    --len;
5970 		    ++src;
5971 		    if (dest != NULL)
5972 			*dest++ = *src;
5973 		}
5974 	}
5975 # endif
5976     }
5977     if (dest != NULL)
5978 	*dest = NUL;
5979 
5980     return m;
5981 }
5982 #endif /* FEAT_INS_EXPAND */
5983 
5984 /*
5985  * Next character is interpreted literally.
5986  * A one, two or three digit decimal number is interpreted as its byte value.
5987  * If one or two digits are entered, the next character is given to vungetc().
5988  * For Unicode a character > 255 may be returned.
5989  */
5990     int
5991 get_literal(void)
5992 {
5993     int		cc;
5994     int		nc;
5995     int		i;
5996     int		hex = FALSE;
5997     int		octal = FALSE;
5998 #ifdef FEAT_MBYTE
5999     int		unicode = 0;
6000 #endif
6001 
6002     if (got_int)
6003 	return Ctrl_C;
6004 
6005 #ifdef FEAT_GUI
6006     /*
6007      * In GUI there is no point inserting the internal code for a special key.
6008      * It is more useful to insert the string "<KEY>" instead.	This would
6009      * probably be useful in a text window too, but it would not be
6010      * vi-compatible (maybe there should be an option for it?) -- webb
6011      */
6012     if (gui.in_use)
6013 	++allow_keys;
6014 #endif
6015 #ifdef USE_ON_FLY_SCROLL
6016     dont_scroll = TRUE;		/* disallow scrolling here */
6017 #endif
6018     ++no_mapping;		/* don't map the next key hits */
6019     cc = 0;
6020     i = 0;
6021     for (;;)
6022     {
6023 	nc = plain_vgetc();
6024 #ifdef FEAT_CMDL_INFO
6025 	if (!(State & CMDLINE)
6026 # ifdef FEAT_MBYTE
6027 		&& MB_BYTE2LEN_CHECK(nc) == 1
6028 # endif
6029 	   )
6030 	    add_to_showcmd(nc);
6031 #endif
6032 	if (nc == 'x' || nc == 'X')
6033 	    hex = TRUE;
6034 	else if (nc == 'o' || nc == 'O')
6035 	    octal = TRUE;
6036 #ifdef FEAT_MBYTE
6037 	else if (nc == 'u' || nc == 'U')
6038 	    unicode = nc;
6039 #endif
6040 	else
6041 	{
6042 	    if (hex
6043 #ifdef FEAT_MBYTE
6044 		    || unicode != 0
6045 #endif
6046 		    )
6047 	    {
6048 		if (!vim_isxdigit(nc))
6049 		    break;
6050 		cc = cc * 16 + hex2nr(nc);
6051 	    }
6052 	    else if (octal)
6053 	    {
6054 		if (nc < '0' || nc > '7')
6055 		    break;
6056 		cc = cc * 8 + nc - '0';
6057 	    }
6058 	    else
6059 	    {
6060 		if (!VIM_ISDIGIT(nc))
6061 		    break;
6062 		cc = cc * 10 + nc - '0';
6063 	    }
6064 
6065 	    ++i;
6066 	}
6067 
6068 	if (cc > 255
6069 #ifdef FEAT_MBYTE
6070 		&& unicode == 0
6071 #endif
6072 		)
6073 	    cc = 255;		/* limit range to 0-255 */
6074 	nc = 0;
6075 
6076 	if (hex)		/* hex: up to two chars */
6077 	{
6078 	    if (i >= 2)
6079 		break;
6080 	}
6081 #ifdef FEAT_MBYTE
6082 	else if (unicode)	/* Unicode: up to four or eight chars */
6083 	{
6084 	    if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8))
6085 		break;
6086 	}
6087 #endif
6088 	else if (i >= 3)	/* decimal or octal: up to three chars */
6089 	    break;
6090     }
6091     if (i == 0)	    /* no number entered */
6092     {
6093 	if (nc == K_ZERO)   /* NUL is stored as NL */
6094 	{
6095 	    cc = '\n';
6096 	    nc = 0;
6097 	}
6098 	else
6099 	{
6100 	    cc = nc;
6101 	    nc = 0;
6102 	}
6103     }
6104 
6105     if (cc == 0)	/* NUL is stored as NL */
6106 	cc = '\n';
6107 #ifdef FEAT_MBYTE
6108     if (enc_dbcs && (cc & 0xff) == 0)
6109 	cc = '?';	/* don't accept an illegal DBCS char, the NUL in the
6110 			   second byte will cause trouble! */
6111 #endif
6112 
6113     --no_mapping;
6114 #ifdef FEAT_GUI
6115     if (gui.in_use)
6116 	--allow_keys;
6117 #endif
6118     if (nc)
6119 	vungetc(nc);
6120     got_int = FALSE;	    /* CTRL-C typed after CTRL-V is not an interrupt */
6121     return cc;
6122 }
6123 
6124 /*
6125  * Insert character, taking care of special keys and mod_mask
6126  */
6127     static void
6128 insert_special(
6129     int	    c,
6130     int	    allow_modmask,
6131     int	    ctrlv)	    /* c was typed after CTRL-V */
6132 {
6133     char_u  *p;
6134     int	    len;
6135 
6136     /*
6137      * Special function key, translate into "<Key>". Up to the last '>' is
6138      * inserted with ins_str(), so as not to replace characters in replace
6139      * mode.
6140      * Only use mod_mask for special keys, to avoid things like <S-Space>,
6141      * unless 'allow_modmask' is TRUE.
6142      */
6143 #ifdef MACOS_X
6144     /* Command-key never produces a normal key */
6145     if (mod_mask & MOD_MASK_CMD)
6146 	allow_modmask = TRUE;
6147 #endif
6148     if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
6149     {
6150 	p = get_special_key_name(c, mod_mask);
6151 	len = (int)STRLEN(p);
6152 	c = p[len - 1];
6153 	if (len > 2)
6154 	{
6155 	    if (stop_arrow() == FAIL)
6156 		return;
6157 	    p[len - 1] = NUL;
6158 	    ins_str(p);
6159 	    AppendToRedobuffLit(p, -1);
6160 	    ctrlv = FALSE;
6161 	}
6162     }
6163     if (stop_arrow() == OK)
6164 	insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1);
6165 }
6166 
6167 /*
6168  * Special characters in this context are those that need processing other
6169  * than the simple insertion that can be performed here. This includes ESC
6170  * which terminates the insert, and CR/NL which need special processing to
6171  * open up a new line. This routine tries to optimize insertions performed by
6172  * the "redo", "undo" or "put" commands, so it needs to know when it should
6173  * stop and defer processing to the "normal" mechanism.
6174  * '0' and '^' are special, because they can be followed by CTRL-D.
6175  */
6176 #ifdef EBCDIC
6177 # define ISSPECIAL(c)	((c) < ' ' || (c) == '0' || (c) == '^')
6178 #else
6179 # define ISSPECIAL(c)	((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
6180 #endif
6181 
6182 #ifdef FEAT_MBYTE
6183 # define WHITECHAR(cc) (VIM_ISWHITE(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
6184 #else
6185 # define WHITECHAR(cc) VIM_ISWHITE(cc)
6186 #endif
6187 
6188 /*
6189  * "flags": INSCHAR_FORMAT - force formatting
6190  *	    INSCHAR_CTRLV  - char typed just after CTRL-V
6191  *	    INSCHAR_NO_FEX - don't use 'formatexpr'
6192  *
6193  *   NOTE: passes the flags value straight through to internal_format() which,
6194  *	   beside INSCHAR_FORMAT (above), is also looking for these:
6195  *	    INSCHAR_DO_COM   - format comments
6196  *	    INSCHAR_COM_LIST - format comments with num list or 2nd line indent
6197  */
6198     void
6199 insertchar(
6200     int		c,			/* character to insert or NUL */
6201     int		flags,			/* INSCHAR_FORMAT, etc. */
6202     int		second_indent)		/* indent for second line if >= 0 */
6203 {
6204     int		textwidth;
6205 #ifdef FEAT_COMMENTS
6206     char_u	*p;
6207 #endif
6208     int		fo_ins_blank;
6209     int		force_format = flags & INSCHAR_FORMAT;
6210 
6211     textwidth = comp_textwidth(force_format);
6212     fo_ins_blank = has_format_option(FO_INS_BLANK);
6213 
6214     /*
6215      * Try to break the line in two or more pieces when:
6216      * - Always do this if we have been called to do formatting only.
6217      * - Always do this when 'formatoptions' has the 'a' flag and the line
6218      *   ends in white space.
6219      * - Otherwise:
6220      *	 - Don't do this if inserting a blank
6221      *	 - Don't do this if an existing character is being replaced, unless
6222      *	   we're in VREPLACE mode.
6223      *	 - Do this if the cursor is not on the line where insert started
6224      *	 or - 'formatoptions' doesn't have 'l' or the line was not too long
6225      *	       before the insert.
6226      *	    - 'formatoptions' doesn't have 'b' or a blank was inserted at or
6227      *	      before 'textwidth'
6228      */
6229     if (textwidth > 0
6230 	    && (force_format
6231 		|| (!VIM_ISWHITE(c)
6232 		    && !((State & REPLACE_FLAG)
6233 			&& !(State & VREPLACE_FLAG)
6234 			&& *ml_get_cursor() != NUL)
6235 		    && (curwin->w_cursor.lnum != Insstart.lnum
6236 			|| ((!has_format_option(FO_INS_LONG)
6237 				|| Insstart_textlen <= (colnr_T)textwidth)
6238 			    && (!fo_ins_blank
6239 				|| Insstart_blank_vcol <= (colnr_T)textwidth
6240 			    ))))))
6241     {
6242 	/* Format with 'formatexpr' when it's set.  Use internal formatting
6243 	 * when 'formatexpr' isn't set or it returns non-zero. */
6244 #if defined(FEAT_EVAL)
6245 	int     do_internal = TRUE;
6246 	colnr_T virtcol = get_nolist_virtcol()
6247 				  + char2cells(c != NUL ? c : gchar_cursor());
6248 
6249 	if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0
6250 		&& (force_format || virtcol > (colnr_T)textwidth))
6251 	{
6252 	    do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0);
6253 	    /* It may be required to save for undo again, e.g. when setline()
6254 	     * was called. */
6255 	    ins_need_undo = TRUE;
6256 	}
6257 	if (do_internal)
6258 #endif
6259 	    internal_format(textwidth, second_indent, flags, c == NUL, c);
6260     }
6261 
6262     if (c == NUL)	    /* only formatting was wanted */
6263 	return;
6264 
6265 #ifdef FEAT_COMMENTS
6266     /* Check whether this character should end a comment. */
6267     if (did_ai && (int)c == end_comment_pending)
6268     {
6269 	char_u  *line;
6270 	char_u	lead_end[COM_MAX_LEN];	    /* end-comment string */
6271 	int	middle_len, end_len;
6272 	int	i;
6273 
6274 	/*
6275 	 * Need to remove existing (middle) comment leader and insert end
6276 	 * comment leader.  First, check what comment leader we can find.
6277 	 */
6278 	i = get_leader_len(line = ml_get_curline(), &p, FALSE, TRUE);
6279 	if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL)	/* Just checking */
6280 	{
6281 	    /* Skip middle-comment string */
6282 	    while (*p && p[-1] != ':')	/* find end of middle flags */
6283 		++p;
6284 	    middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
6285 	    /* Don't count trailing white space for middle_len */
6286 	    while (middle_len > 0 && VIM_ISWHITE(lead_end[middle_len - 1]))
6287 		--middle_len;
6288 
6289 	    /* Find the end-comment string */
6290 	    while (*p && p[-1] != ':')	/* find end of end flags */
6291 		++p;
6292 	    end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
6293 
6294 	    /* Skip white space before the cursor */
6295 	    i = curwin->w_cursor.col;
6296 	    while (--i >= 0 && VIM_ISWHITE(line[i]))
6297 		;
6298 	    i++;
6299 
6300 	    /* Skip to before the middle leader */
6301 	    i -= middle_len;
6302 
6303 	    /* Check some expected things before we go on */
6304 	    if (i >= 0 && lead_end[end_len - 1] == end_comment_pending)
6305 	    {
6306 		/* Backspace over all the stuff we want to replace */
6307 		backspace_until_column(i);
6308 
6309 		/*
6310 		 * Insert the end-comment string, except for the last
6311 		 * character, which will get inserted as normal later.
6312 		 */
6313 		ins_bytes_len(lead_end, end_len - 1);
6314 	    }
6315 	}
6316     }
6317     end_comment_pending = NUL;
6318 #endif
6319 
6320     did_ai = FALSE;
6321 #ifdef FEAT_SMARTINDENT
6322     did_si = FALSE;
6323     can_si = FALSE;
6324     can_si_back = FALSE;
6325 #endif
6326 
6327     /*
6328      * If there's any pending input, grab up to INPUT_BUFLEN at once.
6329      * This speeds up normal text input considerably.
6330      * Don't do this when 'cindent' or 'indentexpr' is set, because we might
6331      * need to re-indent at a ':', or any other character (but not what
6332      * 'paste' is set)..
6333      * Don't do this when there an InsertCharPre autocommand is defined,
6334      * because we need to fire the event for every character.
6335      * Do the check for InsertCharPre before the call to vpeekc() because the
6336      * InsertCharPre autocommand could change the input buffer.
6337      */
6338 #ifdef USE_ON_FLY_SCROLL
6339     dont_scroll = FALSE;		/* allow scrolling here */
6340 #endif
6341 
6342     if (       !ISSPECIAL(c)
6343 #ifdef FEAT_MBYTE
6344 	    && (!has_mbyte || (*mb_char2len)(c) == 1)
6345 #endif
6346 	    && !has_insertcharpre()
6347 	    && vpeekc() != NUL
6348 	    && !(State & REPLACE_FLAG)
6349 #ifdef FEAT_CINDENT
6350 	    && !cindent_on()
6351 #endif
6352 #ifdef FEAT_RIGHTLEFT
6353 	    && !p_ri
6354 #endif
6355 	   )
6356     {
6357 #define INPUT_BUFLEN 100
6358 	char_u		buf[INPUT_BUFLEN + 1];
6359 	int		i;
6360 	colnr_T		virtcol = 0;
6361 
6362 	buf[0] = c;
6363 	i = 1;
6364 	if (textwidth > 0)
6365 	    virtcol = get_nolist_virtcol();
6366 	/*
6367 	 * Stop the string when:
6368 	 * - no more chars available
6369 	 * - finding a special character (command key)
6370 	 * - buffer is full
6371 	 * - running into the 'textwidth' boundary
6372 	 * - need to check for abbreviation: A non-word char after a word-char
6373 	 */
6374 	while (	   (c = vpeekc()) != NUL
6375 		&& !ISSPECIAL(c)
6376 #ifdef FEAT_MBYTE
6377 		&& (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
6378 #endif
6379 		&& i < INPUT_BUFLEN
6380 # ifdef FEAT_FKMAP
6381 		&& !(p_fkmap && KeyTyped) /* Farsi mode mapping moves cursor */
6382 # endif
6383 		&& (textwidth == 0
6384 		    || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
6385 		&& !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
6386 	{
6387 #ifdef FEAT_RIGHTLEFT
6388 	    c = vgetc();
6389 	    if (p_hkmap && KeyTyped)
6390 		c = hkmap(c);		    /* Hebrew mode mapping */
6391 	    buf[i++] = c;
6392 #else
6393 	    buf[i++] = vgetc();
6394 #endif
6395 	}
6396 
6397 #ifdef FEAT_DIGRAPHS
6398 	do_digraph(-1);			/* clear digraphs */
6399 	do_digraph(buf[i-1]);		/* may be the start of a digraph */
6400 #endif
6401 	buf[i] = NUL;
6402 	ins_str(buf);
6403 	if (flags & INSCHAR_CTRLV)
6404 	{
6405 	    redo_literal(*buf);
6406 	    i = 1;
6407 	}
6408 	else
6409 	    i = 0;
6410 	if (buf[i] != NUL)
6411 	    AppendToRedobuffLit(buf + i, -1);
6412     }
6413     else
6414     {
6415 #ifdef FEAT_MBYTE
6416 	int		cc;
6417 
6418 	if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
6419 	{
6420 	    char_u	buf[MB_MAXBYTES + 1];
6421 
6422 	    (*mb_char2bytes)(c, buf);
6423 	    buf[cc] = NUL;
6424 	    ins_char_bytes(buf, cc);
6425 	    AppendCharToRedobuff(c);
6426 	}
6427 	else
6428 #endif
6429 	{
6430 	    ins_char(c);
6431 	    if (flags & INSCHAR_CTRLV)
6432 		redo_literal(c);
6433 	    else
6434 		AppendCharToRedobuff(c);
6435 	}
6436     }
6437 }
6438 
6439 /*
6440  * Format text at the current insert position.
6441  *
6442  * If the INSCHAR_COM_LIST flag is present, then the value of second_indent
6443  * will be the comment leader length sent to open_line().
6444  */
6445     static void
6446 internal_format(
6447     int		textwidth,
6448     int		second_indent,
6449     int		flags,
6450     int		format_only,
6451     int		c) /* character to be inserted (can be NUL) */
6452 {
6453     int		cc;
6454     int		save_char = NUL;
6455     int		haveto_redraw = FALSE;
6456     int		fo_ins_blank = has_format_option(FO_INS_BLANK);
6457 #ifdef FEAT_MBYTE
6458     int		fo_multibyte = has_format_option(FO_MBYTE_BREAK);
6459 #endif
6460     int		fo_white_par = has_format_option(FO_WHITE_PAR);
6461     int		first_line = TRUE;
6462 #ifdef FEAT_COMMENTS
6463     colnr_T	leader_len;
6464     int		no_leader = FALSE;
6465     int		do_comments = (flags & INSCHAR_DO_COM);
6466 #endif
6467 #ifdef FEAT_LINEBREAK
6468     int		has_lbr = curwin->w_p_lbr;
6469 
6470     /* make sure win_lbr_chartabsize() counts correctly */
6471     curwin->w_p_lbr = FALSE;
6472 #endif
6473 
6474     /*
6475      * When 'ai' is off we don't want a space under the cursor to be
6476      * deleted.  Replace it with an 'x' temporarily.
6477      */
6478     if (!curbuf->b_p_ai && !(State & VREPLACE_FLAG))
6479     {
6480 	cc = gchar_cursor();
6481 	if (VIM_ISWHITE(cc))
6482 	{
6483 	    save_char = cc;
6484 	    pchar_cursor('x');
6485 	}
6486     }
6487 
6488     /*
6489      * Repeat breaking lines, until the current line is not too long.
6490      */
6491     while (!got_int)
6492     {
6493 	int	startcol;		/* Cursor column at entry */
6494 	int	wantcol;		/* column at textwidth border */
6495 	int	foundcol;		/* column for start of spaces */
6496 	int	end_foundcol = 0;	/* column for start of word */
6497 	colnr_T	len;
6498 	colnr_T	virtcol;
6499 	int	orig_col = 0;
6500 	char_u	*saved_text = NULL;
6501 	colnr_T	col;
6502 	colnr_T	end_col;
6503 	int	wcc;			// counter for whitespace chars
6504 
6505 	virtcol = get_nolist_virtcol()
6506 		+ char2cells(c != NUL ? c : gchar_cursor());
6507 	if (virtcol <= (colnr_T)textwidth)
6508 	    break;
6509 
6510 #ifdef FEAT_COMMENTS
6511 	if (no_leader)
6512 	    do_comments = FALSE;
6513 	else if (!(flags & INSCHAR_FORMAT)
6514 				       && has_format_option(FO_WRAP_COMS))
6515 	    do_comments = TRUE;
6516 
6517 	/* Don't break until after the comment leader */
6518 	if (do_comments)
6519 	    leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE);
6520 	else
6521 	    leader_len = 0;
6522 
6523 	/* If the line doesn't start with a comment leader, then don't
6524 	 * start one in a following broken line.  Avoids that a %word
6525 	 * moved to the start of the next line causes all following lines
6526 	 * to start with %. */
6527 	if (leader_len == 0)
6528 	    no_leader = TRUE;
6529 #endif
6530 	if (!(flags & INSCHAR_FORMAT)
6531 #ifdef FEAT_COMMENTS
6532 		&& leader_len == 0
6533 #endif
6534 		&& !has_format_option(FO_WRAP))
6535 
6536 	    break;
6537 	if ((startcol = curwin->w_cursor.col) == 0)
6538 	    break;
6539 
6540 	/* find column of textwidth border */
6541 	coladvance((colnr_T)textwidth);
6542 	wantcol = curwin->w_cursor.col;
6543 
6544 	curwin->w_cursor.col = startcol;
6545 	foundcol = 0;
6546 
6547 	/*
6548 	 * Find position to break at.
6549 	 * Stop at first entered white when 'formatoptions' has 'v'
6550 	 */
6551 	while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
6552 		    || (flags & INSCHAR_FORMAT)
6553 		    || curwin->w_cursor.lnum != Insstart.lnum
6554 		    || curwin->w_cursor.col >= Insstart.col)
6555 	{
6556 	    if (curwin->w_cursor.col == startcol && c != NUL)
6557 		cc = c;
6558 	    else
6559 		cc = gchar_cursor();
6560 	    if (WHITECHAR(cc))
6561 	    {
6562 		/* remember position of blank just before text */
6563 		end_col = curwin->w_cursor.col;
6564 
6565 		// find start of sequence of blanks
6566 		wcc = 0;
6567 		while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
6568 		{
6569 		    dec_cursor();
6570 		    cc = gchar_cursor();
6571 
6572 		    // Increment count of how many whitespace chars in this
6573 		    // group; we only need to know if it's more than one.
6574 		    if (wcc < 2)
6575 		        wcc++;
6576 		}
6577 		if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
6578 		    break;		/* only spaces in front of text */
6579 
6580 		// Don't break after a period when 'formatoptions' has 'p' and
6581 		// there are less than two spaces.
6582 		if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2)
6583 		    continue;
6584 
6585 #ifdef FEAT_COMMENTS
6586 		/* Don't break until after the comment leader */
6587 		if (curwin->w_cursor.col < leader_len)
6588 		    break;
6589 #endif
6590 		if (has_format_option(FO_ONE_LETTER))
6591 		{
6592 		    /* do not break after one-letter words */
6593 		    if (curwin->w_cursor.col == 0)
6594 			break;	/* one-letter word at begin */
6595 #ifdef FEAT_COMMENTS
6596 		    /* do not break "#a b" when 'tw' is 2 */
6597 		    if (curwin->w_cursor.col <= leader_len)
6598 			break;
6599 #endif
6600 		    col = curwin->w_cursor.col;
6601 		    dec_cursor();
6602 		    cc = gchar_cursor();
6603 
6604 		    if (WHITECHAR(cc))
6605 			continue;	/* one-letter, continue */
6606 		    curwin->w_cursor.col = col;
6607 		}
6608 
6609 		inc_cursor();
6610 
6611 		end_foundcol = end_col + 1;
6612 		foundcol = curwin->w_cursor.col;
6613 		if (curwin->w_cursor.col <= (colnr_T)wantcol)
6614 		    break;
6615 	    }
6616 #ifdef FEAT_MBYTE
6617 	    else if (cc >= 0x100 && fo_multibyte)
6618 	    {
6619 		/* Break after or before a multi-byte character. */
6620 		if (curwin->w_cursor.col != startcol)
6621 		{
6622 #ifdef FEAT_COMMENTS
6623 		    /* Don't break until after the comment leader */
6624 		    if (curwin->w_cursor.col < leader_len)
6625 			break;
6626 #endif
6627 		    col = curwin->w_cursor.col;
6628 		    inc_cursor();
6629 		    /* Don't change end_foundcol if already set. */
6630 		    if (foundcol != curwin->w_cursor.col)
6631 		    {
6632 			foundcol = curwin->w_cursor.col;
6633 			end_foundcol = foundcol;
6634 			if (curwin->w_cursor.col <= (colnr_T)wantcol)
6635 			    break;
6636 		    }
6637 		    curwin->w_cursor.col = col;
6638 		}
6639 
6640 		if (curwin->w_cursor.col == 0)
6641 		    break;
6642 
6643 		col = curwin->w_cursor.col;
6644 
6645 		dec_cursor();
6646 		cc = gchar_cursor();
6647 
6648 		if (WHITECHAR(cc))
6649 		    continue;		/* break with space */
6650 #ifdef FEAT_COMMENTS
6651 		/* Don't break until after the comment leader */
6652 		if (curwin->w_cursor.col < leader_len)
6653 		    break;
6654 #endif
6655 
6656 		curwin->w_cursor.col = col;
6657 
6658 		foundcol = curwin->w_cursor.col;
6659 		end_foundcol = foundcol;
6660 		if (curwin->w_cursor.col <= (colnr_T)wantcol)
6661 		    break;
6662 	    }
6663 #endif
6664 	    if (curwin->w_cursor.col == 0)
6665 		break;
6666 	    dec_cursor();
6667 	}
6668 
6669 	if (foundcol == 0)		/* no spaces, cannot break line */
6670 	{
6671 	    curwin->w_cursor.col = startcol;
6672 	    break;
6673 	}
6674 
6675 	/* Going to break the line, remove any "$" now. */
6676 	undisplay_dollar();
6677 
6678 	/*
6679 	 * Offset between cursor position and line break is used by replace
6680 	 * stack functions.  VREPLACE does not use this, and backspaces
6681 	 * over the text instead.
6682 	 */
6683 	if (State & VREPLACE_FLAG)
6684 	    orig_col = startcol;	/* Will start backspacing from here */
6685 	else
6686 	    replace_offset = startcol - end_foundcol;
6687 
6688 	/*
6689 	 * adjust startcol for spaces that will be deleted and
6690 	 * characters that will remain on top line
6691 	 */
6692 	curwin->w_cursor.col = foundcol;
6693 	while ((cc = gchar_cursor(), WHITECHAR(cc))
6694 		    && (!fo_white_par || curwin->w_cursor.col < startcol))
6695 	    inc_cursor();
6696 	startcol -= curwin->w_cursor.col;
6697 	if (startcol < 0)
6698 	    startcol = 0;
6699 
6700 	if (State & VREPLACE_FLAG)
6701 	{
6702 	    /*
6703 	     * In VREPLACE mode, we will backspace over the text to be
6704 	     * wrapped, so save a copy now to put on the next line.
6705 	     */
6706 	    saved_text = vim_strsave(ml_get_cursor());
6707 	    curwin->w_cursor.col = orig_col;
6708 	    if (saved_text == NULL)
6709 		break;	/* Can't do it, out of memory */
6710 	    saved_text[startcol] = NUL;
6711 
6712 	    /* Backspace over characters that will move to the next line */
6713 	    if (!fo_white_par)
6714 		backspace_until_column(foundcol);
6715 	}
6716 	else
6717 	{
6718 	    /* put cursor after pos. to break line */
6719 	    if (!fo_white_par)
6720 		curwin->w_cursor.col = foundcol;
6721 	}
6722 
6723 	/*
6724 	 * Split the line just before the margin.
6725 	 * Only insert/delete lines, but don't really redraw the window.
6726 	 */
6727 	open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
6728 		+ (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
6729 #ifdef FEAT_COMMENTS
6730 		+ (do_comments ? OPENLINE_DO_COM : 0)
6731 		+ ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0)
6732 #endif
6733 		, ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent));
6734 	if (!(flags & INSCHAR_COM_LIST))
6735 	    old_indent = 0;
6736 
6737 	replace_offset = 0;
6738 	if (first_line)
6739 	{
6740 	    if (!(flags & INSCHAR_COM_LIST))
6741 	    {
6742 		/*
6743 		 * This section is for auto-wrap of numeric lists.  When not
6744 		 * in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
6745 		 * flag will be set and open_line() will handle it (as seen
6746 		 * above).  The code here (and in get_number_indent()) will
6747 		 * recognize comments if needed...
6748 		 */
6749 		if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
6750 		    second_indent =
6751 				 get_number_indent(curwin->w_cursor.lnum - 1);
6752 		if (second_indent >= 0)
6753 		{
6754 		    if (State & VREPLACE_FLAG)
6755 			change_indent(INDENT_SET, second_indent,
6756 							    FALSE, NUL, TRUE);
6757 		    else
6758 #ifdef FEAT_COMMENTS
6759 			if (leader_len > 0 && second_indent - leader_len > 0)
6760 		    {
6761 			int i;
6762 			int padding = second_indent - leader_len;
6763 
6764 			/* We started at the first_line of a numbered list
6765 			 * that has a comment.  the open_line() function has
6766 			 * inserted the proper comment leader and positioned
6767 			 * the cursor at the end of the split line.  Now we
6768 			 * add the additional whitespace needed after the
6769 			 * comment leader for the numbered list.  */
6770 			for (i = 0; i < padding; i++)
6771 			    ins_str((char_u *)" ");
6772 		    }
6773 		    else
6774 		    {
6775 #endif
6776 			(void)set_indent(second_indent, SIN_CHANGED);
6777 #ifdef FEAT_COMMENTS
6778 		    }
6779 #endif
6780 		}
6781 	    }
6782 	    first_line = FALSE;
6783 	}
6784 
6785 	if (State & VREPLACE_FLAG)
6786 	{
6787 	    /*
6788 	     * In VREPLACE mode we have backspaced over the text to be
6789 	     * moved, now we re-insert it into the new line.
6790 	     */
6791 	    ins_bytes(saved_text);
6792 	    vim_free(saved_text);
6793 	}
6794 	else
6795 	{
6796 	    /*
6797 	     * Check if cursor is not past the NUL off the line, cindent
6798 	     * may have added or removed indent.
6799 	     */
6800 	    curwin->w_cursor.col += startcol;
6801 	    len = (colnr_T)STRLEN(ml_get_curline());
6802 	    if (curwin->w_cursor.col > len)
6803 		curwin->w_cursor.col = len;
6804 	}
6805 
6806 	haveto_redraw = TRUE;
6807 #ifdef FEAT_CINDENT
6808 	can_cindent = TRUE;
6809 #endif
6810 	/* moved the cursor, don't autoindent or cindent now */
6811 	did_ai = FALSE;
6812 #ifdef FEAT_SMARTINDENT
6813 	did_si = FALSE;
6814 	can_si = FALSE;
6815 	can_si_back = FALSE;
6816 #endif
6817 	line_breakcheck();
6818     }
6819 
6820     if (save_char != NUL)		/* put back space after cursor */
6821 	pchar_cursor(save_char);
6822 
6823 #ifdef FEAT_LINEBREAK
6824     curwin->w_p_lbr = has_lbr;
6825 #endif
6826     if (!format_only && haveto_redraw)
6827     {
6828 	update_topline();
6829 	redraw_curbuf_later(VALID);
6830     }
6831 }
6832 
6833 /*
6834  * Called after inserting or deleting text: When 'formatoptions' includes the
6835  * 'a' flag format from the current line until the end of the paragraph.
6836  * Keep the cursor at the same position relative to the text.
6837  * The caller must have saved the cursor line for undo, following ones will be
6838  * saved here.
6839  */
6840     void
6841 auto_format(
6842     int		trailblank,	/* when TRUE also format with trailing blank */
6843     int		prev_line)	/* may start in previous line */
6844 {
6845     pos_T	pos;
6846     colnr_T	len;
6847     char_u	*old;
6848     char_u	*new, *pnew;
6849     int		wasatend;
6850     int		cc;
6851 
6852     if (!has_format_option(FO_AUTO))
6853 	return;
6854 
6855     pos = curwin->w_cursor;
6856     old = ml_get_curline();
6857 
6858     /* may remove added space */
6859     check_auto_format(FALSE);
6860 
6861     /* Don't format in Insert mode when the cursor is on a trailing blank, the
6862      * user might insert normal text next.  Also skip formatting when "1" is
6863      * in 'formatoptions' and there is a single character before the cursor.
6864      * Otherwise the line would be broken and when typing another non-white
6865      * next they are not joined back together. */
6866     wasatend = (pos.col == (colnr_T)STRLEN(old));
6867     if (*old != NUL && !trailblank && wasatend)
6868     {
6869 	dec_cursor();
6870 	cc = gchar_cursor();
6871 	if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
6872 					  && has_format_option(FO_ONE_LETTER))
6873 	    dec_cursor();
6874 	cc = gchar_cursor();
6875 	if (WHITECHAR(cc))
6876 	{
6877 	    curwin->w_cursor = pos;
6878 	    return;
6879 	}
6880 	curwin->w_cursor = pos;
6881     }
6882 
6883 #ifdef FEAT_COMMENTS
6884     /* With the 'c' flag in 'formatoptions' and 't' missing: only format
6885      * comments. */
6886     if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
6887 				     && get_leader_len(old, NULL, FALSE, TRUE) == 0)
6888 	return;
6889 #endif
6890 
6891     /*
6892      * May start formatting in a previous line, so that after "x" a word is
6893      * moved to the previous line if it fits there now.  Only when this is not
6894      * the start of a paragraph.
6895      */
6896     if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
6897     {
6898 	--curwin->w_cursor.lnum;
6899 	if (u_save_cursor() == FAIL)
6900 	    return;
6901     }
6902 
6903     /*
6904      * Do the formatting and restore the cursor position.  "saved_cursor" will
6905      * be adjusted for the text formatting.
6906      */
6907     saved_cursor = pos;
6908     format_lines((linenr_T)-1, FALSE);
6909     curwin->w_cursor = saved_cursor;
6910     saved_cursor.lnum = 0;
6911 
6912     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
6913     {
6914 	/* "cannot happen" */
6915 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
6916 	coladvance((colnr_T)MAXCOL);
6917     }
6918     else
6919 	check_cursor_col();
6920 
6921     /* Insert mode: If the cursor is now after the end of the line while it
6922      * previously wasn't, the line was broken.  Because of the rule above we
6923      * need to add a space when 'w' is in 'formatoptions' to keep a paragraph
6924      * formatted. */
6925     if (!wasatend && has_format_option(FO_WHITE_PAR))
6926     {
6927 	new = ml_get_curline();
6928 	len = (colnr_T)STRLEN(new);
6929 	if (curwin->w_cursor.col == len)
6930 	{
6931 	    pnew = vim_strnsave(new, len + 2);
6932 	    pnew[len] = ' ';
6933 	    pnew[len + 1] = NUL;
6934 	    ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
6935 	    /* remove the space later */
6936 	    did_add_space = TRUE;
6937 	}
6938 	else
6939 	    /* may remove added space */
6940 	    check_auto_format(FALSE);
6941     }
6942 
6943     check_cursor();
6944 }
6945 
6946 /*
6947  * When an extra space was added to continue a paragraph for auto-formatting,
6948  * delete it now.  The space must be under the cursor, just after the insert
6949  * position.
6950  */
6951     static void
6952 check_auto_format(
6953     int		end_insert)	    /* TRUE when ending Insert mode */
6954 {
6955     int		c = ' ';
6956     int		cc;
6957 
6958     if (did_add_space)
6959     {
6960 	cc = gchar_cursor();
6961 	if (!WHITECHAR(cc))
6962 	    /* Somehow the space was removed already. */
6963 	    did_add_space = FALSE;
6964 	else
6965 	{
6966 	    if (!end_insert)
6967 	    {
6968 		inc_cursor();
6969 		c = gchar_cursor();
6970 		dec_cursor();
6971 	    }
6972 	    if (c != NUL)
6973 	    {
6974 		/* The space is no longer at the end of the line, delete it. */
6975 		del_char(FALSE);
6976 		did_add_space = FALSE;
6977 	    }
6978 	}
6979     }
6980 }
6981 
6982 /*
6983  * Find out textwidth to be used for formatting:
6984  *	if 'textwidth' option is set, use it
6985  *	else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
6986  *	if invalid value, use 0.
6987  *	Set default to window width (maximum 79) for "gq" operator.
6988  */
6989     int
6990 comp_textwidth(
6991     int		ff)	/* force formatting (for "gq" command) */
6992 {
6993     int		textwidth;
6994 
6995     textwidth = curbuf->b_p_tw;
6996     if (textwidth == 0 && curbuf->b_p_wm)
6997     {
6998 	/* The width is the window width minus 'wrapmargin' minus all the
6999 	 * things that add to the margin. */
7000 	textwidth = curwin->w_width - curbuf->b_p_wm;
7001 #ifdef FEAT_CMDWIN
7002 	if (cmdwin_type != 0)
7003 	    textwidth -= 1;
7004 #endif
7005 #ifdef FEAT_FOLDING
7006 	textwidth -= curwin->w_p_fdc;
7007 #endif
7008 #ifdef FEAT_SIGNS
7009 	if (signcolumn_on(curwin))
7010 	    textwidth -= 1;
7011 #endif
7012 	if (curwin->w_p_nu || curwin->w_p_rnu)
7013 	    textwidth -= 8;
7014     }
7015     if (textwidth < 0)
7016 	textwidth = 0;
7017     if (ff && textwidth == 0)
7018     {
7019 	textwidth = curwin->w_width - 1;
7020 	if (textwidth > 79)
7021 	    textwidth = 79;
7022     }
7023     return textwidth;
7024 }
7025 
7026 /*
7027  * Put a character in the redo buffer, for when just after a CTRL-V.
7028  */
7029     static void
7030 redo_literal(int c)
7031 {
7032     char_u	buf[10];
7033 
7034     /* Only digits need special treatment.  Translate them into a string of
7035      * three digits. */
7036     if (VIM_ISDIGIT(c))
7037     {
7038 	vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
7039 	AppendToRedobuff(buf);
7040     }
7041     else
7042 	AppendCharToRedobuff(c);
7043 }
7044 
7045 /*
7046  * start_arrow() is called when an arrow key is used in insert mode.
7047  * For undo/redo it resembles hitting the <ESC> key.
7048  */
7049     static void
7050 start_arrow(
7051     pos_T    *end_insert_pos)		/* can be NULL */
7052 {
7053     start_arrow_common(end_insert_pos, TRUE);
7054 }
7055 
7056 /*
7057  * Like start_arrow() but with end_change argument.
7058  * Will prepare for redo of CTRL-G U if "end_change" is FALSE.
7059  */
7060     static void
7061 start_arrow_with_change(
7062     pos_T    *end_insert_pos,		/* can be NULL */
7063     int	      end_change)		/* end undoable change */
7064 {
7065     start_arrow_common(end_insert_pos, end_change);
7066     if (!end_change)
7067     {
7068 	AppendCharToRedobuff(Ctrl_G);
7069 	AppendCharToRedobuff('U');
7070     }
7071 }
7072 
7073     static void
7074 start_arrow_common(
7075     pos_T    *end_insert_pos,		/* can be NULL */
7076     int	      end_change)		/* end undoable change */
7077 {
7078     if (!arrow_used && end_change)	/* something has been inserted */
7079     {
7080 	AppendToRedobuff(ESC_STR);
7081 	stop_insert(end_insert_pos, FALSE, FALSE);
7082 	arrow_used = TRUE;	/* this means we stopped the current insert */
7083     }
7084 #ifdef FEAT_SPELL
7085     check_spell_redraw();
7086 #endif
7087 }
7088 
7089 #ifdef FEAT_SPELL
7090 /*
7091  * If we skipped highlighting word at cursor, do it now.
7092  * It may be skipped again, thus reset spell_redraw_lnum first.
7093  */
7094     static void
7095 check_spell_redraw(void)
7096 {
7097     if (spell_redraw_lnum != 0)
7098     {
7099 	linenr_T	lnum = spell_redraw_lnum;
7100 
7101 	spell_redraw_lnum = 0;
7102 	redrawWinline(curwin, lnum);
7103     }
7104 }
7105 
7106 /*
7107  * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
7108  * spelled word, if there is one.
7109  */
7110     static void
7111 spell_back_to_badword(void)
7112 {
7113     pos_T	tpos = curwin->w_cursor;
7114 
7115     spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
7116     if (curwin->w_cursor.col != tpos.col)
7117 	start_arrow(&tpos);
7118 }
7119 #endif
7120 
7121 /*
7122  * stop_arrow() is called before a change is made in insert mode.
7123  * If an arrow key has been used, start a new insertion.
7124  * Returns FAIL if undo is impossible, shouldn't insert then.
7125  */
7126     int
7127 stop_arrow(void)
7128 {
7129     if (arrow_used)
7130     {
7131 	Insstart = curwin->w_cursor;	/* new insertion starts here */
7132 	if (Insstart.col > Insstart_orig.col && !ins_need_undo)
7133 	    /* Don't update the original insert position when moved to the
7134 	     * right, except when nothing was inserted yet. */
7135 	    update_Insstart_orig = FALSE;
7136 	Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
7137 
7138 	if (u_save_cursor() == OK)
7139 	{
7140 	    arrow_used = FALSE;
7141 	    ins_need_undo = FALSE;
7142 	}
7143 
7144 	ai_col = 0;
7145 	if (State & VREPLACE_FLAG)
7146 	{
7147 	    orig_line_count = curbuf->b_ml.ml_line_count;
7148 	    vr_lines_changed = 1;
7149 	}
7150 	ResetRedobuff();
7151 	AppendToRedobuff((char_u *)"1i");   /* pretend we start an insertion */
7152 	new_insert_skip = 2;
7153     }
7154     else if (ins_need_undo)
7155     {
7156 	if (u_save_cursor() == OK)
7157 	    ins_need_undo = FALSE;
7158     }
7159 
7160 #ifdef FEAT_FOLDING
7161     /* Always open fold at the cursor line when inserting something. */
7162     foldOpenCursor();
7163 #endif
7164 
7165     return (arrow_used || ins_need_undo ? FAIL : OK);
7166 }
7167 
7168 /*
7169  * Do a few things to stop inserting.
7170  * "end_insert_pos" is where insert ended.  It is NULL when we already jumped
7171  * to another window/buffer.
7172  */
7173     static void
7174 stop_insert(
7175     pos_T	*end_insert_pos,
7176     int		esc,			/* called by ins_esc() */
7177     int		nomove)			/* <c-\><c-o>, don't move cursor */
7178 {
7179     int		cc;
7180     char_u	*ptr;
7181 
7182     stop_redo_ins();
7183     replace_flush();		/* abandon replace stack */
7184 
7185     /*
7186      * Save the inserted text for later redo with ^@ and CTRL-A.
7187      * Don't do it when "restart_edit" was set and nothing was inserted,
7188      * otherwise CTRL-O w and then <Left> will clear "last_insert".
7189      */
7190     ptr = get_inserted();
7191     if (did_restart_edit == 0 || (ptr != NULL
7192 				       && (int)STRLEN(ptr) > new_insert_skip))
7193     {
7194 	vim_free(last_insert);
7195 	last_insert = ptr;
7196 	last_insert_skip = new_insert_skip;
7197     }
7198     else
7199 	vim_free(ptr);
7200 
7201     if (!arrow_used && end_insert_pos != NULL)
7202     {
7203 	/* Auto-format now.  It may seem strange to do this when stopping an
7204 	 * insertion (or moving the cursor), but it's required when appending
7205 	 * a line and having it end in a space.  But only do it when something
7206 	 * was actually inserted, otherwise undo won't work. */
7207 	if (!ins_need_undo && has_format_option(FO_AUTO))
7208 	{
7209 	    pos_T   tpos = curwin->w_cursor;
7210 
7211 	    /* When the cursor is at the end of the line after a space the
7212 	     * formatting will move it to the following word.  Avoid that by
7213 	     * moving the cursor onto the space. */
7214 	    cc = 'x';
7215 	    if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL)
7216 	    {
7217 		dec_cursor();
7218 		cc = gchar_cursor();
7219 		if (!VIM_ISWHITE(cc))
7220 		    curwin->w_cursor = tpos;
7221 	    }
7222 
7223 	    auto_format(TRUE, FALSE);
7224 
7225 	    if (VIM_ISWHITE(cc))
7226 	    {
7227 		if (gchar_cursor() != NUL)
7228 		    inc_cursor();
7229 #ifdef FEAT_VIRTUALEDIT
7230 		/* If the cursor is still at the same character, also keep
7231 		 * the "coladd". */
7232 		if (gchar_cursor() == NUL
7233 			&& curwin->w_cursor.lnum == tpos.lnum
7234 			&& curwin->w_cursor.col == tpos.col)
7235 		    curwin->w_cursor.coladd = tpos.coladd;
7236 #endif
7237 	    }
7238 	}
7239 
7240 	/* If a space was inserted for auto-formatting, remove it now. */
7241 	check_auto_format(TRUE);
7242 
7243 	/* If we just did an auto-indent, remove the white space from the end
7244 	 * of the line, and put the cursor back.
7245 	 * Do this when ESC was used or moving the cursor up/down.
7246 	 * Check for the old position still being valid, just in case the text
7247 	 * got changed unexpectedly. */
7248 	if (!nomove && did_ai && (esc || (vim_strchr(p_cpo, CPO_INDENT) == NULL
7249 			&& curwin->w_cursor.lnum != end_insert_pos->lnum))
7250 		&& end_insert_pos->lnum <= curbuf->b_ml.ml_line_count)
7251 	{
7252 	    pos_T	tpos = curwin->w_cursor;
7253 
7254 	    curwin->w_cursor = *end_insert_pos;
7255 	    check_cursor_col();  /* make sure it is not past the line */
7256 	    for (;;)
7257 	    {
7258 		if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
7259 		    --curwin->w_cursor.col;
7260 		cc = gchar_cursor();
7261 		if (!VIM_ISWHITE(cc))
7262 		    break;
7263 		if (del_char(TRUE) == FAIL)
7264 		    break;  /* should not happen */
7265 	    }
7266 	    if (curwin->w_cursor.lnum != tpos.lnum)
7267 		curwin->w_cursor = tpos;
7268 	    else
7269 	    {
7270 		/* reset tpos, could have been invalidated in the loop above */
7271 		tpos = curwin->w_cursor;
7272 		tpos.col++;
7273 		if (cc != NUL && gchar_pos(&tpos) == NUL)
7274 		    ++curwin->w_cursor.col;	/* put cursor back on the NUL */
7275 	    }
7276 
7277 	    /* <C-S-Right> may have started Visual mode, adjust the position for
7278 	     * deleted characters. */
7279 	    if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum)
7280 	    {
7281 		int len = (int)STRLEN(ml_get_curline());
7282 
7283 		if (VIsual.col > len)
7284 		{
7285 		    VIsual.col = len;
7286 #ifdef FEAT_VIRTUALEDIT
7287 		    VIsual.coladd = 0;
7288 #endif
7289 		}
7290 	    }
7291 	}
7292     }
7293     did_ai = FALSE;
7294 #ifdef FEAT_SMARTINDENT
7295     did_si = FALSE;
7296     can_si = FALSE;
7297     can_si_back = FALSE;
7298 #endif
7299 
7300     /* Set '[ and '] to the inserted text.  When end_insert_pos is NULL we are
7301      * now in a different buffer. */
7302     if (end_insert_pos != NULL)
7303     {
7304 	curbuf->b_op_start = Insstart;
7305 	curbuf->b_op_start_orig = Insstart_orig;
7306 	curbuf->b_op_end = *end_insert_pos;
7307     }
7308 }
7309 
7310 /*
7311  * Set the last inserted text to a single character.
7312  * Used for the replace command.
7313  */
7314     void
7315 set_last_insert(int c)
7316 {
7317     char_u	*s;
7318 
7319     vim_free(last_insert);
7320     last_insert = alloc(MB_MAXBYTES * 3 + 5);
7321     if (last_insert != NULL)
7322     {
7323 	s = last_insert;
7324 	/* Use the CTRL-V only when entering a special char */
7325 	if (c < ' ' || c == DEL)
7326 	    *s++ = Ctrl_V;
7327 	s = add_char2buf(c, s);
7328 	*s++ = ESC;
7329 	*s++ = NUL;
7330 	last_insert_skip = 0;
7331     }
7332 }
7333 
7334 #if defined(EXITFREE) || defined(PROTO)
7335     void
7336 free_last_insert(void)
7337 {
7338     VIM_CLEAR(last_insert);
7339 # ifdef FEAT_INS_EXPAND
7340     VIM_CLEAR(compl_orig_text);
7341 # endif
7342 }
7343 #endif
7344 
7345 /*
7346  * Add character "c" to buffer "s".  Escape the special meaning of K_SPECIAL
7347  * and CSI.  Handle multi-byte characters.
7348  * Returns a pointer to after the added bytes.
7349  */
7350     char_u *
7351 add_char2buf(int c, char_u *s)
7352 {
7353 #ifdef FEAT_MBYTE
7354     char_u	temp[MB_MAXBYTES + 1];
7355     int		i;
7356     int		len;
7357 
7358     len = (*mb_char2bytes)(c, temp);
7359     for (i = 0; i < len; ++i)
7360     {
7361 	c = temp[i];
7362 #endif
7363 	/* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */
7364 	if (c == K_SPECIAL)
7365 	{
7366 	    *s++ = K_SPECIAL;
7367 	    *s++ = KS_SPECIAL;
7368 	    *s++ = KE_FILLER;
7369 	}
7370 #ifdef FEAT_GUI
7371 	else if (c == CSI)
7372 	{
7373 	    *s++ = CSI;
7374 	    *s++ = KS_EXTRA;
7375 	    *s++ = (int)KE_CSI;
7376 	}
7377 #endif
7378 	else
7379 	    *s++ = c;
7380 #ifdef FEAT_MBYTE
7381     }
7382 #endif
7383     return s;
7384 }
7385 
7386 /*
7387  * move cursor to start of line
7388  * if flags & BL_WHITE	move to first non-white
7389  * if flags & BL_SOL	move to first non-white if startofline is set,
7390  *			    otherwise keep "curswant" column
7391  * if flags & BL_FIX	don't leave the cursor on a NUL.
7392  */
7393     void
7394 beginline(int flags)
7395 {
7396     if ((flags & BL_SOL) && !p_sol)
7397 	coladvance(curwin->w_curswant);
7398     else
7399     {
7400 	curwin->w_cursor.col = 0;
7401 #ifdef FEAT_VIRTUALEDIT
7402 	curwin->w_cursor.coladd = 0;
7403 #endif
7404 
7405 	if (flags & (BL_WHITE | BL_SOL))
7406 	{
7407 	    char_u  *ptr;
7408 
7409 	    for (ptr = ml_get_curline(); VIM_ISWHITE(*ptr)
7410 			       && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
7411 		++curwin->w_cursor.col;
7412 	}
7413 	curwin->w_set_curswant = TRUE;
7414     }
7415 }
7416 
7417 /*
7418  * oneright oneleft cursor_down cursor_up
7419  *
7420  * Move one char {right,left,down,up}.
7421  * Doesn't move onto the NUL past the end of the line, unless it is allowed.
7422  * Return OK when successful, FAIL when we hit a line of file boundary.
7423  */
7424 
7425     int
7426 oneright(void)
7427 {
7428     char_u	*ptr;
7429     int		l;
7430 
7431 #ifdef FEAT_VIRTUALEDIT
7432     if (virtual_active())
7433     {
7434 	pos_T	prevpos = curwin->w_cursor;
7435 
7436 	/* Adjust for multi-wide char (excluding TAB) */
7437 	ptr = ml_get_cursor();
7438 	coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(
7439 # ifdef FEAT_MBYTE
7440 			    (*mb_ptr2char)(ptr)
7441 # else
7442 			    *ptr
7443 # endif
7444 			    ))
7445 		    ? ptr2cells(ptr) : 1));
7446 	curwin->w_set_curswant = TRUE;
7447 	/* Return OK if the cursor moved, FAIL otherwise (at window edge). */
7448 	return (prevpos.col != curwin->w_cursor.col
7449 		    || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL;
7450     }
7451 #endif
7452 
7453     ptr = ml_get_cursor();
7454     if (*ptr == NUL)
7455 	return FAIL;	    /* already at the very end */
7456 
7457 #ifdef FEAT_MBYTE
7458     if (has_mbyte)
7459 	l = (*mb_ptr2len)(ptr);
7460     else
7461 #endif
7462 	l = 1;
7463 
7464     /* move "l" bytes right, but don't end up on the NUL, unless 'virtualedit'
7465      * contains "onemore". */
7466     if (ptr[l] == NUL
7467 #ifdef FEAT_VIRTUALEDIT
7468 	    && (ve_flags & VE_ONEMORE) == 0
7469 #endif
7470 	    )
7471 	return FAIL;
7472     curwin->w_cursor.col += l;
7473 
7474     curwin->w_set_curswant = TRUE;
7475     return OK;
7476 }
7477 
7478     int
7479 oneleft(void)
7480 {
7481 #ifdef FEAT_VIRTUALEDIT
7482     if (virtual_active())
7483     {
7484 # ifdef FEAT_LINEBREAK
7485 	int width;
7486 # endif
7487 	int v = getviscol();
7488 
7489 	if (v == 0)
7490 	    return FAIL;
7491 
7492 # ifdef FEAT_LINEBREAK
7493 	/* We might get stuck on 'showbreak', skip over it. */
7494 	width = 1;
7495 	for (;;)
7496 	{
7497 	    coladvance(v - width);
7498 	    /* getviscol() is slow, skip it when 'showbreak' is empty,
7499 	     * 'breakindent' is not set and there are no multi-byte
7500 	     * characters */
7501 	    if ((*p_sbr == NUL && !curwin->w_p_bri
7502 #  ifdef FEAT_MBYTE
7503 			&& !has_mbyte
7504 #  endif
7505 			) || getviscol() < v)
7506 		break;
7507 	    ++width;
7508 	}
7509 # else
7510 	coladvance(v - 1);
7511 # endif
7512 
7513 	if (curwin->w_cursor.coladd == 1)
7514 	{
7515 	    char_u *ptr;
7516 
7517 	    /* Adjust for multi-wide char (not a TAB) */
7518 	    ptr = ml_get_cursor();
7519 	    if (*ptr != TAB && vim_isprintc(
7520 #  ifdef FEAT_MBYTE
7521 			    (*mb_ptr2char)(ptr)
7522 #  else
7523 			    *ptr
7524 #  endif
7525 			    ) && ptr2cells(ptr) > 1)
7526 		curwin->w_cursor.coladd = 0;
7527 	}
7528 
7529 	curwin->w_set_curswant = TRUE;
7530 	return OK;
7531     }
7532 #endif
7533 
7534     if (curwin->w_cursor.col == 0)
7535 	return FAIL;
7536 
7537     curwin->w_set_curswant = TRUE;
7538     --curwin->w_cursor.col;
7539 
7540 #ifdef FEAT_MBYTE
7541     /* if the character on the left of the current cursor is a multi-byte
7542      * character, move to its first byte */
7543     if (has_mbyte)
7544 	mb_adjust_cursor();
7545 #endif
7546     return OK;
7547 }
7548 
7549     int
7550 cursor_up(
7551     long	n,
7552     int		upd_topline)	    /* When TRUE: update topline */
7553 {
7554     linenr_T	lnum;
7555 
7556     if (n > 0)
7557     {
7558 	lnum = curwin->w_cursor.lnum;
7559 	/* This fails if the cursor is already in the first line or the count
7560 	 * is larger than the line number and '-' is in 'cpoptions' */
7561 	if (lnum <= 1 || (n >= lnum && vim_strchr(p_cpo, CPO_MINUS) != NULL))
7562 	    return FAIL;
7563 	if (n >= lnum)
7564 	    lnum = 1;
7565 	else
7566 #ifdef FEAT_FOLDING
7567 	    if (hasAnyFolding(curwin))
7568 	{
7569 	    /*
7570 	     * Count each sequence of folded lines as one logical line.
7571 	     */
7572 	    /* go to the start of the current fold */
7573 	    (void)hasFolding(lnum, &lnum, NULL);
7574 
7575 	    while (n--)
7576 	    {
7577 		/* move up one line */
7578 		--lnum;
7579 		if (lnum <= 1)
7580 		    break;
7581 		/* If we entered a fold, move to the beginning, unless in
7582 		 * Insert mode or when 'foldopen' contains "all": it will open
7583 		 * in a moment. */
7584 		if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL)))
7585 		    (void)hasFolding(lnum, &lnum, NULL);
7586 	    }
7587 	    if (lnum < 1)
7588 		lnum = 1;
7589 	}
7590 	else
7591 #endif
7592 	    lnum -= n;
7593 	curwin->w_cursor.lnum = lnum;
7594     }
7595 
7596     /* try to advance to the column we want to be at */
7597     coladvance(curwin->w_curswant);
7598 
7599     if (upd_topline)
7600 	update_topline();	/* make sure curwin->w_topline is valid */
7601 
7602     return OK;
7603 }
7604 
7605 /*
7606  * Cursor down a number of logical lines.
7607  */
7608     int
7609 cursor_down(
7610     long	n,
7611     int		upd_topline)	    /* When TRUE: update topline */
7612 {
7613     linenr_T	lnum;
7614 
7615     if (n > 0)
7616     {
7617 	lnum = curwin->w_cursor.lnum;
7618 #ifdef FEAT_FOLDING
7619 	/* Move to last line of fold, will fail if it's the end-of-file. */
7620 	(void)hasFolding(lnum, NULL, &lnum);
7621 #endif
7622 	/* This fails if the cursor is already in the last line or would move
7623 	 * beyond the last line and '-' is in 'cpoptions' */
7624 	if (lnum >= curbuf->b_ml.ml_line_count
7625 		|| (lnum + n > curbuf->b_ml.ml_line_count
7626 		    && vim_strchr(p_cpo, CPO_MINUS) != NULL))
7627 	    return FAIL;
7628 	if (lnum + n >= curbuf->b_ml.ml_line_count)
7629 	    lnum = curbuf->b_ml.ml_line_count;
7630 	else
7631 #ifdef FEAT_FOLDING
7632 	if (hasAnyFolding(curwin))
7633 	{
7634 	    linenr_T	last;
7635 
7636 	    /* count each sequence of folded lines as one logical line */
7637 	    while (n--)
7638 	    {
7639 		if (hasFolding(lnum, NULL, &last))
7640 		    lnum = last + 1;
7641 		else
7642 		    ++lnum;
7643 		if (lnum >= curbuf->b_ml.ml_line_count)
7644 		    break;
7645 	    }
7646 	    if (lnum > curbuf->b_ml.ml_line_count)
7647 		lnum = curbuf->b_ml.ml_line_count;
7648 	}
7649 	else
7650 #endif
7651 	    lnum += n;
7652 	curwin->w_cursor.lnum = lnum;
7653     }
7654 
7655     /* try to advance to the column we want to be at */
7656     coladvance(curwin->w_curswant);
7657 
7658     if (upd_topline)
7659 	update_topline();	/* make sure curwin->w_topline is valid */
7660 
7661     return OK;
7662 }
7663 
7664 /*
7665  * Stuff the last inserted text in the read buffer.
7666  * Last_insert actually is a copy of the redo buffer, so we
7667  * first have to remove the command.
7668  */
7669     int
7670 stuff_inserted(
7671     int	    c,		/* Command character to be inserted */
7672     long    count,	/* Repeat this many times */
7673     int	    no_esc)	/* Don't add an ESC at the end */
7674 {
7675     char_u	*esc_ptr;
7676     char_u	*ptr;
7677     char_u	*last_ptr;
7678     char_u	last = NUL;
7679 
7680     ptr = get_last_insert();
7681     if (ptr == NULL)
7682     {
7683 	emsg(_(e_noinstext));
7684 	return FAIL;
7685     }
7686 
7687     /* may want to stuff the command character, to start Insert mode */
7688     if (c != NUL)
7689 	stuffcharReadbuff(c);
7690     if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
7691 	*esc_ptr = NUL;	    /* remove the ESC */
7692 
7693     /* when the last char is either "0" or "^" it will be quoted if no ESC
7694      * comes after it OR if it will inserted more than once and "ptr"
7695      * starts with ^D.	-- Acevedo
7696      */
7697     last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
7698     if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
7699 	    && (no_esc || (*ptr == Ctrl_D && count > 1)))
7700     {
7701 	last = *last_ptr;
7702 	*last_ptr = NUL;
7703     }
7704 
7705     do
7706     {
7707 	stuffReadbuff(ptr);
7708 	/* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
7709 	if (last)
7710 	    stuffReadbuff((char_u *)(last == '0'
7711 			? IF_EB("\026\060\064\070", CTRL_V_STR "xf0")
7712 			: IF_EB("\026^", CTRL_V_STR "^")));
7713     }
7714     while (--count > 0);
7715 
7716     if (last)
7717 	*last_ptr = last;
7718 
7719     if (esc_ptr != NULL)
7720 	*esc_ptr = ESC;	    /* put the ESC back */
7721 
7722     /* may want to stuff a trailing ESC, to get out of Insert mode */
7723     if (!no_esc)
7724 	stuffcharReadbuff(ESC);
7725 
7726     return OK;
7727 }
7728 
7729     char_u *
7730 get_last_insert(void)
7731 {
7732     if (last_insert == NULL)
7733 	return NULL;
7734     return last_insert + last_insert_skip;
7735 }
7736 
7737 /*
7738  * Get last inserted string, and remove trailing <Esc>.
7739  * Returns pointer to allocated memory (must be freed) or NULL.
7740  */
7741     char_u *
7742 get_last_insert_save(void)
7743 {
7744     char_u	*s;
7745     int		len;
7746 
7747     if (last_insert == NULL)
7748 	return NULL;
7749     s = vim_strsave(last_insert + last_insert_skip);
7750     if (s != NULL)
7751     {
7752 	len = (int)STRLEN(s);
7753 	if (len > 0 && s[len - 1] == ESC)	/* remove trailing ESC */
7754 	    s[len - 1] = NUL;
7755     }
7756     return s;
7757 }
7758 
7759 /*
7760  * Check the word in front of the cursor for an abbreviation.
7761  * Called when the non-id character "c" has been entered.
7762  * When an abbreviation is recognized it is removed from the text and
7763  * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
7764  */
7765     static int
7766 echeck_abbr(int c)
7767 {
7768     /* Don't check for abbreviation in paste mode, when disabled and just
7769      * after moving around with cursor keys. */
7770     if (p_paste || no_abbr || arrow_used)
7771 	return FALSE;
7772 
7773     return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
7774 		curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
7775 }
7776 
7777 /*
7778  * replace-stack functions
7779  *
7780  * When replacing characters, the replaced characters are remembered for each
7781  * new character.  This is used to re-insert the old text when backspacing.
7782  *
7783  * There is a NUL headed list of characters for each character that is
7784  * currently in the file after the insertion point.  When BS is used, one NUL
7785  * headed list is put back for the deleted character.
7786  *
7787  * For a newline, there are two NUL headed lists.  One contains the characters
7788  * that the NL replaced.  The extra one stores the characters after the cursor
7789  * that were deleted (always white space).
7790  *
7791  * Replace_offset is normally 0, in which case replace_push will add a new
7792  * character at the end of the stack.  If replace_offset is not 0, that many
7793  * characters will be left on the stack above the newly inserted character.
7794  */
7795 
7796 static char_u	*replace_stack = NULL;
7797 static long	replace_stack_nr = 0;	    /* next entry in replace stack */
7798 static long	replace_stack_len = 0;	    /* max. number of entries */
7799 
7800     void
7801 replace_push(
7802     int	    c)	    /* character that is replaced (NUL is none) */
7803 {
7804     char_u  *p;
7805 
7806     if (replace_stack_nr < replace_offset)	/* nothing to do */
7807 	return;
7808     if (replace_stack_len <= replace_stack_nr)
7809     {
7810 	replace_stack_len += 50;
7811 	p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
7812 	if (p == NULL)	    /* out of memory */
7813 	{
7814 	    replace_stack_len -= 50;
7815 	    return;
7816 	}
7817 	if (replace_stack != NULL)
7818 	{
7819 	    mch_memmove(p, replace_stack,
7820 				 (size_t)(replace_stack_nr * sizeof(char_u)));
7821 	    vim_free(replace_stack);
7822 	}
7823 	replace_stack = p;
7824     }
7825     p = replace_stack + replace_stack_nr - replace_offset;
7826     if (replace_offset)
7827 	mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
7828     *p = c;
7829     ++replace_stack_nr;
7830 }
7831 
7832 #if defined(FEAT_MBYTE) || defined(PROTO)
7833 /*
7834  * Push a character onto the replace stack.  Handles a multi-byte character in
7835  * reverse byte order, so that the first byte is popped off first.
7836  * Return the number of bytes done (includes composing characters).
7837  */
7838     int
7839 replace_push_mb(char_u *p)
7840 {
7841     int l = (*mb_ptr2len)(p);
7842     int j;
7843 
7844     for (j = l - 1; j >= 0; --j)
7845 	replace_push(p[j]);
7846     return l;
7847 }
7848 #endif
7849 
7850 /*
7851  * Pop one item from the replace stack.
7852  * return -1 if stack empty
7853  * return replaced character or NUL otherwise
7854  */
7855     static int
7856 replace_pop(void)
7857 {
7858     if (replace_stack_nr == 0)
7859 	return -1;
7860     return (int)replace_stack[--replace_stack_nr];
7861 }
7862 
7863 /*
7864  * Join the top two items on the replace stack.  This removes to "off"'th NUL
7865  * encountered.
7866  */
7867     static void
7868 replace_join(
7869     int	    off)	/* offset for which NUL to remove */
7870 {
7871     int	    i;
7872 
7873     for (i = replace_stack_nr; --i >= 0; )
7874 	if (replace_stack[i] == NUL && off-- <= 0)
7875 	{
7876 	    --replace_stack_nr;
7877 	    mch_memmove(replace_stack + i, replace_stack + i + 1,
7878 					      (size_t)(replace_stack_nr - i));
7879 	    return;
7880 	}
7881 }
7882 
7883 /*
7884  * Pop bytes from the replace stack until a NUL is found, and insert them
7885  * before the cursor.  Can only be used in REPLACE or VREPLACE mode.
7886  */
7887     static void
7888 replace_pop_ins(void)
7889 {
7890     int	    cc;
7891     int	    oldState = State;
7892 
7893     State = NORMAL;			/* don't want REPLACE here */
7894     while ((cc = replace_pop()) > 0)
7895     {
7896 #ifdef FEAT_MBYTE
7897 	mb_replace_pop_ins(cc);
7898 #else
7899 	ins_char(cc);
7900 #endif
7901 	dec_cursor();
7902     }
7903     State = oldState;
7904 }
7905 
7906 #ifdef FEAT_MBYTE
7907 /*
7908  * Insert bytes popped from the replace stack. "cc" is the first byte.  If it
7909  * indicates a multi-byte char, pop the other bytes too.
7910  */
7911     static void
7912 mb_replace_pop_ins(int cc)
7913 {
7914     int		n;
7915     char_u	buf[MB_MAXBYTES + 1];
7916     int		i;
7917     int		c;
7918 
7919     if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1)
7920     {
7921 	buf[0] = cc;
7922 	for (i = 1; i < n; ++i)
7923 	    buf[i] = replace_pop();
7924 	ins_bytes_len(buf, n);
7925     }
7926     else
7927 	ins_char(cc);
7928 
7929     if (enc_utf8)
7930 	/* Handle composing chars. */
7931 	for (;;)
7932 	{
7933 	    c = replace_pop();
7934 	    if (c == -1)	    /* stack empty */
7935 		break;
7936 	    if ((n = MB_BYTE2LEN(c)) == 1)
7937 	    {
7938 		/* Not a multi-byte char, put it back. */
7939 		replace_push(c);
7940 		break;
7941 	    }
7942 	    else
7943 	    {
7944 		buf[0] = c;
7945 		for (i = 1; i < n; ++i)
7946 		    buf[i] = replace_pop();
7947 		if (utf_iscomposing(utf_ptr2char(buf)))
7948 		    ins_bytes_len(buf, n);
7949 		else
7950 		{
7951 		    /* Not a composing char, put it back. */
7952 		    for (i = n - 1; i >= 0; --i)
7953 			replace_push(buf[i]);
7954 		    break;
7955 		}
7956 	    }
7957 	}
7958 }
7959 #endif
7960 
7961 /*
7962  * make the replace stack empty
7963  * (called when exiting replace mode)
7964  */
7965     static void
7966 replace_flush(void)
7967 {
7968     VIM_CLEAR(replace_stack);
7969     replace_stack_len = 0;
7970     replace_stack_nr = 0;
7971 }
7972 
7973 /*
7974  * Handle doing a BS for one character.
7975  * cc < 0: replace stack empty, just move cursor
7976  * cc == 0: character was inserted, delete it
7977  * cc > 0: character was replaced, put cc (first byte of original char) back
7978  * and check for more characters to be put back
7979  * When "limit_col" is >= 0, don't delete before this column.  Matters when
7980  * using composing characters, use del_char_after_col() instead of del_char().
7981  */
7982     static void
7983 replace_do_bs(int limit_col)
7984 {
7985     int		cc;
7986     int		orig_len = 0;
7987     int		ins_len;
7988     int		orig_vcols = 0;
7989     colnr_T	start_vcol;
7990     char_u	*p;
7991     int		i;
7992     int		vcol;
7993 
7994     cc = replace_pop();
7995     if (cc > 0)
7996     {
7997 #ifdef FEAT_TEXT_PROP
7998 	size_t	len_before = 0;  // init to shut up GCC
7999 
8000 	if (curbuf->b_has_textprop)
8001 	{
8002 	    // Do not adjust text properties for individual delete and insert
8003 	    // operations, do it afterwards on the resulting text.
8004 	    len_before = STRLEN(ml_get_curline());
8005 	    ++text_prop_frozen;
8006 	}
8007 #endif
8008 	if (State & VREPLACE_FLAG)
8009 	{
8010 	    /* Get the number of screen cells used by the character we are
8011 	     * going to delete. */
8012 	    getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
8013 	    orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
8014 	}
8015 #ifdef FEAT_MBYTE
8016 	if (has_mbyte)
8017 	{
8018 	    (void)del_char_after_col(limit_col);
8019 	    if (State & VREPLACE_FLAG)
8020 		orig_len = (int)STRLEN(ml_get_cursor());
8021 	    replace_push(cc);
8022 	}
8023 	else
8024 #endif
8025 	{
8026 	    pchar_cursor(cc);
8027 	    if (State & VREPLACE_FLAG)
8028 		orig_len = (int)STRLEN(ml_get_cursor()) - 1;
8029 	}
8030 	replace_pop_ins();
8031 
8032 	if (State & VREPLACE_FLAG)
8033 	{
8034 	    /* Get the number of screen cells used by the inserted characters */
8035 	    p = ml_get_cursor();
8036 	    ins_len = (int)STRLEN(p) - orig_len;
8037 	    vcol = start_vcol;
8038 	    for (i = 0; i < ins_len; ++i)
8039 	    {
8040 		vcol += chartabsize(p + i, vcol);
8041 #ifdef FEAT_MBYTE
8042 		i += (*mb_ptr2len)(p) - 1;
8043 #endif
8044 	    }
8045 	    vcol -= start_vcol;
8046 
8047 	    /* Delete spaces that were inserted after the cursor to keep the
8048 	     * text aligned. */
8049 	    curwin->w_cursor.col += ins_len;
8050 	    while (vcol > orig_vcols && gchar_cursor() == ' ')
8051 	    {
8052 		del_char(FALSE);
8053 		++orig_vcols;
8054 	    }
8055 	    curwin->w_cursor.col -= ins_len;
8056 	}
8057 
8058 	// mark the buffer as changed and prepare for displaying
8059 	changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
8060 
8061 #ifdef FEAT_TEXT_PROP
8062 	if (curbuf->b_has_textprop)
8063 	{
8064 	    size_t len_now = STRLEN(ml_get_curline());
8065 
8066 	    --text_prop_frozen;
8067 	    adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col,
8068 						  (int)(len_now - len_before));
8069 	}
8070 #endif
8071     }
8072     else if (cc == 0)
8073 	(void)del_char_after_col(limit_col);
8074 }
8075 
8076 #ifdef FEAT_CINDENT
8077 /*
8078  * Return TRUE if C-indenting is on.
8079  */
8080     static int
8081 cindent_on(void)
8082 {
8083     return (!p_paste && (curbuf->b_p_cin
8084 # ifdef FEAT_EVAL
8085 		    || *curbuf->b_p_inde != NUL
8086 # endif
8087 		    ));
8088 }
8089 #endif
8090 
8091 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
8092 /*
8093  * Re-indent the current line, based on the current contents of it and the
8094  * surrounding lines. Fixing the cursor position seems really easy -- I'm very
8095  * confused what all the part that handles Control-T is doing that I'm not.
8096  * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
8097  */
8098 
8099     void
8100 fixthisline(int (*get_the_indent)(void))
8101 {
8102     int amount = get_the_indent();
8103 
8104     if (amount >= 0)
8105     {
8106 	change_indent(INDENT_SET, amount, FALSE, 0, TRUE);
8107 	if (linewhite(curwin->w_cursor.lnum))
8108 	    did_ai = TRUE;	/* delete the indent if the line stays empty */
8109     }
8110 }
8111 
8112     void
8113 fix_indent(void)
8114 {
8115     if (p_paste)
8116 	return;
8117 # ifdef FEAT_LISP
8118     if (curbuf->b_p_lisp && curbuf->b_p_ai)
8119 	fixthisline(get_lisp_indent);
8120 # endif
8121 # if defined(FEAT_LISP) && defined(FEAT_CINDENT)
8122     else
8123 # endif
8124 # ifdef FEAT_CINDENT
8125 	if (cindent_on())
8126 	    do_c_expr_indent();
8127 # endif
8128 }
8129 
8130 #endif
8131 
8132 #ifdef FEAT_CINDENT
8133 /*
8134  * return TRUE if 'cinkeys' contains the key "keytyped",
8135  * when == '*':	    Only if key is preceded with '*'	(indent before insert)
8136  * when == '!':	    Only if key is preceded with '!'	(don't insert)
8137  * when == ' ':	    Only if key is not preceded with '*'(indent afterwards)
8138  *
8139  * "keytyped" can have a few special values:
8140  * KEY_OPEN_FORW
8141  * KEY_OPEN_BACK
8142  * KEY_COMPLETE	    just finished completion.
8143  *
8144  * If line_is_empty is TRUE accept keys with '0' before them.
8145  */
8146     int
8147 in_cinkeys(
8148     int		keytyped,
8149     int		when,
8150     int		line_is_empty)
8151 {
8152     char_u	*look;
8153     int		try_match;
8154     int		try_match_word;
8155     char_u	*p;
8156     char_u	*line;
8157     int		icase;
8158     int		i;
8159 
8160     if (keytyped == NUL)
8161 	/* Can happen with CTRL-Y and CTRL-E on a short line. */
8162 	return FALSE;
8163 
8164 #ifdef FEAT_EVAL
8165     if (*curbuf->b_p_inde != NUL)
8166 	look = curbuf->b_p_indk;	/* 'indentexpr' set: use 'indentkeys' */
8167     else
8168 #endif
8169 	look = curbuf->b_p_cink;	/* 'indentexpr' empty: use 'cinkeys' */
8170     while (*look)
8171     {
8172 	/*
8173 	 * Find out if we want to try a match with this key, depending on
8174 	 * 'when' and a '*' or '!' before the key.
8175 	 */
8176 	switch (when)
8177 	{
8178 	    case '*': try_match = (*look == '*'); break;
8179 	    case '!': try_match = (*look == '!'); break;
8180 	     default: try_match = (*look != '*'); break;
8181 	}
8182 	if (*look == '*' || *look == '!')
8183 	    ++look;
8184 
8185 	/*
8186 	 * If there is a '0', only accept a match if the line is empty.
8187 	 * But may still match when typing last char of a word.
8188 	 */
8189 	if (*look == '0')
8190 	{
8191 	    try_match_word = try_match;
8192 	    if (!line_is_empty)
8193 		try_match = FALSE;
8194 	    ++look;
8195 	}
8196 	else
8197 	    try_match_word = FALSE;
8198 
8199 	/*
8200 	 * does it look like a control character?
8201 	 */
8202 	if (*look == '^'
8203 #ifdef EBCDIC
8204 		&& (Ctrl_chr(look[1]) != 0)
8205 #else
8206 		&& look[1] >= '?' && look[1] <= '_'
8207 #endif
8208 		)
8209 	{
8210 	    if (try_match && keytyped == Ctrl_chr(look[1]))
8211 		return TRUE;
8212 	    look += 2;
8213 	}
8214 	/*
8215 	 * 'o' means "o" command, open forward.
8216 	 * 'O' means "O" command, open backward.
8217 	 */
8218 	else if (*look == 'o')
8219 	{
8220 	    if (try_match && keytyped == KEY_OPEN_FORW)
8221 		return TRUE;
8222 	    ++look;
8223 	}
8224 	else if (*look == 'O')
8225 	{
8226 	    if (try_match && keytyped == KEY_OPEN_BACK)
8227 		return TRUE;
8228 	    ++look;
8229 	}
8230 
8231 	/*
8232 	 * 'e' means to check for "else" at start of line and just before the
8233 	 * cursor.
8234 	 */
8235 	else if (*look == 'e')
8236 	{
8237 	    if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
8238 	    {
8239 		p = ml_get_curline();
8240 		if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
8241 			STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
8242 		    return TRUE;
8243 	    }
8244 	    ++look;
8245 	}
8246 
8247 	/*
8248 	 * ':' only causes an indent if it is at the end of a label or case
8249 	 * statement, or when it was before typing the ':' (to fix
8250 	 * class::method for C++).
8251 	 */
8252 	else if (*look == ':')
8253 	{
8254 	    if (try_match && keytyped == ':')
8255 	    {
8256 		p = ml_get_curline();
8257 		if (cin_iscase(p, FALSE) || cin_isscopedecl(p) || cin_islabel())
8258 		    return TRUE;
8259 		/* Need to get the line again after cin_islabel(). */
8260 		p = ml_get_curline();
8261 		if (curwin->w_cursor.col > 2
8262 			&& p[curwin->w_cursor.col - 1] == ':'
8263 			&& p[curwin->w_cursor.col - 2] == ':')
8264 		{
8265 		    p[curwin->w_cursor.col - 1] = ' ';
8266 		    i = (cin_iscase(p, FALSE) || cin_isscopedecl(p)
8267 							    || cin_islabel());
8268 		    p = ml_get_curline();
8269 		    p[curwin->w_cursor.col - 1] = ':';
8270 		    if (i)
8271 			return TRUE;
8272 		}
8273 	    }
8274 	    ++look;
8275 	}
8276 
8277 
8278 	/*
8279 	 * Is it a key in <>, maybe?
8280 	 */
8281 	else if (*look == '<')
8282 	{
8283 	    if (try_match)
8284 	    {
8285 		/*
8286 		 * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
8287 		 * <:> and <!> so that people can re-indent on o, O, e, 0, <,
8288 		 * >, *, : and ! keys if they really really want to.
8289 		 */
8290 		if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
8291 						       && keytyped == look[1])
8292 		    return TRUE;
8293 
8294 		if (keytyped == get_special_key_code(look + 1))
8295 		    return TRUE;
8296 	    }
8297 	    while (*look && *look != '>')
8298 		look++;
8299 	    while (*look == '>')
8300 		look++;
8301 	}
8302 
8303 	/*
8304 	 * Is it a word: "=word"?
8305 	 */
8306 	else if (*look == '=' && look[1] != ',' && look[1] != NUL)
8307 	{
8308 	    ++look;
8309 	    if (*look == '~')
8310 	    {
8311 		icase = TRUE;
8312 		++look;
8313 	    }
8314 	    else
8315 		icase = FALSE;
8316 	    p = vim_strchr(look, ',');
8317 	    if (p == NULL)
8318 		p = look + STRLEN(look);
8319 	    if ((try_match || try_match_word)
8320 		    && curwin->w_cursor.col >= (colnr_T)(p - look))
8321 	    {
8322 		int		match = FALSE;
8323 
8324 #ifdef FEAT_INS_EXPAND
8325 		if (keytyped == KEY_COMPLETE)
8326 		{
8327 		    char_u	*s;
8328 
8329 		    /* Just completed a word, check if it starts with "look".
8330 		     * search back for the start of a word. */
8331 		    line = ml_get_curline();
8332 # ifdef FEAT_MBYTE
8333 		    if (has_mbyte)
8334 		    {
8335 			char_u	*n;
8336 
8337 			for (s = line + curwin->w_cursor.col; s > line; s = n)
8338 			{
8339 			    n = mb_prevptr(line, s);
8340 			    if (!vim_iswordp(n))
8341 				break;
8342 			}
8343 		    }
8344 		    else
8345 # endif
8346 			for (s = line + curwin->w_cursor.col; s > line; --s)
8347 			    if (!vim_iswordc(s[-1]))
8348 				break;
8349 		    if (s + (p - look) <= line + curwin->w_cursor.col
8350 			    && (icase
8351 				? MB_STRNICMP(s, look, p - look)
8352 				: STRNCMP(s, look, p - look)) == 0)
8353 			match = TRUE;
8354 		}
8355 		else
8356 #endif
8357 		    /* TODO: multi-byte */
8358 		    if (keytyped == (int)p[-1] || (icase && keytyped < 256
8359 			 && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
8360 		{
8361 		    line = ml_get_cursor();
8362 		    if ((curwin->w_cursor.col == (colnr_T)(p - look)
8363 				|| !vim_iswordc(line[-(p - look) - 1]))
8364 			    && (icase
8365 				? MB_STRNICMP(line - (p - look), look, p - look)
8366 				: STRNCMP(line - (p - look), look, p - look))
8367 									 == 0)
8368 			match = TRUE;
8369 		}
8370 		if (match && try_match_word && !try_match)
8371 		{
8372 		    /* "0=word": Check if there are only blanks before the
8373 		     * word. */
8374 		    if (getwhitecols_curline() !=
8375 				     (int)(curwin->w_cursor.col - (p - look)))
8376 			match = FALSE;
8377 		}
8378 		if (match)
8379 		    return TRUE;
8380 	    }
8381 	    look = p;
8382 	}
8383 
8384 	/*
8385 	 * ok, it's a boring generic character.
8386 	 */
8387 	else
8388 	{
8389 	    if (try_match && *look == keytyped)
8390 		return TRUE;
8391 	    if (*look != NUL)
8392 		++look;
8393 	}
8394 
8395 	/*
8396 	 * Skip over ", ".
8397 	 */
8398 	look = skip_to_option_part(look);
8399     }
8400     return FALSE;
8401 }
8402 #endif /* FEAT_CINDENT */
8403 
8404 #if defined(FEAT_RIGHTLEFT) || defined(PROTO)
8405 /*
8406  * Map Hebrew keyboard when in hkmap mode.
8407  */
8408     int
8409 hkmap(int c)
8410 {
8411     if (p_hkmapp)   /* phonetic mapping, by Ilya Dogolazky */
8412     {
8413 	enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
8414 	    KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
8415 	    PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
8416 	static char_u map[26] =
8417 	    {(char_u)hALEF/*a*/, (char_u)BET  /*b*/, (char_u)hKAF    /*c*/,
8418 	     (char_u)DALET/*d*/, (char_u)-1   /*e*/, (char_u)PEIsofit/*f*/,
8419 	     (char_u)GIMEL/*g*/, (char_u)HEI  /*h*/, (char_u)IUD     /*i*/,
8420 	     (char_u)HET  /*j*/, (char_u)KOF  /*k*/, (char_u)LAMED   /*l*/,
8421 	     (char_u)MEM  /*m*/, (char_u)NUN  /*n*/, (char_u)SAMEH   /*o*/,
8422 	     (char_u)PEI  /*p*/, (char_u)-1   /*q*/, (char_u)RESH    /*r*/,
8423 	     (char_u)ZAIN /*s*/, (char_u)TAV  /*t*/, (char_u)TET     /*u*/,
8424 	     (char_u)VAV  /*v*/, (char_u)hSHIN/*w*/, (char_u)-1      /*x*/,
8425 	     (char_u)AIN  /*y*/, (char_u)ZADI /*z*/};
8426 
8427 	if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
8428 	    return (int)(map[CharOrd(c)] - 1 + p_aleph);
8429 							    /* '-1'='sofit' */
8430 	else if (c == 'x')
8431 	    return 'X';
8432 	else if (c == 'q')
8433 	    return '\''; /* {geresh}={'} */
8434 	else if (c == 246)
8435 	    return ' ';  /* \"o --> ' ' for a german keyboard */
8436 	else if (c == 228)
8437 	    return ' ';  /* \"a --> ' '      -- / --	       */
8438 	else if (c == 252)
8439 	    return ' ';  /* \"u --> ' '      -- / --	       */
8440 #ifdef EBCDIC
8441 	else if (islower(c))
8442 #else
8443 	/* NOTE: islower() does not do the right thing for us on Linux so we
8444 	 * do this the same was as 5.7 and previous, so it works correctly on
8445 	 * all systems.  Specifically, the e.g. Delete and Arrow keys are
8446 	 * munged and won't work if e.g. searching for Hebrew text.
8447 	 */
8448 	else if (c >= 'a' && c <= 'z')
8449 #endif
8450 	    return (int)(map[CharOrdLow(c)] + p_aleph);
8451 	else
8452 	    return c;
8453     }
8454     else
8455     {
8456 	switch (c)
8457 	{
8458 	    case '`':	return ';';
8459 	    case '/':	return '.';
8460 	    case '\'':	return ',';
8461 	    case 'q':	return '/';
8462 	    case 'w':	return '\'';
8463 
8464 			/* Hebrew letters - set offset from 'a' */
8465 	    case ',':	c = '{'; break;
8466 	    case '.':	c = 'v'; break;
8467 	    case ';':	c = 't'; break;
8468 	    default: {
8469 			 static char str[] = "zqbcxlsjphmkwonu ydafe rig";
8470 
8471 #ifdef EBCDIC
8472 			 /* see note about islower() above */
8473 			 if (!islower(c))
8474 #else
8475 			 if (c < 'a' || c > 'z')
8476 #endif
8477 			     return c;
8478 			 c = str[CharOrdLow(c)];
8479 			 break;
8480 		     }
8481 	}
8482 
8483 	return (int)(CharOrdLow(c) + p_aleph);
8484     }
8485 }
8486 #endif
8487 
8488     static void
8489 ins_reg(void)
8490 {
8491     int		need_redraw = FALSE;
8492     int		regname;
8493     int		literally = 0;
8494     int		vis_active = VIsual_active;
8495 
8496     /*
8497      * If we are going to wait for a character, show a '"'.
8498      */
8499     pc_status = PC_STATUS_UNSET;
8500     if (redrawing() && !char_avail())
8501     {
8502 	/* may need to redraw when no more chars available now */
8503 	ins_redraw(FALSE);
8504 
8505 	edit_putchar('"', TRUE);
8506 #ifdef FEAT_CMDL_INFO
8507 	add_to_showcmd_c(Ctrl_R);
8508 #endif
8509     }
8510 
8511 #ifdef USE_ON_FLY_SCROLL
8512     dont_scroll = TRUE;		/* disallow scrolling here */
8513 #endif
8514 
8515     /*
8516      * Don't map the register name. This also prevents the mode message to be
8517      * deleted when ESC is hit.
8518      */
8519     ++no_mapping;
8520     regname = plain_vgetc();
8521     LANGMAP_ADJUST(regname, TRUE);
8522     if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P)
8523     {
8524 	/* Get a third key for literal register insertion */
8525 	literally = regname;
8526 #ifdef FEAT_CMDL_INFO
8527 	add_to_showcmd_c(literally);
8528 #endif
8529 	regname = plain_vgetc();
8530 	LANGMAP_ADJUST(regname, TRUE);
8531     }
8532     --no_mapping;
8533 
8534 #ifdef FEAT_EVAL
8535     /* Don't call u_sync() while typing the expression or giving an error
8536      * message for it. Only call it explicitly. */
8537     ++no_u_sync;
8538     if (regname == '=')
8539     {
8540 # ifdef HAVE_INPUT_METHOD
8541 	int	im_on = im_get_status();
8542 # endif
8543 	/* Sync undo when evaluating the expression calls setline() or
8544 	 * append(), so that it can be undone separately. */
8545 	u_sync_once = 2;
8546 
8547 	regname = get_expr_register();
8548 # ifdef HAVE_INPUT_METHOD
8549 	/* Restore the Input Method. */
8550 	if (im_on)
8551 	    im_set_active(TRUE);
8552 # endif
8553     }
8554     if (regname == NUL || !valid_yank_reg(regname, FALSE))
8555     {
8556 	vim_beep(BO_REG);
8557 	need_redraw = TRUE;	/* remove the '"' */
8558     }
8559     else
8560     {
8561 #endif
8562 	if (literally == Ctrl_O || literally == Ctrl_P)
8563 	{
8564 	    /* Append the command to the redo buffer. */
8565 	    AppendCharToRedobuff(Ctrl_R);
8566 	    AppendCharToRedobuff(literally);
8567 	    AppendCharToRedobuff(regname);
8568 
8569 	    do_put(regname, BACKWARD, 1L,
8570 		 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
8571 	}
8572 	else if (insert_reg(regname, literally) == FAIL)
8573 	{
8574 	    vim_beep(BO_REG);
8575 	    need_redraw = TRUE;	/* remove the '"' */
8576 	}
8577 	else if (stop_insert_mode)
8578 	    /* When the '=' register was used and a function was invoked that
8579 	     * did ":stopinsert" then stuff_empty() returns FALSE but we won't
8580 	     * insert anything, need to remove the '"' */
8581 	    need_redraw = TRUE;
8582 
8583 #ifdef FEAT_EVAL
8584     }
8585     --no_u_sync;
8586     if (u_sync_once == 1)
8587 	ins_need_undo = TRUE;
8588     u_sync_once = 0;
8589 #endif
8590 #ifdef FEAT_CMDL_INFO
8591     clear_showcmd();
8592 #endif
8593 
8594     /* If the inserted register is empty, we need to remove the '"' */
8595     if (need_redraw || stuff_empty())
8596 	edit_unputchar();
8597 
8598     /* Disallow starting Visual mode here, would get a weird mode. */
8599     if (!vis_active && VIsual_active)
8600 	end_visual_mode();
8601 }
8602 
8603 /*
8604  * CTRL-G commands in Insert mode.
8605  */
8606     static void
8607 ins_ctrl_g(void)
8608 {
8609     int		c;
8610 
8611 #ifdef FEAT_INS_EXPAND
8612     /* Right after CTRL-X the cursor will be after the ruler. */
8613     setcursor();
8614 #endif
8615 
8616     /*
8617      * Don't map the second key. This also prevents the mode message to be
8618      * deleted when ESC is hit.
8619      */
8620     ++no_mapping;
8621     c = plain_vgetc();
8622     --no_mapping;
8623     switch (c)
8624     {
8625 	/* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
8626 	case K_UP:
8627 	case Ctrl_K:
8628 	case 'k': ins_up(TRUE);
8629 		  break;
8630 
8631 	/* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
8632 	case K_DOWN:
8633 	case Ctrl_J:
8634 	case 'j': ins_down(TRUE);
8635 		  break;
8636 
8637 	/* CTRL-G u: start new undoable edit */
8638 	case 'u': u_sync(TRUE);
8639 		  ins_need_undo = TRUE;
8640 
8641 		  /* Need to reset Insstart, esp. because a BS that joins
8642 		   * a line to the previous one must save for undo. */
8643 		  update_Insstart_orig = FALSE;
8644 		  Insstart = curwin->w_cursor;
8645 		  break;
8646 
8647 	/* CTRL-G U: do not break undo with the next char */
8648 	case 'U':
8649 		  /* Allow one left/right cursor movement with the next char,
8650 		   * without breaking undo. */
8651 		  dont_sync_undo = MAYBE;
8652 		  break;
8653 
8654 	/* Unknown CTRL-G command, reserved for future expansion. */
8655 	default:  vim_beep(BO_CTRLG);
8656     }
8657 }
8658 
8659 /*
8660  * CTRL-^ in Insert mode.
8661  */
8662     static void
8663 ins_ctrl_hat(void)
8664 {
8665     if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE))
8666     {
8667 	/* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
8668 	if (State & LANGMAP)
8669 	{
8670 	    curbuf->b_p_iminsert = B_IMODE_NONE;
8671 	    State &= ~LANGMAP;
8672 	}
8673 	else
8674 	{
8675 	    curbuf->b_p_iminsert = B_IMODE_LMAP;
8676 	    State |= LANGMAP;
8677 #ifdef HAVE_INPUT_METHOD
8678 	    im_set_active(FALSE);
8679 #endif
8680 	}
8681     }
8682 #ifdef HAVE_INPUT_METHOD
8683     else
8684     {
8685 	/* There are no ":lmap" mappings, toggle IM */
8686 	if (im_get_status())
8687 	{
8688 	    curbuf->b_p_iminsert = B_IMODE_NONE;
8689 	    im_set_active(FALSE);
8690 	}
8691 	else
8692 	{
8693 	    curbuf->b_p_iminsert = B_IMODE_IM;
8694 	    State &= ~LANGMAP;
8695 	    im_set_active(TRUE);
8696 	}
8697     }
8698 #endif
8699     set_iminsert_global();
8700     showmode();
8701 #ifdef FEAT_GUI
8702     /* may show different cursor shape or color */
8703     if (gui.in_use)
8704 	gui_update_cursor(TRUE, FALSE);
8705 #endif
8706 #if defined(FEAT_KEYMAP)
8707     /* Show/unshow value of 'keymap' in status lines. */
8708     status_redraw_curbuf();
8709 #endif
8710 }
8711 
8712 /*
8713  * Handle ESC in insert mode.
8714  * Returns TRUE when leaving insert mode, FALSE when going to repeat the
8715  * insert.
8716  */
8717     static int
8718 ins_esc(
8719     long	*count,
8720     int		cmdchar,
8721     int		nomove)	    /* don't move cursor */
8722 {
8723     int		temp;
8724     static int	disabled_redraw = FALSE;
8725 
8726 #ifdef FEAT_SPELL
8727     check_spell_redraw();
8728 #endif
8729 #if defined(FEAT_HANGULIN)
8730 # if defined(ESC_CHG_TO_ENG_MODE)
8731     hangul_input_state_set(0);
8732 # endif
8733     if (composing_hangul)
8734     {
8735 	push_raw_key(composing_hangul_buffer, 2);
8736 	composing_hangul = 0;
8737     }
8738 #endif
8739 
8740     temp = curwin->w_cursor.col;
8741     if (disabled_redraw)
8742     {
8743 	--RedrawingDisabled;
8744 	disabled_redraw = FALSE;
8745     }
8746     if (!arrow_used)
8747     {
8748 	/*
8749 	 * Don't append the ESC for "r<CR>" and "grx".
8750 	 * When 'insertmode' is set only CTRL-L stops Insert mode.  Needed for
8751 	 * when "count" is non-zero.
8752 	 */
8753 	if (cmdchar != 'r' && cmdchar != 'v')
8754 	    AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
8755 
8756 	/*
8757 	 * Repeating insert may take a long time.  Check for
8758 	 * interrupt now and then.
8759 	 */
8760 	if (*count > 0)
8761 	{
8762 	    line_breakcheck();
8763 	    if (got_int)
8764 		*count = 0;
8765 	}
8766 
8767 	if (--*count > 0)	/* repeat what was typed */
8768 	{
8769 	    /* Vi repeats the insert without replacing characters. */
8770 	    if (vim_strchr(p_cpo, CPO_REPLCNT) != NULL)
8771 		State &= ~REPLACE_FLAG;
8772 
8773 	    (void)start_redo_ins();
8774 	    if (cmdchar == 'r' || cmdchar == 'v')
8775 		stuffRedoReadbuff(ESC_STR);	/* no ESC in redo buffer */
8776 	    ++RedrawingDisabled;
8777 	    disabled_redraw = TRUE;
8778 	    return FALSE;	/* repeat the insert */
8779 	}
8780 	stop_insert(&curwin->w_cursor, TRUE, nomove);
8781 	undisplay_dollar();
8782     }
8783 
8784     /* When an autoindent was removed, curswant stays after the
8785      * indent */
8786     if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col)
8787 	curwin->w_set_curswant = TRUE;
8788 
8789     /* Remember the last Insert position in the '^ mark. */
8790     if (!cmdmod.keepjumps)
8791 	curbuf->b_last_insert = curwin->w_cursor;
8792 
8793     /*
8794      * The cursor should end up on the last inserted character.
8795      * Don't do it for CTRL-O, unless past the end of the line.
8796      */
8797     if (!nomove
8798 	    && (curwin->w_cursor.col != 0
8799 #ifdef FEAT_VIRTUALEDIT
8800 		|| curwin->w_cursor.coladd > 0
8801 #endif
8802 	       )
8803 	    && (restart_edit == NUL
8804 		   || (gchar_cursor() == NUL && !VIsual_active))
8805 #ifdef FEAT_RIGHTLEFT
8806 	    && !revins_on
8807 #endif
8808 				      )
8809     {
8810 #ifdef FEAT_VIRTUALEDIT
8811 	if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL)
8812 	{
8813 	    oneleft();
8814 	    if (restart_edit != NUL)
8815 		++curwin->w_cursor.coladd;
8816 	}
8817 	else
8818 #endif
8819 	{
8820 	    --curwin->w_cursor.col;
8821 #ifdef FEAT_MBYTE
8822 	    /* Correct cursor for multi-byte character. */
8823 	    if (has_mbyte)
8824 		mb_adjust_cursor();
8825 #endif
8826 	}
8827     }
8828 
8829 #ifdef HAVE_INPUT_METHOD
8830     /* Disable IM to allow typing English directly for Normal mode commands.
8831      * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
8832      * well). */
8833     if (!(State & LANGMAP))
8834 	im_save_status(&curbuf->b_p_iminsert);
8835     im_set_active(FALSE);
8836 #endif
8837 
8838     State = NORMAL;
8839     /* need to position cursor again (e.g. when on a TAB ) */
8840     changed_cline_bef_curs();
8841 
8842 #ifdef FEAT_MOUSE
8843     setmouse();
8844 #endif
8845 #ifdef CURSOR_SHAPE
8846     ui_cursor_shape();		/* may show different cursor shape */
8847 #endif
8848     if (!p_ek)
8849 	/* Re-enable bracketed paste mode. */
8850 	out_str(T_BE);
8851 
8852     /*
8853      * When recording or for CTRL-O, need to display the new mode.
8854      * Otherwise remove the mode message.
8855      */
8856     if (reg_recording != 0 || restart_edit != NUL)
8857 	showmode();
8858     else if (p_smd)
8859 	MSG("");
8860 
8861     return TRUE;	    /* exit Insert mode */
8862 }
8863 
8864 #ifdef FEAT_RIGHTLEFT
8865 /*
8866  * Toggle language: hkmap and revins_on.
8867  * Move to end of reverse inserted text.
8868  */
8869     static void
8870 ins_ctrl_(void)
8871 {
8872     if (revins_on && revins_chars && revins_scol >= 0)
8873     {
8874 	while (gchar_cursor() != NUL && revins_chars--)
8875 	    ++curwin->w_cursor.col;
8876     }
8877     p_ri = !p_ri;
8878     revins_on = (State == INSERT && p_ri);
8879     if (revins_on)
8880     {
8881 	revins_scol = curwin->w_cursor.col;
8882 	revins_legal++;
8883 	revins_chars = 0;
8884 	undisplay_dollar();
8885     }
8886     else
8887 	revins_scol = -1;
8888 #ifdef FEAT_FKMAP
8889     if (p_altkeymap)
8890     {
8891 	/*
8892 	 * to be consistent also for redo command, using '.'
8893 	 * set arrow_used to true and stop it - causing to redo
8894 	 * characters entered in one mode (normal/reverse insert).
8895 	 */
8896 	arrow_used = TRUE;
8897 	(void)stop_arrow();
8898 	p_fkmap = curwin->w_p_rl ^ p_ri;
8899 	if (p_fkmap && p_ri)
8900 	    State = INSERT;
8901     }
8902     else
8903 #endif
8904 	p_hkmap = curwin->w_p_rl ^ p_ri;    /* be consistent! */
8905     showmode();
8906 }
8907 #endif
8908 
8909 /*
8910  * If 'keymodel' contains "startsel", may start selection.
8911  * Returns TRUE when a CTRL-O and other keys stuffed.
8912  */
8913     static int
8914 ins_start_select(int c)
8915 {
8916     if (km_startsel)
8917 	switch (c)
8918 	{
8919 	    case K_KHOME:
8920 	    case K_KEND:
8921 	    case K_PAGEUP:
8922 	    case K_KPAGEUP:
8923 	    case K_PAGEDOWN:
8924 	    case K_KPAGEDOWN:
8925 # ifdef MACOS_X
8926 	    case K_LEFT:
8927 	    case K_RIGHT:
8928 	    case K_UP:
8929 	    case K_DOWN:
8930 	    case K_END:
8931 	    case K_HOME:
8932 # endif
8933 		if (!(mod_mask & MOD_MASK_SHIFT))
8934 		    break;
8935 		/* FALLTHROUGH */
8936 	    case K_S_LEFT:
8937 	    case K_S_RIGHT:
8938 	    case K_S_UP:
8939 	    case K_S_DOWN:
8940 	    case K_S_END:
8941 	    case K_S_HOME:
8942 		/* Start selection right away, the cursor can move with
8943 		 * CTRL-O when beyond the end of the line. */
8944 		start_selection();
8945 
8946 		/* Execute the key in (insert) Select mode. */
8947 		stuffcharReadbuff(Ctrl_O);
8948 		if (mod_mask)
8949 		{
8950 		    char_u	    buf[4];
8951 
8952 		    buf[0] = K_SPECIAL;
8953 		    buf[1] = KS_MODIFIER;
8954 		    buf[2] = mod_mask;
8955 		    buf[3] = NUL;
8956 		    stuffReadbuff(buf);
8957 		}
8958 		stuffcharReadbuff(c);
8959 		return TRUE;
8960 	}
8961     return FALSE;
8962 }
8963 
8964 /*
8965  * <Insert> key in Insert mode: toggle insert/replace mode.
8966  */
8967     static void
8968 ins_insert(int replaceState)
8969 {
8970 #ifdef FEAT_FKMAP
8971     if (p_fkmap && p_ri)
8972     {
8973 	beep_flush();
8974 	emsg(farsi_text_3);	/* encoded in Farsi */
8975 	return;
8976     }
8977 #endif
8978 
8979 # ifdef FEAT_EVAL
8980     set_vim_var_string(VV_INSERTMODE,
8981 		   (char_u *)((State & REPLACE_FLAG) ? "i"
8982 		          : replaceState == VREPLACE ? "v"
8983 						     : "r"), 1);
8984 # endif
8985     ins_apply_autocmds(EVENT_INSERTCHANGE);
8986     if (State & REPLACE_FLAG)
8987 	State = INSERT | (State & LANGMAP);
8988     else
8989 	State = replaceState | (State & LANGMAP);
8990     AppendCharToRedobuff(K_INS);
8991     showmode();
8992 #ifdef CURSOR_SHAPE
8993     ui_cursor_shape();		/* may show different cursor shape */
8994 #endif
8995 }
8996 
8997 /*
8998  * Pressed CTRL-O in Insert mode.
8999  */
9000     static void
9001 ins_ctrl_o(void)
9002 {
9003     if (State & VREPLACE_FLAG)
9004 	restart_edit = 'V';
9005     else
9006 	if (State & REPLACE_FLAG)
9007 	restart_edit = 'R';
9008     else
9009 	restart_edit = 'I';
9010 #ifdef FEAT_VIRTUALEDIT
9011     if (virtual_active())
9012 	ins_at_eol = FALSE;	/* cursor always keeps its column */
9013     else
9014 #endif
9015 	ins_at_eol = (gchar_cursor() == NUL);
9016 }
9017 
9018 /*
9019  * If the cursor is on an indent, ^T/^D insert/delete one
9020  * shiftwidth.	Otherwise ^T/^D behave like a "<<" or ">>".
9021  * Always round the indent to 'shiftwidth', this is compatible
9022  * with vi.  But vi only supports ^T and ^D after an
9023  * autoindent, we support it everywhere.
9024  */
9025     static void
9026 ins_shift(int c, int lastc)
9027 {
9028     if (stop_arrow() == FAIL)
9029 	return;
9030     AppendCharToRedobuff(c);
9031 
9032     /*
9033      * 0^D and ^^D: remove all indent.
9034      */
9035     if (c == Ctrl_D && (lastc == '0' || lastc == '^')
9036 						  && curwin->w_cursor.col > 0)
9037     {
9038 	--curwin->w_cursor.col;
9039 	(void)del_char(FALSE);		/* delete the '^' or '0' */
9040 	/* In Replace mode, restore the characters that '^' or '0' replaced. */
9041 	if (State & REPLACE_FLAG)
9042 	    replace_pop_ins();
9043 	if (lastc == '^')
9044 	    old_indent = get_indent();	/* remember curr. indent */
9045 	change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
9046     }
9047     else
9048 	change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
9049 
9050     if (did_ai && *skipwhite(ml_get_curline()) != NUL)
9051 	did_ai = FALSE;
9052 #ifdef FEAT_SMARTINDENT
9053     did_si = FALSE;
9054     can_si = FALSE;
9055     can_si_back = FALSE;
9056 #endif
9057 #ifdef FEAT_CINDENT
9058     can_cindent = FALSE;	/* no cindenting after ^D or ^T */
9059 #endif
9060 }
9061 
9062     static void
9063 ins_del(void)
9064 {
9065     int	    temp;
9066 
9067     if (stop_arrow() == FAIL)
9068 	return;
9069     if (gchar_cursor() == NUL)		/* delete newline */
9070     {
9071 	temp = curwin->w_cursor.col;
9072 	if (!can_bs(BS_EOL)		/* only if "eol" included */
9073 		|| do_join(2, FALSE, TRUE, FALSE, FALSE) == FAIL)
9074 	    vim_beep(BO_BS);
9075 	else
9076 	{
9077 	    curwin->w_cursor.col = temp;
9078 	    /* Adjust orig_line_count in case more lines have been deleted than
9079 	     * have been added. That makes sure, that open_line() later
9080 	     * can access all buffer lines correctly */
9081 	    if (State & VREPLACE_FLAG &&
9082 		    orig_line_count > curbuf->b_ml.ml_line_count)
9083 		orig_line_count = curbuf->b_ml.ml_line_count;
9084 	}
9085     }
9086     else if (del_char(FALSE) == FAIL)  /* delete char under cursor */
9087 	vim_beep(BO_BS);
9088     did_ai = FALSE;
9089 #ifdef FEAT_SMARTINDENT
9090     did_si = FALSE;
9091     can_si = FALSE;
9092     can_si_back = FALSE;
9093 #endif
9094     AppendCharToRedobuff(K_DEL);
9095 }
9096 
9097 /*
9098  * Delete one character for ins_bs().
9099  */
9100     static void
9101 ins_bs_one(colnr_T *vcolp)
9102 {
9103     dec_cursor();
9104     getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
9105     if (State & REPLACE_FLAG)
9106     {
9107 	/* Don't delete characters before the insert point when in
9108 	 * Replace mode */
9109 	if (curwin->w_cursor.lnum != Insstart.lnum
9110 		|| curwin->w_cursor.col >= Insstart.col)
9111 	    replace_do_bs(-1);
9112     }
9113     else
9114 	(void)del_char(FALSE);
9115 }
9116 
9117 /*
9118  * Handle Backspace, delete-word and delete-line in Insert mode.
9119  * Return TRUE when backspace was actually used.
9120  */
9121     static int
9122 ins_bs(
9123     int		c,
9124     int		mode,
9125     int		*inserted_space_p)
9126 {
9127     linenr_T	lnum;
9128     int		cc;
9129     int		temp = 0;	    /* init for GCC */
9130     colnr_T	save_col;
9131     colnr_T	mincol;
9132     int		did_backspace = FALSE;
9133     int		in_indent;
9134     int		oldState;
9135 #ifdef FEAT_MBYTE
9136     int		cpc[MAX_MCO];	    /* composing characters */
9137 #endif
9138 
9139     /*
9140      * can't delete anything in an empty file
9141      * can't backup past first character in buffer
9142      * can't backup past starting point unless 'backspace' > 1
9143      * can backup to a previous line if 'backspace' == 0
9144      */
9145     if (       BUFEMPTY()
9146 	    || (
9147 #ifdef FEAT_RIGHTLEFT
9148 		!revins_on &&
9149 #endif
9150 		((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
9151 		    || (!can_bs(BS_START)
9152 			&& (arrow_used
9153 			    || (curwin->w_cursor.lnum == Insstart_orig.lnum
9154 				&& curwin->w_cursor.col <= Insstart_orig.col)))
9155 		    || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
9156 					 && curwin->w_cursor.col <= ai_col)
9157 		    || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0))))
9158     {
9159 	vim_beep(BO_BS);
9160 	return FALSE;
9161     }
9162 
9163     if (stop_arrow() == FAIL)
9164 	return FALSE;
9165     in_indent = inindent(0);
9166 #ifdef FEAT_CINDENT
9167     if (in_indent)
9168 	can_cindent = FALSE;
9169 #endif
9170 #ifdef FEAT_COMMENTS
9171     end_comment_pending = NUL;	/* After BS, don't auto-end comment */
9172 #endif
9173 #ifdef FEAT_RIGHTLEFT
9174     if (revins_on)	    /* put cursor after last inserted char */
9175 	inc_cursor();
9176 #endif
9177 
9178 #ifdef FEAT_VIRTUALEDIT
9179     /* Virtualedit:
9180      *	BACKSPACE_CHAR eats a virtual space
9181      *	BACKSPACE_WORD eats all coladd
9182      *	BACKSPACE_LINE eats all coladd and keeps going
9183      */
9184     if (curwin->w_cursor.coladd > 0)
9185     {
9186 	if (mode == BACKSPACE_CHAR)
9187 	{
9188 	    --curwin->w_cursor.coladd;
9189 	    return TRUE;
9190 	}
9191 	if (mode == BACKSPACE_WORD)
9192 	{
9193 	    curwin->w_cursor.coladd = 0;
9194 	    return TRUE;
9195 	}
9196 	curwin->w_cursor.coladd = 0;
9197     }
9198 #endif
9199 
9200     /*
9201      * Delete newline!
9202      */
9203     if (curwin->w_cursor.col == 0)
9204     {
9205 	lnum = Insstart.lnum;
9206 	if (curwin->w_cursor.lnum == lnum
9207 #ifdef FEAT_RIGHTLEFT
9208 			|| revins_on
9209 #endif
9210 				    )
9211 	{
9212 	    if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
9213 			       (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
9214 		return FALSE;
9215 	    --Insstart.lnum;
9216 	    Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum));
9217 	}
9218 	/*
9219 	 * In replace mode:
9220 	 * cc < 0: NL was inserted, delete it
9221 	 * cc >= 0: NL was replaced, put original characters back
9222 	 */
9223 	cc = -1;
9224 	if (State & REPLACE_FLAG)
9225 	    cc = replace_pop();	    /* returns -1 if NL was inserted */
9226 	/*
9227 	 * In replace mode, in the line we started replacing, we only move the
9228 	 * cursor.
9229 	 */
9230 	if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum)
9231 	{
9232 	    dec_cursor();
9233 	}
9234 	else
9235 	{
9236 	    if (!(State & VREPLACE_FLAG)
9237 				   || curwin->w_cursor.lnum > orig_line_count)
9238 	    {
9239 		temp = gchar_cursor();	/* remember current char */
9240 		--curwin->w_cursor.lnum;
9241 
9242 		/* When "aw" is in 'formatoptions' we must delete the space at
9243 		 * the end of the line, otherwise the line will be broken
9244 		 * again when auto-formatting. */
9245 		if (has_format_option(FO_AUTO)
9246 					   && has_format_option(FO_WHITE_PAR))
9247 		{
9248 		    char_u  *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum,
9249 									TRUE);
9250 		    int	    len;
9251 
9252 		    len = (int)STRLEN(ptr);
9253 		    if (len > 0 && ptr[len - 1] == ' ')
9254 			ptr[len - 1] = NUL;
9255 		}
9256 
9257 		(void)do_join(2, FALSE, FALSE, FALSE, FALSE);
9258 		if (temp == NUL && gchar_cursor() != NUL)
9259 		    inc_cursor();
9260 	    }
9261 	    else
9262 		dec_cursor();
9263 
9264 	    /*
9265 	     * In REPLACE mode we have to put back the text that was replaced
9266 	     * by the NL. On the replace stack is first a NUL-terminated
9267 	     * sequence of characters that were deleted and then the
9268 	     * characters that NL replaced.
9269 	     */
9270 	    if (State & REPLACE_FLAG)
9271 	    {
9272 		/*
9273 		 * Do the next ins_char() in NORMAL state, to
9274 		 * prevent ins_char() from replacing characters and
9275 		 * avoiding showmatch().
9276 		 */
9277 		oldState = State;
9278 		State = NORMAL;
9279 		/*
9280 		 * restore characters (blanks) deleted after cursor
9281 		 */
9282 		while (cc > 0)
9283 		{
9284 		    save_col = curwin->w_cursor.col;
9285 #ifdef FEAT_MBYTE
9286 		    mb_replace_pop_ins(cc);
9287 #else
9288 		    ins_char(cc);
9289 #endif
9290 		    curwin->w_cursor.col = save_col;
9291 		    cc = replace_pop();
9292 		}
9293 		/* restore the characters that NL replaced */
9294 		replace_pop_ins();
9295 		State = oldState;
9296 	    }
9297 	}
9298 	did_ai = FALSE;
9299     }
9300     else
9301     {
9302 	/*
9303 	 * Delete character(s) before the cursor.
9304 	 */
9305 #ifdef FEAT_RIGHTLEFT
9306 	if (revins_on)		/* put cursor on last inserted char */
9307 	    dec_cursor();
9308 #endif
9309 	mincol = 0;
9310 						/* keep indent */
9311 	if (mode == BACKSPACE_LINE
9312 		&& (curbuf->b_p_ai
9313 #ifdef FEAT_CINDENT
9314 		    || cindent_on()
9315 #endif
9316 		   )
9317 #ifdef FEAT_RIGHTLEFT
9318 		&& !revins_on
9319 #endif
9320 			    )
9321 	{
9322 	    save_col = curwin->w_cursor.col;
9323 	    beginline(BL_WHITE);
9324 	    if (curwin->w_cursor.col < save_col)
9325 		mincol = curwin->w_cursor.col;
9326 	    curwin->w_cursor.col = save_col;
9327 	}
9328 
9329 	/*
9330 	 * Handle deleting one 'shiftwidth' or 'softtabstop'.
9331 	 */
9332 	if (	   mode == BACKSPACE_CHAR
9333 		&& ((p_sta && in_indent)
9334 		    || ((get_sts_value() != 0
9335 #ifdef FEAT_VARTABS
9336 			|| tabstop_count(curbuf->b_p_vsts_array)
9337 #endif
9338 			)
9339 			&& curwin->w_cursor.col > 0
9340 			&& (*(ml_get_cursor() - 1) == TAB
9341 			    || (*(ml_get_cursor() - 1) == ' '
9342 				&& (!*inserted_space_p
9343 				    || arrow_used))))))
9344 	{
9345 	    int		ts;
9346 	    colnr_T	vcol;
9347 	    colnr_T	want_vcol;
9348 	    colnr_T	start_vcol;
9349 
9350 	    *inserted_space_p = FALSE;
9351 	    /* Compute the virtual column where we want to be.  Since
9352 	     * 'showbreak' may get in the way, need to get the last column of
9353 	     * the previous character. */
9354 	    getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
9355 	    start_vcol = vcol;
9356 	    dec_cursor();
9357 	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
9358 	    inc_cursor();
9359 #ifdef FEAT_VARTABS
9360 	    if (p_sta && in_indent)
9361 	    {
9362 		ts = (int)get_sw_value(curbuf);
9363 		want_vcol = (want_vcol / ts) * ts;
9364 	    }
9365 	    else
9366 		want_vcol = tabstop_start(want_vcol, get_sts_value(),
9367 						     curbuf->b_p_vsts_array);
9368 #else
9369 	    if (p_sta && in_indent)
9370 		ts = (int)get_sw_value(curbuf);
9371 	    else
9372 		ts = (int)get_sts_value();
9373 	    want_vcol = (want_vcol / ts) * ts;
9374 #endif
9375 
9376 	    /* delete characters until we are at or before want_vcol */
9377 	    while (vcol > want_vcol
9378 		    && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc)))
9379 		ins_bs_one(&vcol);
9380 
9381 	    /* insert extra spaces until we are at want_vcol */
9382 	    while (vcol < want_vcol)
9383 	    {
9384 		/* Remember the first char we inserted */
9385 		if (curwin->w_cursor.lnum == Insstart_orig.lnum
9386 				   && curwin->w_cursor.col < Insstart_orig.col)
9387 		    Insstart_orig.col = curwin->w_cursor.col;
9388 
9389 		if (State & VREPLACE_FLAG)
9390 		    ins_char(' ');
9391 		else
9392 		{
9393 		    ins_str((char_u *)" ");
9394 		    if ((State & REPLACE_FLAG))
9395 			replace_push(NUL);
9396 		}
9397 		getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
9398 	    }
9399 
9400 	    /* If we are now back where we started delete one character.  Can
9401 	     * happen when using 'sts' and 'linebreak'. */
9402 	    if (vcol >= start_vcol)
9403 		ins_bs_one(&vcol);
9404 	}
9405 
9406 	/*
9407 	 * Delete upto starting point, start of line or previous word.
9408 	 */
9409 	else
9410 	{
9411 #ifdef FEAT_MBYTE
9412 	    int cclass = 0, prev_cclass = 0;
9413 
9414 	    if (has_mbyte)
9415 		cclass = mb_get_class(ml_get_cursor());
9416 #endif
9417 	    do
9418 	    {
9419 #ifdef FEAT_RIGHTLEFT
9420 		if (!revins_on) /* put cursor on char to be deleted */
9421 #endif
9422 		    dec_cursor();
9423 
9424 		cc = gchar_cursor();
9425 #ifdef FEAT_MBYTE
9426 		/* look multi-byte character class */
9427 		if (has_mbyte)
9428 		{
9429 		    prev_cclass = cclass;
9430 		    cclass = mb_get_class(ml_get_cursor());
9431 		}
9432 #endif
9433 
9434 		/* start of word? */
9435 		if (mode == BACKSPACE_WORD && !vim_isspace(cc))
9436 		{
9437 		    mode = BACKSPACE_WORD_NOT_SPACE;
9438 		    temp = vim_iswordc(cc);
9439 		}
9440 		/* end of word? */
9441 		else if (mode == BACKSPACE_WORD_NOT_SPACE
9442 			&& ((vim_isspace(cc) || vim_iswordc(cc) != temp)
9443 #ifdef FEAT_MBYTE
9444 			|| prev_cclass != cclass
9445 #endif
9446 			))
9447 		{
9448 #ifdef FEAT_RIGHTLEFT
9449 		    if (!revins_on)
9450 #endif
9451 			inc_cursor();
9452 #ifdef FEAT_RIGHTLEFT
9453 		    else if (State & REPLACE_FLAG)
9454 			dec_cursor();
9455 #endif
9456 		    break;
9457 		}
9458 		if (State & REPLACE_FLAG)
9459 		    replace_do_bs(-1);
9460 		else
9461 		{
9462 #ifdef FEAT_MBYTE
9463 		    if (enc_utf8 && p_deco)
9464 			(void)utfc_ptr2char(ml_get_cursor(), cpc);
9465 #endif
9466 		    (void)del_char(FALSE);
9467 #ifdef FEAT_MBYTE
9468 		    /*
9469 		     * If there are combining characters and 'delcombine' is set
9470 		     * move the cursor back.  Don't back up before the base
9471 		     * character.
9472 		     */
9473 		    if (enc_utf8 && p_deco && cpc[0] != NUL)
9474 			inc_cursor();
9475 #endif
9476 #ifdef FEAT_RIGHTLEFT
9477 		    if (revins_chars)
9478 		    {
9479 			revins_chars--;
9480 			revins_legal++;
9481 		    }
9482 		    if (revins_on && gchar_cursor() == NUL)
9483 			break;
9484 #endif
9485 		}
9486 		/* Just a single backspace?: */
9487 		if (mode == BACKSPACE_CHAR)
9488 		    break;
9489 	    } while (
9490 #ifdef FEAT_RIGHTLEFT
9491 		    revins_on ||
9492 #endif
9493 		    (curwin->w_cursor.col > mincol
9494 		    && (curwin->w_cursor.lnum != Insstart_orig.lnum
9495 			|| curwin->w_cursor.col != Insstart_orig.col)));
9496 	}
9497 	did_backspace = TRUE;
9498     }
9499 #ifdef FEAT_SMARTINDENT
9500     did_si = FALSE;
9501     can_si = FALSE;
9502     can_si_back = FALSE;
9503 #endif
9504     if (curwin->w_cursor.col <= 1)
9505 	did_ai = FALSE;
9506     /*
9507      * It's a little strange to put backspaces into the redo
9508      * buffer, but it makes auto-indent a lot easier to deal
9509      * with.
9510      */
9511     AppendCharToRedobuff(c);
9512 
9513     /* If deleted before the insertion point, adjust it */
9514     if (curwin->w_cursor.lnum == Insstart_orig.lnum
9515 				  && curwin->w_cursor.col < Insstart_orig.col)
9516 	Insstart_orig.col = curwin->w_cursor.col;
9517 
9518     /* vi behaviour: the cursor moves backward but the character that
9519      *		     was there remains visible
9520      * Vim behaviour: the cursor moves backward and the character that
9521      *		      was there is erased from the screen.
9522      * We can emulate the vi behaviour by pretending there is a dollar
9523      * displayed even when there isn't.
9524      *  --pkv Sun Jan 19 01:56:40 EST 2003 */
9525     if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == -1)
9526 	dollar_vcol = curwin->w_virtcol;
9527 
9528 #ifdef FEAT_FOLDING
9529     /* When deleting a char the cursor line must never be in a closed fold.
9530      * E.g., when 'foldmethod' is indent and deleting the first non-white
9531      * char before a Tab. */
9532     if (did_backspace)
9533 	foldOpenCursor();
9534 #endif
9535 
9536     return did_backspace;
9537 }
9538 
9539 #ifdef FEAT_MOUSE
9540     static void
9541 ins_mouse(int c)
9542 {
9543     pos_T	tpos;
9544     win_T	*old_curwin = curwin;
9545 
9546 # ifdef FEAT_GUI
9547     /* When GUI is active, also move/paste when 'mouse' is empty */
9548     if (!gui.in_use)
9549 # endif
9550 	if (!mouse_has(MOUSE_INSERT))
9551 	    return;
9552 
9553     undisplay_dollar();
9554     tpos = curwin->w_cursor;
9555     if (do_mouse(NULL, c, BACKWARD, 1L, 0))
9556     {
9557 	win_T	*new_curwin = curwin;
9558 
9559 	if (curwin != old_curwin && win_valid(old_curwin))
9560 	{
9561 	    /* Mouse took us to another window.  We need to go back to the
9562 	     * previous one to stop insert there properly. */
9563 	    curwin = old_curwin;
9564 	    curbuf = curwin->w_buffer;
9565 #ifdef FEAT_JOB_CHANNEL
9566 	    if (bt_prompt(curbuf))
9567 		// Restart Insert mode when re-entering the prompt buffer.
9568 		curbuf->b_prompt_insert = 'A';
9569 #endif
9570 	}
9571 	start_arrow(curwin == old_curwin ? &tpos : NULL);
9572 	if (curwin != new_curwin && win_valid(new_curwin))
9573 	{
9574 	    curwin = new_curwin;
9575 	    curbuf = curwin->w_buffer;
9576 	}
9577 # ifdef FEAT_CINDENT
9578 	can_cindent = TRUE;
9579 # endif
9580     }
9581 
9582     /* redraw status lines (in case another window became active) */
9583     redraw_statuslines();
9584 }
9585 
9586     static void
9587 ins_mousescroll(int dir)
9588 {
9589     pos_T	tpos;
9590     win_T	*old_curwin = curwin, *wp;
9591 # ifdef FEAT_INS_EXPAND
9592     int		did_scroll = FALSE;
9593 # endif
9594 
9595     tpos = curwin->w_cursor;
9596 
9597     if (mouse_row >= 0 && mouse_col >= 0)
9598     {
9599 	int row, col;
9600 
9601 	row = mouse_row;
9602 	col = mouse_col;
9603 
9604 	/* find the window at the pointer coordinates */
9605 	wp = mouse_find_win(&row, &col);
9606 	if (wp == NULL)
9607 	    return;
9608 	curwin = wp;
9609 	curbuf = curwin->w_buffer;
9610     }
9611     if (curwin == old_curwin)
9612 	undisplay_dollar();
9613 
9614 # ifdef FEAT_INS_EXPAND
9615     /* Don't scroll the window in which completion is being done. */
9616     if (!pum_visible() || curwin != old_curwin)
9617 # endif
9618     {
9619 	if (dir == MSCR_DOWN || dir == MSCR_UP)
9620 	{
9621 	    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
9622 		scroll_redraw(dir,
9623 			(long)(curwin->w_botline - curwin->w_topline));
9624 	    else
9625 		scroll_redraw(dir, 3L);
9626 	}
9627 #ifdef FEAT_GUI
9628 	else
9629 	{
9630 	    int val, step = 6;
9631 
9632 	    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
9633 		step = curwin->w_width;
9634 	    val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step);
9635 	    if (val < 0)
9636 		val = 0;
9637 	    gui_do_horiz_scroll(val, TRUE);
9638 	}
9639 #endif
9640 # ifdef FEAT_INS_EXPAND
9641 	did_scroll = TRUE;
9642 # endif
9643     }
9644 
9645     curwin->w_redr_status = TRUE;
9646 
9647     curwin = old_curwin;
9648     curbuf = curwin->w_buffer;
9649 
9650 # ifdef FEAT_INS_EXPAND
9651     /* The popup menu may overlay the window, need to redraw it.
9652      * TODO: Would be more efficient to only redraw the windows that are
9653      * overlapped by the popup menu. */
9654     if (pum_visible() && did_scroll)
9655     {
9656 	redraw_all_later(NOT_VALID);
9657 	ins_compl_show_pum();
9658     }
9659 # endif
9660 
9661     if (!EQUAL_POS(curwin->w_cursor, tpos))
9662     {
9663 	start_arrow(&tpos);
9664 # ifdef FEAT_CINDENT
9665 	can_cindent = TRUE;
9666 # endif
9667     }
9668 }
9669 #endif
9670 
9671 /*
9672  * Handle receiving P_PS: start paste mode.  Inserts the following text up to
9673  * P_PE literally.
9674  * When "drop" is TRUE then consume the text and drop it.
9675  */
9676     int
9677 bracketed_paste(paste_mode_T mode, int drop, garray_T *gap)
9678 {
9679     int		c;
9680     char_u	buf[NUMBUFLEN + MB_MAXBYTES];
9681     int		idx = 0;
9682     char_u	*end = find_termcode((char_u *)"PE");
9683     int		ret_char = -1;
9684     int		save_allow_keys = allow_keys;
9685     int		save_paste = p_paste;
9686 
9687     /* If the end code is too long we can't detect it, read everything. */
9688     if (STRLEN(end) >= NUMBUFLEN)
9689 	end = NULL;
9690     ++no_mapping;
9691     allow_keys = 0;
9692     if (!p_paste)
9693 	// Also have the side effects of setting 'paste' to make it work much
9694 	// faster.
9695 	set_option_value((char_u *)"paste", TRUE, NULL, 0);
9696 
9697     for (;;)
9698     {
9699 	// When the end is not defined read everything there is.
9700 	if (end == NULL && vpeekc() == NUL)
9701 	    break;
9702 	do
9703 	{
9704 	    c = vgetc();
9705 	} while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR);
9706 	if (c == NUL || got_int)
9707 	    // When CTRL-C was encountered the typeahead will be flushed and we
9708 	    // won't get the end sequence.
9709 	    break;
9710 
9711 #ifdef FEAT_MBYTE
9712 	if (has_mbyte)
9713 	    idx += (*mb_char2bytes)(c, buf + idx);
9714 	else
9715 #endif
9716 	    buf[idx++] = c;
9717 	buf[idx] = NUL;
9718 	if (end != NULL && STRNCMP(buf, end, idx) == 0)
9719 	{
9720 	    if (end[idx] == NUL)
9721 		break; /* Found the end of paste code. */
9722 	    continue;
9723 	}
9724 	if (!drop)
9725 	{
9726 	    switch (mode)
9727 	    {
9728 		case PASTE_CMDLINE:
9729 		    put_on_cmdline(buf, idx, TRUE);
9730 		    break;
9731 
9732 		case PASTE_EX:
9733 		    if (gap != NULL && ga_grow(gap, idx) == OK)
9734 		    {
9735 			mch_memmove((char *)gap->ga_data + gap->ga_len,
9736 							     buf, (size_t)idx);
9737 			gap->ga_len += idx;
9738 		    }
9739 		    break;
9740 
9741 		case PASTE_INSERT:
9742 		    if (stop_arrow() == OK)
9743 		    {
9744 			c = buf[0];
9745 			if (idx == 1 && (c == CAR || c == K_KENTER || c == NL))
9746 			    ins_eol(c);
9747 			else
9748 			{
9749 			    ins_char_bytes(buf, idx);
9750 			    AppendToRedobuffLit(buf, idx);
9751 			}
9752 		    }
9753 		    break;
9754 
9755 		case PASTE_ONE_CHAR:
9756 		    if (ret_char == -1)
9757 		    {
9758 #ifdef FEAT_MBYTE
9759 			if (has_mbyte)
9760 			    ret_char = (*mb_ptr2char)(buf);
9761 			else
9762 #endif
9763 			    ret_char = buf[0];
9764 		    }
9765 		    break;
9766 	    }
9767 	}
9768 	idx = 0;
9769     }
9770 
9771     --no_mapping;
9772     allow_keys = save_allow_keys;
9773     if (!save_paste)
9774 	set_option_value((char_u *)"paste", FALSE, NULL, 0);
9775 
9776     return ret_char;
9777 }
9778 
9779 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
9780     static void
9781 ins_tabline(int c)
9782 {
9783     /* We will be leaving the current window, unless closing another tab. */
9784     if (c != K_TABMENU || current_tabmenu != TABLINE_MENU_CLOSE
9785 		|| (current_tab != 0 && current_tab != tabpage_index(curtab)))
9786     {
9787 	undisplay_dollar();
9788 	start_arrow(&curwin->w_cursor);
9789 # ifdef FEAT_CINDENT
9790 	can_cindent = TRUE;
9791 # endif
9792     }
9793 
9794     if (c == K_TABLINE)
9795 	goto_tabpage(current_tab);
9796     else
9797     {
9798 	handle_tabmenu();
9799 	redraw_statuslines();	/* will redraw the tabline when needed */
9800     }
9801 }
9802 #endif
9803 
9804 #if defined(FEAT_GUI) || defined(PROTO)
9805     void
9806 ins_scroll(void)
9807 {
9808     pos_T	tpos;
9809 
9810     undisplay_dollar();
9811     tpos = curwin->w_cursor;
9812     if (gui_do_scroll())
9813     {
9814 	start_arrow(&tpos);
9815 # ifdef FEAT_CINDENT
9816 	can_cindent = TRUE;
9817 # endif
9818     }
9819 }
9820 
9821     void
9822 ins_horscroll(void)
9823 {
9824     pos_T	tpos;
9825 
9826     undisplay_dollar();
9827     tpos = curwin->w_cursor;
9828     if (gui_do_horiz_scroll(scrollbar_value, FALSE))
9829     {
9830 	start_arrow(&tpos);
9831 # ifdef FEAT_CINDENT
9832 	can_cindent = TRUE;
9833 # endif
9834     }
9835 }
9836 #endif
9837 
9838     static void
9839 ins_left(
9840     int	    end_change) /* end undoable change */
9841 {
9842     pos_T	tpos;
9843 
9844 #ifdef FEAT_FOLDING
9845     if ((fdo_flags & FDO_HOR) && KeyTyped)
9846 	foldOpenCursor();
9847 #endif
9848     undisplay_dollar();
9849     tpos = curwin->w_cursor;
9850     if (oneleft() == OK)
9851     {
9852 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
9853 	/* Only call start_arrow() when not busy with preediting, it will
9854 	 * break undo.  K_LEFT is inserted in im_correct_cursor(). */
9855 	if (p_imst == IM_OVER_THE_SPOT || !im_is_preediting())
9856 #endif
9857 	{
9858 	    start_arrow_with_change(&tpos, end_change);
9859 	    if (!end_change)
9860 		AppendCharToRedobuff(K_LEFT);
9861 	}
9862 #ifdef FEAT_RIGHTLEFT
9863 	/* If exit reversed string, position is fixed */
9864 	if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
9865 	    revins_legal++;
9866 	revins_chars++;
9867 #endif
9868     }
9869 
9870     /*
9871      * if 'whichwrap' set for cursor in insert mode may go to
9872      * previous line
9873      */
9874     else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
9875     {
9876 	/* always break undo when moving upwards/downwards, else undo may break */
9877 	start_arrow(&tpos);
9878 	--(curwin->w_cursor.lnum);
9879 	coladvance((colnr_T)MAXCOL);
9880 	curwin->w_set_curswant = TRUE;	/* so we stay at the end */
9881     }
9882     else
9883 	vim_beep(BO_CRSR);
9884     dont_sync_undo = FALSE;
9885 }
9886 
9887     static void
9888 ins_home(int c)
9889 {
9890     pos_T	tpos;
9891 
9892 #ifdef FEAT_FOLDING
9893     if ((fdo_flags & FDO_HOR) && KeyTyped)
9894 	foldOpenCursor();
9895 #endif
9896     undisplay_dollar();
9897     tpos = curwin->w_cursor;
9898     if (c == K_C_HOME)
9899 	curwin->w_cursor.lnum = 1;
9900     curwin->w_cursor.col = 0;
9901 #ifdef FEAT_VIRTUALEDIT
9902     curwin->w_cursor.coladd = 0;
9903 #endif
9904     curwin->w_curswant = 0;
9905     start_arrow(&tpos);
9906 }
9907 
9908     static void
9909 ins_end(int c)
9910 {
9911     pos_T	tpos;
9912 
9913 #ifdef FEAT_FOLDING
9914     if ((fdo_flags & FDO_HOR) && KeyTyped)
9915 	foldOpenCursor();
9916 #endif
9917     undisplay_dollar();
9918     tpos = curwin->w_cursor;
9919     if (c == K_C_END)
9920 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
9921     coladvance((colnr_T)MAXCOL);
9922     curwin->w_curswant = MAXCOL;
9923 
9924     start_arrow(&tpos);
9925 }
9926 
9927     static void
9928 ins_s_left(void)
9929 {
9930 #ifdef FEAT_FOLDING
9931     if ((fdo_flags & FDO_HOR) && KeyTyped)
9932 	foldOpenCursor();
9933 #endif
9934     undisplay_dollar();
9935     if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
9936     {
9937 	start_arrow(&curwin->w_cursor);
9938 	(void)bck_word(1L, FALSE, FALSE);
9939 	curwin->w_set_curswant = TRUE;
9940     }
9941     else
9942 	vim_beep(BO_CRSR);
9943 }
9944 
9945     static void
9946 ins_right(
9947     int	    end_change) /* end undoable change */
9948 {
9949 #ifdef FEAT_FOLDING
9950     if ((fdo_flags & FDO_HOR) && KeyTyped)
9951 	foldOpenCursor();
9952 #endif
9953     undisplay_dollar();
9954     if (gchar_cursor() != NUL
9955 #ifdef FEAT_VIRTUALEDIT
9956 	    || virtual_active()
9957 #endif
9958 	    )
9959     {
9960 	start_arrow_with_change(&curwin->w_cursor, end_change);
9961 	if (!end_change)
9962 	    AppendCharToRedobuff(K_RIGHT);
9963 	curwin->w_set_curswant = TRUE;
9964 #ifdef FEAT_VIRTUALEDIT
9965 	if (virtual_active())
9966 	    oneright();
9967 	else
9968 #endif
9969 	{
9970 #ifdef FEAT_MBYTE
9971 	    if (has_mbyte)
9972 		curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor());
9973 	    else
9974 #endif
9975 		++curwin->w_cursor.col;
9976 	}
9977 
9978 #ifdef FEAT_RIGHTLEFT
9979 	revins_legal++;
9980 	if (revins_chars)
9981 	    revins_chars--;
9982 #endif
9983     }
9984     /* if 'whichwrap' set for cursor in insert mode, may move the
9985      * cursor to the next line */
9986     else if (vim_strchr(p_ww, ']') != NULL
9987 	    && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
9988     {
9989 	start_arrow(&curwin->w_cursor);
9990 	curwin->w_set_curswant = TRUE;
9991 	++curwin->w_cursor.lnum;
9992 	curwin->w_cursor.col = 0;
9993     }
9994     else
9995 	vim_beep(BO_CRSR);
9996     dont_sync_undo = FALSE;
9997 }
9998 
9999     static void
10000 ins_s_right(void)
10001 {
10002 #ifdef FEAT_FOLDING
10003     if ((fdo_flags & FDO_HOR) && KeyTyped)
10004 	foldOpenCursor();
10005 #endif
10006     undisplay_dollar();
10007     if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
10008 	    || gchar_cursor() != NUL)
10009     {
10010 	start_arrow(&curwin->w_cursor);
10011 	(void)fwd_word(1L, FALSE, 0);
10012 	curwin->w_set_curswant = TRUE;
10013     }
10014     else
10015 	vim_beep(BO_CRSR);
10016 }
10017 
10018     static void
10019 ins_up(
10020     int		startcol)	/* when TRUE move to Insstart.col */
10021 {
10022     pos_T	tpos;
10023     linenr_T	old_topline = curwin->w_topline;
10024 #ifdef FEAT_DIFF
10025     int		old_topfill = curwin->w_topfill;
10026 #endif
10027 
10028     undisplay_dollar();
10029     tpos = curwin->w_cursor;
10030     if (cursor_up(1L, TRUE) == OK)
10031     {
10032 	if (startcol)
10033 	    coladvance(getvcol_nolist(&Insstart));
10034 	if (old_topline != curwin->w_topline
10035 #ifdef FEAT_DIFF
10036 		|| old_topfill != curwin->w_topfill
10037 #endif
10038 		)
10039 	    redraw_later(VALID);
10040 	start_arrow(&tpos);
10041 #ifdef FEAT_CINDENT
10042 	can_cindent = TRUE;
10043 #endif
10044     }
10045     else
10046 	vim_beep(BO_CRSR);
10047 }
10048 
10049     static void
10050 ins_pageup(void)
10051 {
10052     pos_T	tpos;
10053 
10054     undisplay_dollar();
10055 
10056     if (mod_mask & MOD_MASK_CTRL)
10057     {
10058 	/* <C-PageUp>: tab page back */
10059 	if (first_tabpage->tp_next != NULL)
10060 	{
10061 	    start_arrow(&curwin->w_cursor);
10062 	    goto_tabpage(-1);
10063 	}
10064 	return;
10065     }
10066 
10067     tpos = curwin->w_cursor;
10068     if (onepage(BACKWARD, 1L) == OK)
10069     {
10070 	start_arrow(&tpos);
10071 #ifdef FEAT_CINDENT
10072 	can_cindent = TRUE;
10073 #endif
10074     }
10075     else
10076 	vim_beep(BO_CRSR);
10077 }
10078 
10079     static void
10080 ins_down(
10081     int		startcol)	/* when TRUE move to Insstart.col */
10082 {
10083     pos_T	tpos;
10084     linenr_T	old_topline = curwin->w_topline;
10085 #ifdef FEAT_DIFF
10086     int		old_topfill = curwin->w_topfill;
10087 #endif
10088 
10089     undisplay_dollar();
10090     tpos = curwin->w_cursor;
10091     if (cursor_down(1L, TRUE) == OK)
10092     {
10093 	if (startcol)
10094 	    coladvance(getvcol_nolist(&Insstart));
10095 	if (old_topline != curwin->w_topline
10096 #ifdef FEAT_DIFF
10097 		|| old_topfill != curwin->w_topfill
10098 #endif
10099 		)
10100 	    redraw_later(VALID);
10101 	start_arrow(&tpos);
10102 #ifdef FEAT_CINDENT
10103 	can_cindent = TRUE;
10104 #endif
10105     }
10106     else
10107 	vim_beep(BO_CRSR);
10108 }
10109 
10110     static void
10111 ins_pagedown(void)
10112 {
10113     pos_T	tpos;
10114 
10115     undisplay_dollar();
10116 
10117     if (mod_mask & MOD_MASK_CTRL)
10118     {
10119 	/* <C-PageDown>: tab page forward */
10120 	if (first_tabpage->tp_next != NULL)
10121 	{
10122 	    start_arrow(&curwin->w_cursor);
10123 	    goto_tabpage(0);
10124 	}
10125 	return;
10126     }
10127 
10128     tpos = curwin->w_cursor;
10129     if (onepage(FORWARD, 1L) == OK)
10130     {
10131 	start_arrow(&tpos);
10132 #ifdef FEAT_CINDENT
10133 	can_cindent = TRUE;
10134 #endif
10135     }
10136     else
10137 	vim_beep(BO_CRSR);
10138 }
10139 
10140 #ifdef FEAT_DND
10141     static void
10142 ins_drop(void)
10143 {
10144     do_put('~', BACKWARD, 1L, PUT_CURSEND);
10145 }
10146 #endif
10147 
10148 /*
10149  * Handle TAB in Insert or Replace mode.
10150  * Return TRUE when the TAB needs to be inserted like a normal character.
10151  */
10152     static int
10153 ins_tab(void)
10154 {
10155     int		ind;
10156     int		i;
10157     int		temp;
10158 
10159     if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
10160 	Insstart_blank_vcol = get_nolist_virtcol();
10161     if (echeck_abbr(TAB + ABBR_OFF))
10162 	return FALSE;
10163 
10164     ind = inindent(0);
10165 #ifdef FEAT_CINDENT
10166     if (ind)
10167 	can_cindent = FALSE;
10168 #endif
10169 
10170     /*
10171      * When nothing special, insert TAB like a normal character.
10172      */
10173     if (!curbuf->b_p_et
10174 #ifdef FEAT_VARTABS
10175 	    && !(p_sta && ind
10176 		/* These five lines mean 'tabstop' != 'shiftwidth' */
10177 		&& ((tabstop_count(curbuf->b_p_vts_array) > 1)
10178 		    || (tabstop_count(curbuf->b_p_vts_array) == 1
10179 		        && tabstop_first(curbuf->b_p_vts_array)
10180 						       != get_sw_value(curbuf))
10181 	            || (tabstop_count(curbuf->b_p_vts_array) == 0
10182 		        && curbuf->b_p_ts != get_sw_value(curbuf))))
10183 	    && tabstop_count(curbuf->b_p_vsts_array) == 0
10184 #else
10185 	    && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf))
10186 #endif
10187 	    && get_sts_value() == 0)
10188 	return TRUE;
10189 
10190     if (stop_arrow() == FAIL)
10191 	return TRUE;
10192 
10193     did_ai = FALSE;
10194 #ifdef FEAT_SMARTINDENT
10195     did_si = FALSE;
10196     can_si = FALSE;
10197     can_si_back = FALSE;
10198 #endif
10199     AppendToRedobuff((char_u *)"\t");
10200 
10201 #ifdef FEAT_VARTABS
10202     if (p_sta && ind)		/* insert tab in indent, use 'shiftwidth' */
10203     {
10204 	temp = (int)get_sw_value(curbuf);
10205 	temp -= get_nolist_virtcol() % temp;
10206     }
10207     else if (tabstop_count(curbuf->b_p_vsts_array) > 0 || curbuf->b_p_sts != 0)
10208 	                        /* use 'softtabstop' when set */
10209 	temp = tabstop_padding(get_nolist_virtcol(), get_sts_value(),
10210 						     curbuf->b_p_vsts_array);
10211     else			/* otherwise use 'tabstop' */
10212 	temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_ts,
10213 						     curbuf->b_p_vts_array);
10214 #else
10215     if (p_sta && ind)		/* insert tab in indent, use 'shiftwidth' */
10216 	temp = (int)get_sw_value(curbuf);
10217     else if (curbuf->b_p_sts != 0) /* use 'softtabstop' when set */
10218 	temp = (int)get_sts_value();
10219     else			/* otherwise use 'tabstop' */
10220 	temp = (int)curbuf->b_p_ts;
10221     temp -= get_nolist_virtcol() % temp;
10222 #endif
10223 
10224     /*
10225      * Insert the first space with ins_char().	It will delete one char in
10226      * replace mode.  Insert the rest with ins_str(); it will not delete any
10227      * chars.  For VREPLACE mode, we use ins_char() for all characters.
10228      */
10229     ins_char(' ');
10230     while (--temp > 0)
10231     {
10232 	if (State & VREPLACE_FLAG)
10233 	    ins_char(' ');
10234 	else
10235 	{
10236 	    ins_str((char_u *)" ");
10237 	    if (State & REPLACE_FLAG)	    /* no char replaced */
10238 		replace_push(NUL);
10239 	}
10240     }
10241 
10242     /*
10243      * When 'expandtab' not set: Replace spaces by TABs where possible.
10244      */
10245 #ifdef FEAT_VARTABS
10246     if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0
10247                             || get_sts_value() > 0
10248 			    || (p_sta && ind)))
10249 #else
10250     if (!curbuf->b_p_et && (get_sts_value() || (p_sta && ind)))
10251 #endif
10252     {
10253 	char_u		*ptr;
10254 	char_u		*saved_line = NULL;	/* init for GCC */
10255 	pos_T		pos;
10256 	pos_T		fpos;
10257 	pos_T		*cursor;
10258 	colnr_T		want_vcol, vcol;
10259 	int		change_col = -1;
10260 	int		save_list = curwin->w_p_list;
10261 
10262 	/*
10263 	 * Get the current line.  For VREPLACE mode, don't make real changes
10264 	 * yet, just work on a copy of the line.
10265 	 */
10266 	if (State & VREPLACE_FLAG)
10267 	{
10268 	    pos = curwin->w_cursor;
10269 	    cursor = &pos;
10270 	    saved_line = vim_strsave(ml_get_curline());
10271 	    if (saved_line == NULL)
10272 		return FALSE;
10273 	    ptr = saved_line + pos.col;
10274 	}
10275 	else
10276 	{
10277 	    ptr = ml_get_cursor();
10278 	    cursor = &curwin->w_cursor;
10279 	}
10280 
10281 	/* When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. */
10282 	if (vim_strchr(p_cpo, CPO_LISTWM) == NULL)
10283 	    curwin->w_p_list = FALSE;
10284 
10285 	/* Find first white before the cursor */
10286 	fpos = curwin->w_cursor;
10287 	while (fpos.col > 0 && VIM_ISWHITE(ptr[-1]))
10288 	{
10289 	    --fpos.col;
10290 	    --ptr;
10291 	}
10292 
10293 	/* In Replace mode, don't change characters before the insert point. */
10294 	if ((State & REPLACE_FLAG)
10295 		&& fpos.lnum == Insstart.lnum
10296 		&& fpos.col < Insstart.col)
10297 	{
10298 	    ptr += Insstart.col - fpos.col;
10299 	    fpos.col = Insstart.col;
10300 	}
10301 
10302 	/* compute virtual column numbers of first white and cursor */
10303 	getvcol(curwin, &fpos, &vcol, NULL, NULL);
10304 	getvcol(curwin, cursor, &want_vcol, NULL, NULL);
10305 
10306 	/* Use as many TABs as possible.  Beware of 'breakindent', 'showbreak'
10307 	 * and 'linebreak' adding extra virtual columns. */
10308 	while (VIM_ISWHITE(*ptr))
10309 	{
10310 	    i = lbr_chartabsize(NULL, (char_u *)"\t", vcol);
10311 	    if (vcol + i > want_vcol)
10312 		break;
10313 	    if (*ptr != TAB)
10314 	    {
10315 		*ptr = TAB;
10316 		if (change_col < 0)
10317 		{
10318 		    change_col = fpos.col;  /* Column of first change */
10319 		    /* May have to adjust Insstart */
10320 		    if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col)
10321 			Insstart.col = fpos.col;
10322 		}
10323 	    }
10324 	    ++fpos.col;
10325 	    ++ptr;
10326 	    vcol += i;
10327 	}
10328 
10329 	if (change_col >= 0)
10330 	{
10331 	    int repl_off = 0;
10332 	    char_u *line = ptr;
10333 
10334 	    /* Skip over the spaces we need. */
10335 	    while (vcol < want_vcol && *ptr == ' ')
10336 	    {
10337 		vcol += lbr_chartabsize(line, ptr, vcol);
10338 		++ptr;
10339 		++repl_off;
10340 	    }
10341 	    if (vcol > want_vcol)
10342 	    {
10343 		/* Must have a char with 'showbreak' just before it. */
10344 		--ptr;
10345 		--repl_off;
10346 	    }
10347 	    fpos.col += repl_off;
10348 
10349 	    /* Delete following spaces. */
10350 	    i = cursor->col - fpos.col;
10351 	    if (i > 0)
10352 	    {
10353 		STRMOVE(ptr, ptr + i);
10354 		/* correct replace stack. */
10355 		if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG))
10356 		    for (temp = i; --temp >= 0; )
10357 			replace_join(repl_off);
10358 #ifdef FEAT_TEXT_PROP
10359 		curbuf->b_ml.ml_line_len -= i;
10360 #endif
10361 	    }
10362 #ifdef FEAT_NETBEANS_INTG
10363 	    if (netbeans_active())
10364 	    {
10365 		netbeans_removed(curbuf, fpos.lnum, cursor->col, (long)(i + 1));
10366 		netbeans_inserted(curbuf, fpos.lnum, cursor->col,
10367 							   (char_u *)"\t", 1);
10368 	    }
10369 #endif
10370 	    cursor->col -= i;
10371 
10372 	    /*
10373 	     * In VREPLACE mode, we haven't changed anything yet.  Do it now by
10374 	     * backspacing over the changed spacing and then inserting the new
10375 	     * spacing.
10376 	     */
10377 	    if (State & VREPLACE_FLAG)
10378 	    {
10379 		/* Backspace from real cursor to change_col */
10380 		backspace_until_column(change_col);
10381 
10382 		/* Insert each char in saved_line from changed_col to
10383 		 * ptr-cursor */
10384 		ins_bytes_len(saved_line + change_col,
10385 						    cursor->col - change_col);
10386 	    }
10387 	}
10388 
10389 	if (State & VREPLACE_FLAG)
10390 	    vim_free(saved_line);
10391 	curwin->w_p_list = save_list;
10392     }
10393 
10394     return FALSE;
10395 }
10396 
10397 /*
10398  * Handle CR or NL in insert mode.
10399  * Return FAIL when out of memory or can't undo.
10400  */
10401     static int
10402 ins_eol(int c)
10403 {
10404     int	    i;
10405 
10406     if (echeck_abbr(c + ABBR_OFF))
10407 	return OK;
10408     if (stop_arrow() == FAIL)
10409 	return FAIL;
10410     undisplay_dollar();
10411 
10412     /*
10413      * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
10414      * character under the cursor.  Only push a NUL on the replace stack,
10415      * nothing to put back when the NL is deleted.
10416      */
10417     if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG))
10418 	replace_push(NUL);
10419 
10420     /*
10421      * In VREPLACE mode, a NL replaces the rest of the line, and starts
10422      * replacing the next line, so we push all of the characters left on the
10423      * line onto the replace stack.  This is not done here though, it is done
10424      * in open_line().
10425      */
10426 
10427 #ifdef FEAT_VIRTUALEDIT
10428     /* Put cursor on NUL if on the last char and coladd is 1 (happens after
10429      * CTRL-O). */
10430     if (virtual_active() && curwin->w_cursor.coladd > 0)
10431 	coladvance(getviscol());
10432 #endif
10433 
10434 #ifdef FEAT_RIGHTLEFT
10435 # ifdef FEAT_FKMAP
10436     if (p_altkeymap && p_fkmap)
10437 	fkmap(NL);
10438 # endif
10439     /* NL in reverse insert will always start in the end of
10440      * current line. */
10441     if (revins_on)
10442 	curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
10443 #endif
10444 
10445     AppendToRedobuff(NL_STR);
10446     i = open_line(FORWARD,
10447 #ifdef FEAT_COMMENTS
10448 	    has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
10449 #endif
10450 	    0, old_indent);
10451     old_indent = 0;
10452 #ifdef FEAT_CINDENT
10453     can_cindent = TRUE;
10454 #endif
10455 #ifdef FEAT_FOLDING
10456     /* When inserting a line the cursor line must never be in a closed fold. */
10457     foldOpenCursor();
10458 #endif
10459 
10460     return i;
10461 }
10462 
10463 #ifdef FEAT_DIGRAPHS
10464 /*
10465  * Handle digraph in insert mode.
10466  * Returns character still to be inserted, or NUL when nothing remaining to be
10467  * done.
10468  */
10469     static int
10470 ins_digraph(void)
10471 {
10472     int	    c;
10473     int	    cc;
10474     int	    did_putchar = FALSE;
10475 
10476     pc_status = PC_STATUS_UNSET;
10477     if (redrawing() && !char_avail())
10478     {
10479 	/* may need to redraw when no more chars available now */
10480 	ins_redraw(FALSE);
10481 
10482 	edit_putchar('?', TRUE);
10483 	did_putchar = TRUE;
10484 #ifdef FEAT_CMDL_INFO
10485 	add_to_showcmd_c(Ctrl_K);
10486 #endif
10487     }
10488 
10489 #ifdef USE_ON_FLY_SCROLL
10490     dont_scroll = TRUE;		/* disallow scrolling here */
10491 #endif
10492 
10493     /* don't map the digraph chars. This also prevents the
10494      * mode message to be deleted when ESC is hit */
10495     ++no_mapping;
10496     ++allow_keys;
10497     c = plain_vgetc();
10498     --no_mapping;
10499     --allow_keys;
10500     if (did_putchar)
10501 	/* when the line fits in 'columns' the '?' is at the start of the next
10502 	 * line and will not be removed by the redraw */
10503 	edit_unputchar();
10504 
10505     if (IS_SPECIAL(c) || mod_mask)	    /* special key */
10506     {
10507 #ifdef FEAT_CMDL_INFO
10508 	clear_showcmd();
10509 #endif
10510 	insert_special(c, TRUE, FALSE);
10511 	return NUL;
10512     }
10513     if (c != ESC)
10514     {
10515 	did_putchar = FALSE;
10516 	if (redrawing() && !char_avail())
10517 	{
10518 	    /* may need to redraw when no more chars available now */
10519 	    ins_redraw(FALSE);
10520 
10521 	    if (char2cells(c) == 1)
10522 	    {
10523 		ins_redraw(FALSE);
10524 		edit_putchar(c, TRUE);
10525 		did_putchar = TRUE;
10526 	    }
10527 #ifdef FEAT_CMDL_INFO
10528 	    add_to_showcmd_c(c);
10529 #endif
10530 	}
10531 	++no_mapping;
10532 	++allow_keys;
10533 	cc = plain_vgetc();
10534 	--no_mapping;
10535 	--allow_keys;
10536 	if (did_putchar)
10537 	    /* when the line fits in 'columns' the '?' is at the start of the
10538 	     * next line and will not be removed by a redraw */
10539 	    edit_unputchar();
10540 	if (cc != ESC)
10541 	{
10542 	    AppendToRedobuff((char_u *)CTRL_V_STR);
10543 	    c = getdigraph(c, cc, TRUE);
10544 #ifdef FEAT_CMDL_INFO
10545 	    clear_showcmd();
10546 #endif
10547 	    return c;
10548 	}
10549     }
10550 #ifdef FEAT_CMDL_INFO
10551     clear_showcmd();
10552 #endif
10553     return NUL;
10554 }
10555 #endif
10556 
10557 /*
10558  * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
10559  * Returns the char to be inserted, or NUL if none found.
10560  */
10561     int
10562 ins_copychar(linenr_T lnum)
10563 {
10564     int	    c;
10565     int	    temp;
10566     char_u  *ptr, *prev_ptr;
10567     char_u  *line;
10568 
10569     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
10570     {
10571 	vim_beep(BO_COPY);
10572 	return NUL;
10573     }
10574 
10575     /* try to advance to the cursor column */
10576     temp = 0;
10577     line = ptr = ml_get(lnum);
10578     prev_ptr = ptr;
10579     validate_virtcol();
10580     while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
10581     {
10582 	prev_ptr = ptr;
10583 	temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp);
10584     }
10585     if ((colnr_T)temp > curwin->w_virtcol)
10586 	ptr = prev_ptr;
10587 
10588 #ifdef FEAT_MBYTE
10589     c = (*mb_ptr2char)(ptr);
10590 #else
10591     c = *ptr;
10592 #endif
10593     if (c == NUL)
10594 	vim_beep(BO_COPY);
10595     return c;
10596 }
10597 
10598 /*
10599  * CTRL-Y or CTRL-E typed in Insert mode.
10600  */
10601     static int
10602 ins_ctrl_ey(int tc)
10603 {
10604     int	    c = tc;
10605 
10606 #ifdef FEAT_INS_EXPAND
10607     if (ctrl_x_mode == CTRL_X_SCROLL)
10608     {
10609 	if (c == Ctrl_Y)
10610 	    scrolldown_clamp();
10611 	else
10612 	    scrollup_clamp();
10613 	redraw_later(VALID);
10614     }
10615     else
10616 #endif
10617     {
10618 	c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1));
10619 	if (c != NUL)
10620 	{
10621 	    long	tw_save;
10622 
10623 	    /* The character must be taken literally, insert like it
10624 	     * was typed after a CTRL-V, and pretend 'textwidth'
10625 	     * wasn't set.  Digits, 'o' and 'x' are special after a
10626 	     * CTRL-V, don't use it for these. */
10627 	    if (c < 256 && !isalnum(c))
10628 		AppendToRedobuff((char_u *)CTRL_V_STR);	/* CTRL-V */
10629 	    tw_save = curbuf->b_p_tw;
10630 	    curbuf->b_p_tw = -1;
10631 	    insert_special(c, TRUE, FALSE);
10632 	    curbuf->b_p_tw = tw_save;
10633 #ifdef FEAT_RIGHTLEFT
10634 	    revins_chars++;
10635 	    revins_legal++;
10636 #endif
10637 	    c = Ctrl_V;	/* pretend CTRL-V is last character */
10638 	    auto_format(FALSE, TRUE);
10639 	}
10640     }
10641     return c;
10642 }
10643 
10644 #ifdef FEAT_SMARTINDENT
10645 /*
10646  * Try to do some very smart auto-indenting.
10647  * Used when inserting a "normal" character.
10648  */
10649     static void
10650 ins_try_si(int c)
10651 {
10652     pos_T	*pos, old_pos;
10653     char_u	*ptr;
10654     int		i;
10655     int		temp;
10656 
10657     /*
10658      * do some very smart indenting when entering '{' or '}'
10659      */
10660     if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
10661     {
10662 	/*
10663 	 * for '}' set indent equal to indent of line containing matching '{'
10664 	 */
10665 	if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
10666 	{
10667 	    old_pos = curwin->w_cursor;
10668 	    /*
10669 	     * If the matching '{' has a ')' immediately before it (ignoring
10670 	     * white-space), then line up with the start of the line
10671 	     * containing the matching '(' if there is one.  This handles the
10672 	     * case where an "if (..\n..) {" statement continues over multiple
10673 	     * lines -- webb
10674 	     */
10675 	    ptr = ml_get(pos->lnum);
10676 	    i = pos->col;
10677 	    if (i > 0)		/* skip blanks before '{' */
10678 		while (--i > 0 && VIM_ISWHITE(ptr[i]))
10679 		    ;
10680 	    curwin->w_cursor.lnum = pos->lnum;
10681 	    curwin->w_cursor.col = i;
10682 	    if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
10683 		curwin->w_cursor = *pos;
10684 	    i = get_indent();
10685 	    curwin->w_cursor = old_pos;
10686 	    if (State & VREPLACE_FLAG)
10687 		change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
10688 	    else
10689 		(void)set_indent(i, SIN_CHANGED);
10690 	}
10691 	else if (curwin->w_cursor.col > 0)
10692 	{
10693 	    /*
10694 	     * when inserting '{' after "O" reduce indent, but not
10695 	     * more than indent of previous line
10696 	     */
10697 	    temp = TRUE;
10698 	    if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
10699 	    {
10700 		old_pos = curwin->w_cursor;
10701 		i = get_indent();
10702 		while (curwin->w_cursor.lnum > 1)
10703 		{
10704 		    ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
10705 
10706 		    /* ignore empty lines and lines starting with '#'. */
10707 		    if (*ptr != '#' && *ptr != NUL)
10708 			break;
10709 		}
10710 		if (get_indent() >= i)
10711 		    temp = FALSE;
10712 		curwin->w_cursor = old_pos;
10713 	    }
10714 	    if (temp)
10715 		shift_line(TRUE, FALSE, 1, TRUE);
10716 	}
10717     }
10718 
10719     /*
10720      * set indent of '#' always to 0
10721      */
10722     if (curwin->w_cursor.col > 0 && can_si && c == '#')
10723     {
10724 	/* remember current indent for next line */
10725 	old_indent = get_indent();
10726 	(void)set_indent(0, SIN_CHANGED);
10727     }
10728 
10729     /* Adjust ai_col, the char at this position can be deleted. */
10730     if (ai_col > curwin->w_cursor.col)
10731 	ai_col = curwin->w_cursor.col;
10732 }
10733 #endif
10734 
10735 /*
10736  * Get the value that w_virtcol would have when 'list' is off.
10737  * Unless 'cpo' contains the 'L' flag.
10738  */
10739     colnr_T
10740 get_nolist_virtcol(void)
10741 {
10742     // check validity of cursor in current buffer
10743     if (curwin->w_buffer == NULL
10744 	|| curwin->w_buffer->b_ml.ml_mfp == NULL
10745 	|| curwin->w_cursor.lnum > curwin->w_buffer->b_ml.ml_line_count)
10746 	return 0;
10747     if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
10748 	return getvcol_nolist(&curwin->w_cursor);
10749     validate_virtcol();
10750     return curwin->w_virtcol;
10751 }
10752 
10753 #if defined(FEAT_EVAL)
10754 /*
10755  * Handle the InsertCharPre autocommand.
10756  * "c" is the character that was typed.
10757  * Return a pointer to allocated memory with the replacement string.
10758  * Return NULL to continue inserting "c".
10759  */
10760     static char_u *
10761 do_insert_char_pre(int c)
10762 {
10763     char_u	*res;
10764     char_u	buf[MB_MAXBYTES + 1];
10765     int		save_State = State;
10766 
10767     /* Return quickly when there is nothing to do. */
10768     if (!has_insertcharpre())
10769 	return NULL;
10770 
10771 # ifdef FEAT_MBYTE
10772     if (has_mbyte)
10773 	buf[(*mb_char2bytes)(c, buf)] = NUL;
10774     else
10775 # endif
10776     {
10777 	buf[0] = c;
10778 	buf[1] = NUL;
10779     }
10780 
10781     /* Lock the text to avoid weird things from happening. */
10782     ++textlock;
10783     set_vim_var_string(VV_CHAR, buf, -1);  /* set v:char */
10784 
10785     res = NULL;
10786     if (ins_apply_autocmds(EVENT_INSERTCHARPRE))
10787     {
10788 	/* Get the value of v:char.  It may be empty or more than one
10789 	 * character.  Only use it when changed, otherwise continue with the
10790 	 * original character to avoid breaking autoindent. */
10791 	if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0)
10792 	    res = vim_strsave(get_vim_var_str(VV_CHAR));
10793     }
10794 
10795     set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
10796     --textlock;
10797 
10798     // Restore the State, it may have been changed.
10799     State = save_State;
10800 
10801     return res;
10802 }
10803 #endif
10804 
10805 /*
10806  * Trigger "event" and take care of fixing undo.
10807  */
10808     static int
10809 ins_apply_autocmds(event_T event)
10810 {
10811     varnumber_T	tick = CHANGEDTICK(curbuf);
10812     int r;
10813 
10814     r = apply_autocmds(event, NULL, NULL, FALSE, curbuf);
10815 
10816     // If u_savesub() was called then we are not prepared to start
10817     // a new line.  Call u_save() with no contents to fix that.
10818     if (tick != CHANGEDTICK(curbuf))
10819 	u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1));
10820 
10821     return r;
10822 }
10823