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