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