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