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