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