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