blob: 3370a28f2dd572dc33ecba08daedda542004c4e5 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +000033#define CTRL_X_FUNCTION 12
Bram Moolenaarf75a9632005-09-13 21:20:47 +000034#define CTRL_X_OMNI 13
Bram Moolenaar488c6512005-08-11 20:09:58 +000035#define CTRL_X_SPELL 14
36#define CTRL_X_LOCAL_MSG 15 /* only used in "ctrl_x_msgs" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000037
Bram Moolenaar071d4272004-06-13 20:20:40 +000038#define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
39
40static char *ctrl_x_msgs[] =
41{
42 N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +000043 N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
Bram Moolenaar4be06f92005-07-29 22:36:03 +000044 NULL,
Bram Moolenaar071d4272004-06-13 20:20:40 +000045 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)"),
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +000053 N_(" Command-line completion (^V^N^P)"),
54 N_(" User defined completion (^U^N^P)"),
Bram Moolenaarf75a9632005-09-13 21:20:47 +000055 N_(" Omni completion (^O^N^P)"),
Bram Moolenaar910f66f2006-04-05 20:41:53 +000056 N_(" Spelling suggestion (s^N^P)"),
Bram Moolenaar4be06f92005-07-29 22:36:03 +000057 N_(" Keyword Local completion (^N^P)"),
Bram Moolenaar071d4272004-06-13 20:20:40 +000058};
59
Bram Moolenaar0ab2a882009-05-13 10:51:08 +000060static char e_hitend[] = N_("Hit end of paragraph");
Bram Moolenaar071d4272004-06-13 20:20:40 +000061
62/*
63 * Structure used to store one match for insert completion.
64 */
Bram Moolenaard1f56e62006-02-22 21:25:37 +000065typedef struct compl_S compl_T;
66struct compl_S
Bram Moolenaar071d4272004-06-13 20:20:40 +000067{
Bram Moolenaar572cb562005-08-05 21:35:02 +000068 compl_T *cp_next;
69 compl_T *cp_prev;
70 char_u *cp_str; /* matched text */
Bram Moolenaard1f56e62006-02-22 21:25:37 +000071 char cp_icase; /* TRUE or FALSE: ignore case */
Bram Moolenaar39f05632006-03-19 22:15:26 +000072 char_u *(cp_text[CPT_COUNT]); /* text for the menu */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000073 char_u *cp_fname; /* file containing the match, allocated when
74 * cp_flags has FREE_FNAME */
Bram Moolenaar572cb562005-08-05 21:35:02 +000075 int cp_flags; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
76 int cp_number; /* sequence number */
Bram Moolenaar071d4272004-06-13 20:20:40 +000077};
78
Bram Moolenaar572cb562005-08-05 21:35:02 +000079#define ORIGINAL_TEXT (1) /* the original text when the expansion begun */
Bram Moolenaar071d4272004-06-13 20:20:40 +000080#define FREE_FNAME (2)
81
82/*
83 * All the current matches are stored in a list.
Bram Moolenaar4be06f92005-07-29 22:36:03 +000084 * "compl_first_match" points to the start of the list.
85 * "compl_curr_match" points to the currently selected entry.
86 * "compl_shown_match" is different from compl_curr_match during
87 * ins_compl_get_exp().
Bram Moolenaar071d4272004-06-13 20:20:40 +000088 */
Bram Moolenaar572cb562005-08-05 21:35:02 +000089static compl_T *compl_first_match = NULL;
90static compl_T *compl_curr_match = NULL;
91static compl_T *compl_shown_match = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000092
Bram Moolenaar779b74b2006-04-10 14:55:34 +000093/* After using a cursor key <Enter> selects a match in the popup menu,
94 * otherwise it inserts a line break. */
95static int compl_enter_selects = FALSE;
96
Bram Moolenaara6557602006-02-04 22:43:20 +000097/* When "compl_leader" is not NULL only matches that start with this string
98 * are used. */
99static char_u *compl_leader = NULL;
100
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000101static int compl_get_longest = FALSE; /* put longest common string
102 in compl_leader */
103
Bram Moolenaara6557602006-02-04 22:43:20 +0000104static int compl_used_match; /* Selected one of the matches. When
105 FALSE the match was edited or using
106 the longest common string. */
107
Bram Moolenaar1423b9d2006-05-07 15:16:06 +0000108static int compl_was_interrupted = FALSE; /* didn't finish finding
109 completions. */
110
111static int compl_restarting = FALSE; /* don't insert match */
112
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000113/* When the first completion is done "compl_started" is set. When it's
114 * FALSE the word to be completed must be located. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000115static int compl_started = FALSE;
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000116
Bram Moolenaar031e0dd2009-07-09 16:15:16 +0000117/* Set when doing something for completion that may call edit() recursively,
118 * which is not allowed. */
119static int compl_busy = FALSE;
120
Bram Moolenaar572cb562005-08-05 21:35:02 +0000121static int compl_matches = 0;
122static char_u *compl_pattern = NULL;
123static int compl_direction = FORWARD;
124static int compl_shows_dir = FORWARD;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000125static int compl_pending = 0; /* > 1 for postponed CTRL-N */
Bram Moolenaar572cb562005-08-05 21:35:02 +0000126static pos_T compl_startpos;
127static colnr_T compl_col = 0; /* column where the text starts
128 * that is being completed */
Bram Moolenaar572cb562005-08-05 21:35:02 +0000129static char_u *compl_orig_text = NULL; /* text as it was before
130 * completion started */
131static int compl_cont_mode = 0;
132static expand_T compl_xp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000134static void ins_ctrl_x __ARGS((void));
135static int has_compl_option __ARGS((int dict_opt));
Bram Moolenaar711d5b52007-10-19 18:40:51 +0000136static int ins_compl_accept_char __ARGS((int c));
Bram Moolenaar89d40322006-08-29 15:30:07 +0000137static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup));
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000138static int ins_compl_equal __ARGS((compl_T *match, char_u *str, int len));
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000139static void ins_compl_longest_match __ARGS((compl_T *match));
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000140static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int icase));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000141static int ins_compl_make_cyclic __ARGS((void));
Bram Moolenaar1c7715d2005-10-03 22:02:18 +0000142static void ins_compl_upd_pum __ARGS((void));
143static void ins_compl_del_pum __ARGS((void));
Bram Moolenaar280f1262006-01-30 00:14:18 +0000144static int pum_wanted __ARGS((void));
Bram Moolenaar65c923a2006-03-03 22:56:30 +0000145static int pum_enough_matches __ARGS((void));
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000146static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int flags, int thesaurus));
Bram Moolenaar0b238792006-03-02 22:49:12 +0000147static void ins_compl_files __ARGS((int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000148static char_u *find_line_end __ARGS((char_u *ptr));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149static void ins_compl_free __ARGS((void));
150static void ins_compl_clear __ARGS((void));
Bram Moolenaara6557602006-02-04 22:43:20 +0000151static int ins_compl_bs __ARGS((void));
Bram Moolenaar1423b9d2006-05-07 15:16:06 +0000152static void ins_compl_new_leader __ARGS((void));
Bram Moolenaara6557602006-02-04 22:43:20 +0000153static void ins_compl_addleader __ARGS((int c));
Bram Moolenaar0f6c9482009-01-13 11:29:48 +0000154static int ins_compl_len __ARGS((void));
Bram Moolenaar1423b9d2006-05-07 15:16:06 +0000155static void ins_compl_restart __ARGS((void));
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000156static void ins_compl_set_original_text __ARGS((char_u *str));
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000157static void ins_compl_addfrommatch __ARGS((void));
Bram Moolenaar1c7715d2005-10-03 22:02:18 +0000158static int ins_compl_prep __ARGS((int c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));
Bram Moolenaara94bc432006-03-10 21:42:59 +0000160#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
161static void ins_compl_add_list __ARGS((list_T *list));
162#endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000163static int ins_compl_get_exp __ARGS((pos_T *ini));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164static void ins_compl_delete __ARGS((void));
165static void ins_compl_insert __ARGS((void));
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000166static int ins_compl_next __ARGS((int allow_get_expansion, int count, int insert_match));
Bram Moolenaare3226be2005-12-18 22:10:00 +0000167static int ins_compl_key2dir __ARGS((int c));
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000168static int ins_compl_pum_key __ARGS((int c));
Bram Moolenaare3226be2005-12-18 22:10:00 +0000169static int ins_compl_key2count __ARGS((int c));
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000170static int ins_compl_use_match __ARGS((int c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171static int ins_complete __ARGS((int c));
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +0000172static unsigned quote_meta __ARGS((char_u *dest, char_u *str, int len));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173#endif /* FEAT_INS_EXPAND */
174
175#define BACKSPACE_CHAR 1
176#define BACKSPACE_WORD 2
177#define BACKSPACE_WORD_NOT_SPACE 3
178#define BACKSPACE_LINE 4
179
Bram Moolenaar754b5602006-02-09 23:53:20 +0000180static void ins_redraw __ARGS((int ready));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000181static void ins_ctrl_v __ARGS((void));
182static void undisplay_dollar __ARGS((void));
183static void insert_special __ARGS((int, int, int));
Bram Moolenaar97b98102009-11-17 16:41:01 +0000184static void internal_format __ARGS((int textwidth, int second_indent, int flags, int format_only, int c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185static void check_auto_format __ARGS((int));
186static void redo_literal __ARGS((int c));
187static void start_arrow __ARGS((pos_T *end_insert_pos));
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +0000188#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +0000189static void check_spell_redraw __ARGS((void));
Bram Moolenaar8aff23a2005-08-19 20:40:30 +0000190static void spell_back_to_badword __ARGS((void));
Bram Moolenaar6e7c7f32005-08-24 22:16:11 +0000191static int spell_bad_len = 0; /* length of located bad word */
Bram Moolenaar217ad922005-03-20 22:37:15 +0000192#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193static void stop_insert __ARGS((pos_T *end_insert_pos, int esc));
194static int echeck_abbr __ARGS((int));
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000195#if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196static void replace_push_off __ARGS((int c));
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000197#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198static int replace_pop __ARGS((void));
199static void replace_join __ARGS((int off));
200static void replace_pop_ins __ARGS((void));
201#ifdef FEAT_MBYTE
202static void mb_replace_pop_ins __ARGS((int cc));
203#endif
204static void replace_flush __ARGS((void));
Bram Moolenaar0f6c9482009-01-13 11:29:48 +0000205static void replace_do_bs __ARGS((int limit_col));
206static int del_char_after_col __ARGS((int limit_col));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207#ifdef FEAT_CINDENT
208static int cindent_on __ARGS((void));
209#endif
210static void ins_reg __ARGS((void));
211static void ins_ctrl_g __ARGS((void));
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000212static void ins_ctrl_hat __ARGS((void));
Bram Moolenaar488c6512005-08-11 20:09:58 +0000213static int ins_esc __ARGS((long *count, int cmdchar, int nomove));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214#ifdef FEAT_RIGHTLEFT
215static void ins_ctrl_ __ARGS((void));
216#endif
217#ifdef FEAT_VISUAL
218static int ins_start_select __ARGS((int c));
219#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000220static void ins_insert __ARGS((int replaceState));
221static void ins_ctrl_o __ARGS((void));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222static void ins_shift __ARGS((int c, int lastc));
223static void ins_del __ARGS((void));
224static int ins_bs __ARGS((int c, int mode, int *inserted_space_p));
225#ifdef FEAT_MOUSE
226static void ins_mouse __ARGS((int c));
227static void ins_mousescroll __ARGS((int up));
228#endif
Bram Moolenaara23ccb82006-02-27 00:08:02 +0000229#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
230static void ins_tabline __ARGS((int c));
231#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232static void ins_left __ARGS((void));
233static void ins_home __ARGS((int c));
234static void ins_end __ARGS((int c));
235static void ins_s_left __ARGS((void));
236static void ins_right __ARGS((void));
237static void ins_s_right __ARGS((void));
238static void ins_up __ARGS((int startcol));
239static void ins_pageup __ARGS((void));
240static void ins_down __ARGS((int startcol));
241static void ins_pagedown __ARGS((void));
242#ifdef FEAT_DND
243static void ins_drop __ARGS((void));
244#endif
245static int ins_tab __ARGS((void));
246static int ins_eol __ARGS((int c));
247#ifdef FEAT_DIGRAPHS
248static int ins_digraph __ARGS((void));
249#endif
250static int ins_copychar __ARGS((linenr_T lnum));
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000251static int ins_ctrl_ey __ARGS((int tc));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000252#ifdef FEAT_SMARTINDENT
253static void ins_try_si __ARGS((int c));
254#endif
255static colnr_T get_nolist_virtcol __ARGS((void));
256
257static colnr_T Insstart_textlen; /* length of line when insert started */
258static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */
259
260static char_u *last_insert = NULL; /* the text of the previous insert,
261 K_SPECIAL and CSI are escaped */
262static int last_insert_skip; /* nr of chars in front of previous insert */
263static int new_insert_skip; /* nr of chars in front of current insert */
Bram Moolenaar83c465c2005-12-16 21:53:56 +0000264static int did_restart_edit; /* "restart_edit" when calling edit() */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265
266#ifdef FEAT_CINDENT
267static int can_cindent; /* may do cindenting on this line */
268#endif
269
270static int old_indent = 0; /* for ^^D command in insert mode */
271
272#ifdef FEAT_RIGHTLEFT
Bram Moolenaar6c0b44b2005-06-01 21:56:33 +0000273static int revins_on; /* reverse insert mode on */
274static int revins_chars; /* how much to skip after edit */
275static int revins_legal; /* was the last char 'legal'? */
276static int revins_scol; /* start column of revins session */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000277#endif
278
Bram Moolenaar071d4272004-06-13 20:20:40 +0000279static int ins_need_undo; /* call u_save() before inserting a
280 char. Set when edit() is called.
281 after that arrow_used is used. */
282
283static int did_add_space = FALSE; /* auto_format() added an extra space
284 under the cursor */
285
286/*
287 * edit(): Start inserting text.
288 *
289 * "cmdchar" can be:
290 * 'i' normal insert command
291 * 'a' normal append command
292 * 'R' replace command
293 * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo,
294 * but still only one <CR> is inserted. The <Esc> is not used for redo.
295 * 'g' "gI" command.
296 * 'V' "gR" command for Virtual Replace mode.
297 * 'v' "gr" command for single character Virtual Replace mode.
298 *
299 * This function is not called recursively. For CTRL-O commands, it returns
300 * and lets the caller handle the Normal-mode command.
301 *
302 * Return TRUE if a CTRL-O command caused the return (insert mode pending).
303 */
304 int
305edit(cmdchar, startln, count)
306 int cmdchar;
307 int startln; /* if set, insert at start of line */
308 long count;
309{
310 int c = 0;
311 char_u *ptr;
312 int lastc;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000313 int mincol;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000314 static linenr_T o_lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000315 int i;
316 int did_backspace = TRUE; /* previous char was backspace */
317#ifdef FEAT_CINDENT
318 int line_is_white = FALSE; /* line is empty before insert */
319#endif
320 linenr_T old_topline = 0; /* topline before insertion */
321#ifdef FEAT_DIFF
322 int old_topfill = -1;
323#endif
324 int inserted_space = FALSE; /* just inserted a space */
325 int replaceState = REPLACE;
Bram Moolenaar488c6512005-08-11 20:09:58 +0000326 int nomove = FALSE; /* don't move cursor on return */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000327
Bram Moolenaar83c465c2005-12-16 21:53:56 +0000328 /* Remember whether editing was restarted after CTRL-O. */
329 did_restart_edit = restart_edit;
330
Bram Moolenaar071d4272004-06-13 20:20:40 +0000331 /* sleep before redrawing, needed for "CTRL-O :" that results in an
332 * error message */
333 check_for_delay(TRUE);
334
335#ifdef HAVE_SANDBOX
336 /* Don't allow inserting in the sandbox. */
337 if (sandbox != 0)
338 {
339 EMSG(_(e_sandbox));
340 return FALSE;
341 }
342#endif
Bram Moolenaar8ada17c2006-01-19 22:16:24 +0000343 /* Don't allow changes in the buffer while editing the cmdline. The
344 * caller of getcmdline() may get confused. */
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000345 if (textlock != 0)
Bram Moolenaar8ada17c2006-01-19 22:16:24 +0000346 {
347 EMSG(_(e_secure));
348 return FALSE;
349 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000350
351#ifdef FEAT_INS_EXPAND
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000352 /* Don't allow recursive insert mode when busy with completion. */
Bram Moolenaar031e0dd2009-07-09 16:15:16 +0000353 if (compl_started || compl_busy || pum_visible())
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000354 {
355 EMSG(_(e_secure));
356 return FALSE;
357 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358 ins_compl_clear(); /* clear stuff for CTRL-X mode */
359#endif
360
Bram Moolenaar843ee412004-06-30 16:16:41 +0000361#ifdef FEAT_AUTOCMD
362 /*
363 * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx".
364 */
365 if (cmdchar != 'r' && cmdchar != 'v')
366 {
Bram Moolenaar1e015462005-09-25 22:16:38 +0000367# ifdef FEAT_EVAL
Bram Moolenaar843ee412004-06-30 16:16:41 +0000368 if (cmdchar == 'R')
369 ptr = (char_u *)"r";
370 else if (cmdchar == 'V')
371 ptr = (char_u *)"v";
372 else
373 ptr = (char_u *)"i";
374 set_vim_var_string(VV_INSERTMODE, ptr, 1);
Bram Moolenaar1e015462005-09-25 22:16:38 +0000375# endif
Bram Moolenaar843ee412004-06-30 16:16:41 +0000376 apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf);
377 }
378#endif
379
Bram Moolenaarf5963f72010-07-23 22:10:27 +0200380#ifdef FEAT_CONCEAL
381 /* Check if the cursor line needs redrawing before changing State. If
382 * 'concealcursor' is "n" it needs to be redrawn without concealing. */
383 conceal_check_cursur_line_redraw();
384#endif
385
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386#ifdef FEAT_MOUSE
387 /*
388 * When doing a paste with the middle mouse button, Insstart is set to
389 * where the paste started.
390 */
391 if (where_paste_started.lnum != 0)
392 Insstart = where_paste_started;
393 else
394#endif
395 {
396 Insstart = curwin->w_cursor;
397 if (startln)
398 Insstart.col = 0;
399 }
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000400 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
Bram Moolenaar071d4272004-06-13 20:20:40 +0000401 Insstart_blank_vcol = MAXCOL;
402 if (!did_ai)
403 ai_col = 0;
404
405 if (cmdchar != NUL && restart_edit == 0)
406 {
407 ResetRedobuff();
408 AppendNumberToRedobuff(count);
409#ifdef FEAT_VREPLACE
410 if (cmdchar == 'V' || cmdchar == 'v')
411 {
412 /* "gR" or "gr" command */
413 AppendCharToRedobuff('g');
414 AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R');
415 }
416 else
417#endif
418 {
419 AppendCharToRedobuff(cmdchar);
420 if (cmdchar == 'g') /* "gI" command */
421 AppendCharToRedobuff('I');
422 else if (cmdchar == 'r') /* "r<CR>" command */
423 count = 1; /* insert only one <CR> */
424 }
425 }
426
427 if (cmdchar == 'R')
428 {
429#ifdef FEAT_FKMAP
430 if (p_fkmap && p_ri)
431 {
432 beep_flush();
433 EMSG(farsi_text_3); /* encoded in Farsi */
434 State = INSERT;
435 }
436 else
437#endif
438 State = REPLACE;
439 }
440#ifdef FEAT_VREPLACE
441 else if (cmdchar == 'V' || cmdchar == 'v')
442 {
443 State = VREPLACE;
444 replaceState = VREPLACE;
445 orig_line_count = curbuf->b_ml.ml_line_count;
446 vr_lines_changed = 1;
447 }
448#endif
449 else
450 State = INSERT;
451
452 stop_insert_mode = FALSE;
453
454 /*
455 * Need to recompute the cursor position, it might move when the cursor is
456 * on a TAB or special character.
457 */
458 curs_columns(TRUE);
459
460 /*
461 * Enable langmap or IME, indicated by 'iminsert'.
462 * Note that IME may enabled/disabled without us noticing here, thus the
463 * 'iminsert' value may not reflect what is actually used. It is updated
464 * when hitting <Esc>.
465 */
466 if (curbuf->b_p_iminsert == B_IMODE_LMAP)
467 State |= LANGMAP;
468#ifdef USE_IM_CONTROL
469 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
470#endif
471
Bram Moolenaar071d4272004-06-13 20:20:40 +0000472#ifdef FEAT_MOUSE
473 setmouse();
474#endif
475#ifdef FEAT_CMDL_INFO
476 clear_showcmd();
477#endif
478#ifdef FEAT_RIGHTLEFT
479 /* there is no reverse replace mode */
480 revins_on = (State == INSERT && p_ri);
481 if (revins_on)
482 undisplay_dollar();
483 revins_chars = 0;
484 revins_legal = 0;
485 revins_scol = -1;
486#endif
487
488 /*
489 * Handle restarting Insert mode.
490 * Don't do this for "CTRL-O ." (repeat an insert): we get here with
491 * restart_edit non-zero, and something in the stuff buffer.
492 */
493 if (restart_edit != 0 && stuff_empty())
494 {
495#ifdef FEAT_MOUSE
496 /*
497 * After a paste we consider text typed to be part of the insert for
498 * the pasted text. You can backspace over the pasted text too.
499 */
500 if (where_paste_started.lnum)
501 arrow_used = FALSE;
502 else
503#endif
504 arrow_used = TRUE;
505 restart_edit = 0;
506
507 /*
508 * If the cursor was after the end-of-line before the CTRL-O and it is
509 * now at the end-of-line, put it after the end-of-line (this is not
510 * correct in very rare cases).
511 * Also do this if curswant is greater than the current virtual
512 * column. Eg after "^O$" or "^O80|".
513 */
514 validate_virtcol();
515 update_curswant();
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000516 if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517 || curwin->w_curswant > curwin->w_virtcol)
518 && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL)
519 {
520 if (ptr[1] == NUL)
521 ++curwin->w_cursor.col;
522#ifdef FEAT_MBYTE
523 else if (has_mbyte)
524 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000525 i = (*mb_ptr2len)(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526 if (ptr[i] == NUL)
527 curwin->w_cursor.col += i;
528 }
529#endif
530 }
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000531 ins_at_eol = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 }
533 else
534 arrow_used = FALSE;
535
536 /* we are in insert mode now, don't need to start it anymore */
537 need_start_insertmode = FALSE;
538
539 /* Need to save the line for undo before inserting the first char. */
540 ins_need_undo = TRUE;
541
542#ifdef FEAT_MOUSE
543 where_paste_started.lnum = 0;
544#endif
545#ifdef FEAT_CINDENT
546 can_cindent = TRUE;
547#endif
548#ifdef FEAT_FOLDING
549 /* The cursor line is not in a closed fold, unless 'insertmode' is set or
550 * restarting. */
551 if (!p_im && did_restart_edit == 0)
552 foldOpenCursor();
553#endif
554
555 /*
556 * If 'showmode' is set, show the current (insert/replace/..) mode.
557 * A warning message for changing a readonly file is given here, before
558 * actually changing anything. It's put after the mode, if any.
559 */
560 i = 0;
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000561 if (p_smd && msg_silent == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000562 i = showmode();
563
564 if (!p_im && did_restart_edit == 0)
Bram Moolenaar21af89e2008-01-02 21:09:33 +0000565 change_warning(i == 0 ? 0 : i + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566
567#ifdef CURSOR_SHAPE
568 ui_cursor_shape(); /* may show different cursor shape */
569#endif
570#ifdef FEAT_DIGRAPHS
571 do_digraph(-1); /* clear digraphs */
572#endif
573
Bram Moolenaar83c465c2005-12-16 21:53:56 +0000574 /*
575 * Get the current length of the redo buffer, those characters have to be
576 * skipped if we want to get to the inserted characters.
577 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000578 ptr = get_inserted();
579 if (ptr == NULL)
580 new_insert_skip = 0;
581 else
582 {
583 new_insert_skip = (int)STRLEN(ptr);
584 vim_free(ptr);
585 }
586
587 old_indent = 0;
588
589 /*
590 * Main loop in Insert mode: repeat until Insert mode is left.
591 */
592 for (;;)
593 {
594#ifdef FEAT_RIGHTLEFT
595 if (!revins_legal)
596 revins_scol = -1; /* reset on illegal motions */
597 else
598 revins_legal = 0;
599#endif
600 if (arrow_used) /* don't repeat insert when arrow key used */
601 count = 0;
602
603 if (stop_insert_mode)
604 {
605 /* ":stopinsert" used or 'insertmode' reset */
606 count = 0;
607 goto doESCkey;
608 }
609
610 /* set curwin->w_curswant for next K_DOWN or K_UP */
611 if (!arrow_used)
612 curwin->w_set_curswant = TRUE;
613
614 /* If there is no typeahead may check for timestamps (e.g., for when a
615 * menu invoked a shell command). */
616 if (stuff_empty())
617 {
618 did_check_timestamps = FALSE;
619 if (need_check_timestamps)
620 check_timestamps(FALSE);
621 }
622
623 /*
624 * When emsg() was called msg_scroll will have been set.
625 */
626 msg_scroll = FALSE;
627
628#ifdef FEAT_GUI
629 /* When 'mousefocus' is set a mouse movement may have taken us to
630 * another window. "need_mouse_correct" may then be set because of an
631 * autocommand. */
632 if (need_mouse_correct)
633 gui_mouse_correct();
634#endif
635
636#ifdef FEAT_FOLDING
637 /* Open fold at the cursor line, according to 'foldopen'. */
638 if (fdo_flags & FDO_INSERT)
639 foldOpenCursor();
640 /* Close folds where the cursor isn't, according to 'foldclose' */
641 if (!char_avail())
642 foldCheckClose();
643#endif
644
645 /*
646 * If we inserted a character at the last position of the last line in
647 * the window, scroll the window one line up. This avoids an extra
648 * redraw.
649 * This is detected when the cursor column is smaller after inserting
650 * something.
651 * Don't do this when the topline changed already, it has
652 * already been adjusted (by insertchar() calling open_line())).
653 */
654 if (curbuf->b_mod_set
655 && curwin->w_p_wrap
656 && !did_backspace
657 && curwin->w_topline == old_topline
658#ifdef FEAT_DIFF
659 && curwin->w_topfill == old_topfill
660#endif
661 )
662 {
663 mincol = curwin->w_wcol;
664 validate_cursor_col();
665
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000666 if ((int)curwin->w_wcol < mincol - curbuf->b_p_ts
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 && curwin->w_wrow == W_WINROW(curwin)
668 + curwin->w_height - 1 - p_so
669 && (curwin->w_cursor.lnum != curwin->w_topline
670#ifdef FEAT_DIFF
671 || curwin->w_topfill > 0
672#endif
673 ))
674 {
675#ifdef FEAT_DIFF
676 if (curwin->w_topfill > 0)
677 --curwin->w_topfill;
678 else
679#endif
680#ifdef FEAT_FOLDING
681 if (hasFolding(curwin->w_topline, NULL, &old_topline))
682 set_topline(curwin, old_topline + 1);
683 else
684#endif
685 set_topline(curwin, curwin->w_topline + 1);
686 }
687 }
688
689 /* May need to adjust w_topline to show the cursor. */
690 update_topline();
691
692 did_backspace = FALSE;
693
694 validate_cursor(); /* may set must_redraw */
695
696 /*
697 * Redraw the display when no characters are waiting.
698 * Also shows mode, ruler and positions cursor.
699 */
Bram Moolenaar754b5602006-02-09 23:53:20 +0000700 ins_redraw(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701
702#ifdef FEAT_SCROLLBIND
703 if (curwin->w_p_scb)
704 do_check_scrollbind(TRUE);
705#endif
706
Bram Moolenaar860cae12010-06-05 23:22:07 +0200707#ifdef FEAT_CURSORBIND
708 if (curwin->w_p_crb)
709 do_check_cursorbind();
710#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000711 update_curswant();
712 old_topline = curwin->w_topline;
713#ifdef FEAT_DIFF
714 old_topfill = curwin->w_topfill;
715#endif
716
717#ifdef USE_ON_FLY_SCROLL
718 dont_scroll = FALSE; /* allow scrolling here */
719#endif
720
721 /*
Bram Moolenaard4e20a72008-01-22 16:50:03 +0000722 * Get a character for Insert mode. Ignore K_IGNORE.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723 */
724 lastc = c; /* remember previous char for CTRL-D */
Bram Moolenaard4e20a72008-01-22 16:50:03 +0000725 do
726 {
727 c = safe_vgetc();
728 } while (c == K_IGNORE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729
Bram Moolenaard29a9ee2006-09-14 09:07:34 +0000730#ifdef FEAT_AUTOCMD
731 /* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
732 did_cursorhold = TRUE;
733#endif
734
Bram Moolenaar071d4272004-06-13 20:20:40 +0000735#ifdef FEAT_RIGHTLEFT
736 if (p_hkmap && KeyTyped)
737 c = hkmap(c); /* Hebrew mode mapping */
738#endif
739#ifdef FEAT_FKMAP
740 if (p_fkmap && KeyTyped)
741 c = fkmap(c); /* Farsi mode mapping */
742#endif
743
744#ifdef FEAT_INS_EXPAND
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000745 /*
746 * Special handling of keys while the popup menu is visible or wanted
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +0000747 * and the cursor is still in the completed word. Only when there is
748 * a match, skip this when no matches were found.
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000749 */
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +0000750 if (compl_started
751 && pum_wanted()
752 && curwin->w_cursor.col >= compl_col
753 && (compl_shown_match == NULL
754 || compl_shown_match != compl_shown_match->cp_next))
Bram Moolenaara6557602006-02-04 22:43:20 +0000755 {
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000756 /* BS: Delete one character from "compl_leader". */
757 if ((c == K_BS || c == Ctrl_H)
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000758 && curwin->w_cursor.col > compl_col
759 && (c = ins_compl_bs()) == NUL)
Bram Moolenaara6557602006-02-04 22:43:20 +0000760 continue;
761
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000762 /* When no match was selected or it was edited. */
763 if (!compl_used_match)
Bram Moolenaara6557602006-02-04 22:43:20 +0000764 {
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000765 /* CTRL-L: Add one character from the current match to
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000766 * "compl_leader". Except when at the original match and
767 * there is nothing to add, CTRL-L works like CTRL-P then. */
768 if (c == Ctrl_L
769 && (ctrl_x_mode != CTRL_X_WHOLE_LINE
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +0000770 || (int)STRLEN(compl_shown_match->cp_str)
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000771 > curwin->w_cursor.col - compl_col))
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000772 {
773 ins_compl_addfrommatch();
774 continue;
775 }
776
Bram Moolenaar711d5b52007-10-19 18:40:51 +0000777 /* A non-white character that fits in with the current
778 * completion: Add to "compl_leader". */
779 if (ins_compl_accept_char(c))
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000780 {
781 ins_compl_addleader(c);
782 continue;
783 }
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000784
Bram Moolenaar0440ca32006-05-13 13:24:33 +0000785 /* Pressing CTRL-Y selects the current match. When
Bram Moolenaar779b74b2006-04-10 14:55:34 +0000786 * compl_enter_selects is set the Enter key does the same. */
787 if (c == Ctrl_Y || (compl_enter_selects
788 && (c == CAR || c == K_KENTER || c == NL)))
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000789 {
790 ins_compl_delete();
791 ins_compl_insert();
792 }
Bram Moolenaara6557602006-02-04 22:43:20 +0000793 }
794 }
795
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796 /* Prepare for or stop CTRL-X mode. This doesn't do completion, but
797 * it does fix up the text when finishing completion. */
Bram Moolenaarc7453f52006-02-10 23:20:28 +0000798 compl_get_longest = FALSE;
Bram Moolenaard4e20a72008-01-22 16:50:03 +0000799 if (ins_compl_prep(c))
Bram Moolenaara6557602006-02-04 22:43:20 +0000800 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000801#endif
802
Bram Moolenaar488c6512005-08-11 20:09:58 +0000803 /* CTRL-\ CTRL-N goes to Normal mode,
804 * CTRL-\ CTRL-G goes to mode selected with 'insertmode',
805 * CTRL-\ CTRL-O is like CTRL-O but without moving the cursor. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 if (c == Ctrl_BSL)
807 {
808 /* may need to redraw when no more chars available now */
Bram Moolenaar754b5602006-02-09 23:53:20 +0000809 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 ++no_mapping;
811 ++allow_keys;
Bram Moolenaar61abfd12007-09-13 16:26:47 +0000812 c = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 --no_mapping;
814 --allow_keys;
Bram Moolenaar488c6512005-08-11 20:09:58 +0000815 if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 {
Bram Moolenaar488c6512005-08-11 20:09:58 +0000817 /* it's something else */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 vungetc(c);
819 c = Ctrl_BSL;
820 }
821 else if (c == Ctrl_G && p_im)
822 continue;
823 else
824 {
Bram Moolenaar488c6512005-08-11 20:09:58 +0000825 if (c == Ctrl_O)
826 {
827 ins_ctrl_o();
828 ins_at_eol = FALSE; /* cursor keeps its column */
829 nomove = TRUE;
830 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831 count = 0;
832 goto doESCkey;
833 }
834 }
835
836#ifdef FEAT_DIGRAPHS
837 c = do_digraph(c);
838#endif
839
840#ifdef FEAT_INS_EXPAND
841 if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE)
842 goto docomplete;
843#endif
844 if (c == Ctrl_V || c == Ctrl_Q)
845 {
846 ins_ctrl_v();
847 c = Ctrl_V; /* pretend CTRL-V is last typed character */
848 continue;
849 }
850
851#ifdef FEAT_CINDENT
852 if (cindent_on()
853# ifdef FEAT_INS_EXPAND
854 && ctrl_x_mode == 0
855# endif
856 )
857 {
858 /* A key name preceded by a bang means this key is not to be
859 * inserted. Skip ahead to the re-indenting below.
860 * A key name preceded by a star means that indenting has to be
861 * done before inserting the key. */
862 line_is_white = inindent(0);
863 if (in_cinkeys(c, '!', line_is_white))
864 goto force_cindent;
865 if (can_cindent && in_cinkeys(c, '*', line_is_white)
866 && stop_arrow() == OK)
867 do_c_expr_indent();
868 }
869#endif
870
871#ifdef FEAT_RIGHTLEFT
872 if (curwin->w_p_rl)
873 switch (c)
874 {
875 case K_LEFT: c = K_RIGHT; break;
876 case K_S_LEFT: c = K_S_RIGHT; break;
877 case K_C_LEFT: c = K_C_RIGHT; break;
878 case K_RIGHT: c = K_LEFT; break;
879 case K_S_RIGHT: c = K_S_LEFT; break;
880 case K_C_RIGHT: c = K_C_LEFT; break;
881 }
882#endif
883
884#ifdef FEAT_VISUAL
885 /*
886 * If 'keymodel' contains "startsel", may start selection. If it
887 * does, a CTRL-O and c will be stuffed, we need to get these
888 * characters.
889 */
890 if (ins_start_select(c))
891 continue;
892#endif
893
894 /*
895 * The big switch to handle a character in insert mode.
896 */
897 switch (c)
898 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000899 case ESC: /* End input mode */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000900 if (echeck_abbr(ESC + ABBR_OFF))
901 break;
902 /*FALLTHROUGH*/
903
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000904 case Ctrl_C: /* End input mode */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905#ifdef FEAT_CMDWIN
906 if (c == Ctrl_C && cmdwin_type != 0)
907 {
908 /* Close the cmdline window. */
909 cmdwin_result = K_IGNORE;
910 got_int = FALSE; /* don't stop executing autocommands et al. */
Bram Moolenaar5495cc92006-08-16 14:23:04 +0000911 nomove = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 goto doESCkey;
913 }
914#endif
915
916#ifdef UNIX
917do_intr:
918#endif
919 /* when 'insertmode' set, and not halfway a mapping, don't leave
920 * Insert mode */
921 if (goto_im())
922 {
923 if (got_int)
924 {
925 (void)vgetc(); /* flush all buffers */
926 got_int = FALSE;
927 }
928 else
929 vim_beep();
930 break;
931 }
932doESCkey:
933 /*
934 * This is the ONLY return from edit()!
935 */
936 /* Always update o_lnum, so that a "CTRL-O ." that adds a line
937 * still puts the cursor back after the inserted text. */
Bram Moolenaar68b76a62005-03-25 21:53:48 +0000938 if (ins_at_eol && gchar_cursor() == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 o_lnum = curwin->w_cursor.lnum;
940
Bram Moolenaar488c6512005-08-11 20:09:58 +0000941 if (ins_esc(&count, cmdchar, nomove))
Bram Moolenaar843ee412004-06-30 16:16:41 +0000942 {
943#ifdef FEAT_AUTOCMD
944 if (cmdchar != 'r' && cmdchar != 'v')
945 apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL,
946 FALSE, curbuf);
Bram Moolenaarc0a0ab52006-10-06 18:39:58 +0000947 did_cursorhold = FALSE;
Bram Moolenaar843ee412004-06-30 16:16:41 +0000948#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 return (c == Ctrl_O);
Bram Moolenaar843ee412004-06-30 16:16:41 +0000950 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 continue;
952
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000953 case Ctrl_Z: /* suspend when 'insertmode' set */
954 if (!p_im)
955 goto normalchar; /* insert CTRL-Z as normal char */
956 stuffReadbuff((char_u *)":st\r");
957 c = Ctrl_O;
958 /*FALLTHROUGH*/
959
960 case Ctrl_O: /* execute one command */
Bram Moolenaare344bea2005-09-01 20:46:49 +0000961#ifdef FEAT_COMPL_FUNC
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000962 if (ctrl_x_mode == CTRL_X_OMNI)
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000963 goto docomplete;
964#endif
965 if (echeck_abbr(Ctrl_O + ABBR_OFF))
966 break;
967 ins_ctrl_o();
Bram Moolenaar06a89a52006-04-29 22:01:03 +0000968
969#ifdef FEAT_VIRTUALEDIT
970 /* don't move the cursor left when 'virtualedit' has "onemore". */
971 if (ve_flags & VE_ONEMORE)
972 {
973 ins_at_eol = FALSE;
974 nomove = TRUE;
975 }
976#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000977 count = 0;
978 goto doESCkey;
979
Bram Moolenaar572cb562005-08-05 21:35:02 +0000980 case K_INS: /* toggle insert/replace mode */
981 case K_KINS:
982 ins_insert(replaceState);
983 break;
984
985 case K_SELECT: /* end of Select mode mapping - ignore */
986 break;
987
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000988#ifdef FEAT_SNIFF
989 case K_SNIFF: /* Sniff command received */
990 stuffcharReadbuff(K_SNIFF);
991 goto doESCkey;
992#endif
993
994 case K_HELP: /* Help key works like <ESC> <Help> */
995 case K_F1:
996 case K_XF1:
997 stuffcharReadbuff(K_HELP);
998 if (p_im)
999 need_start_insertmode = TRUE;
1000 goto doESCkey;
1001
1002#ifdef FEAT_NETBEANS_INTG
1003 case K_F21: /* NetBeans command */
1004 ++no_mapping; /* don't map the next key hits */
Bram Moolenaar61abfd12007-09-13 16:26:47 +00001005 i = plain_vgetc();
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001006 --no_mapping;
1007 netbeans_keycommand(i);
1008 break;
1009#endif
1010
1011 case K_ZERO: /* Insert the previously inserted text. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012 case NUL:
1013 case Ctrl_A:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001014 /* For ^@ the trailing ESC will end the insert, unless there is an
1015 * error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001016 if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL
1017 && c != Ctrl_A && !p_im)
1018 goto doESCkey; /* quit insert mode */
1019 inserted_space = FALSE;
1020 break;
1021
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001022 case Ctrl_R: /* insert the contents of a register */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001023 ins_reg();
1024 auto_format(FALSE, TRUE);
1025 inserted_space = FALSE;
1026 break;
1027
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001028 case Ctrl_G: /* commands starting with CTRL-G */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 ins_ctrl_g();
1030 break;
1031
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001032 case Ctrl_HAT: /* switch input mode and/or langmap */
1033 ins_ctrl_hat();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034 break;
1035
1036#ifdef FEAT_RIGHTLEFT
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001037 case Ctrl__: /* switch between languages */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001038 if (!p_ari)
1039 goto normalchar;
1040 ins_ctrl_();
1041 break;
1042#endif
1043
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001044 case Ctrl_D: /* Make indent one shiftwidth smaller. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045#if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
1046 if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
1047 goto docomplete;
1048#endif
1049 /* FALLTHROUGH */
1050
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001051 case Ctrl_T: /* Make indent one shiftwidth greater. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052# ifdef FEAT_INS_EXPAND
1053 if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
1054 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001055 if (has_compl_option(FALSE))
1056 goto docomplete;
1057 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 }
1059# endif
1060 ins_shift(c, lastc);
1061 auto_format(FALSE, TRUE);
1062 inserted_space = FALSE;
1063 break;
1064
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001065 case K_DEL: /* delete character under the cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066 case K_KDEL:
1067 ins_del();
1068 auto_format(FALSE, TRUE);
1069 break;
1070
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001071 case K_BS: /* delete character before the cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001072 case Ctrl_H:
1073 did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
1074 auto_format(FALSE, TRUE);
1075 break;
1076
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001077 case Ctrl_W: /* delete word before the cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078 did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
1079 auto_format(FALSE, TRUE);
1080 break;
1081
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001082 case Ctrl_U: /* delete all inserted text in current line */
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001083# ifdef FEAT_COMPL_FUNC
1084 /* CTRL-X CTRL-U completes with 'completefunc'. */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001085 if (ctrl_x_mode == CTRL_X_FUNCTION)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001086 goto docomplete;
1087# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001088 did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
1089 auto_format(FALSE, TRUE);
1090 inserted_space = FALSE;
1091 break;
1092
1093#ifdef FEAT_MOUSE
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001094 case K_LEFTMOUSE: /* mouse keys */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 case K_LEFTMOUSE_NM:
1096 case K_LEFTDRAG:
1097 case K_LEFTRELEASE:
1098 case K_LEFTRELEASE_NM:
1099 case K_MIDDLEMOUSE:
1100 case K_MIDDLEDRAG:
1101 case K_MIDDLERELEASE:
1102 case K_RIGHTMOUSE:
1103 case K_RIGHTDRAG:
1104 case K_RIGHTRELEASE:
1105 case K_X1MOUSE:
1106 case K_X1DRAG:
1107 case K_X1RELEASE:
1108 case K_X2MOUSE:
1109 case K_X2DRAG:
1110 case K_X2RELEASE:
1111 ins_mouse(c);
1112 break;
1113
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001114 case K_MOUSEDOWN: /* Default action for scroll wheel up: scroll up */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001115 ins_mousescroll(FALSE);
1116 break;
1117
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001118 case K_MOUSEUP: /* Default action for scroll wheel down: scroll down */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001119 ins_mousescroll(TRUE);
1120 break;
1121#endif
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001122#ifdef FEAT_GUI_TABLINE
1123 case K_TABLINE:
1124 case K_TABMENU:
1125 ins_tabline(c);
1126 break;
1127#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001128
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001129 case K_IGNORE: /* Something mapped to nothing */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001130 break;
1131
Bram Moolenaar754b5602006-02-09 23:53:20 +00001132#ifdef FEAT_AUTOCMD
1133 case K_CURSORHOLD: /* Didn't type something for a while. */
1134 apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf);
1135 did_cursorhold = TRUE;
1136 break;
1137#endif
1138
Bram Moolenaar4770d092006-01-12 23:22:24 +00001139#ifdef FEAT_GUI_W32
1140 /* On Win32 ignore <M-F4>, we get it when closing the window was
1141 * cancelled. */
1142 case K_F4:
1143 if (mod_mask != MOD_MASK_ALT)
1144 goto normalchar;
1145 break;
1146#endif
1147
Bram Moolenaar071d4272004-06-13 20:20:40 +00001148#ifdef FEAT_GUI
1149 case K_VER_SCROLLBAR:
1150 ins_scroll();
1151 break;
1152
1153 case K_HOR_SCROLLBAR:
1154 ins_horscroll();
1155 break;
1156#endif
1157
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001158 case K_HOME: /* <Home> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159 case K_KHOME:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160 case K_S_HOME:
1161 case K_C_HOME:
1162 ins_home(c);
1163 break;
1164
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001165 case K_END: /* <End> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166 case K_KEND:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167 case K_S_END:
1168 case K_C_END:
1169 ins_end(c);
1170 break;
1171
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001172 case K_LEFT: /* <Left> */
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00001173 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
1174 ins_s_left();
1175 else
1176 ins_left();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177 break;
1178
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001179 case K_S_LEFT: /* <S-Left> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180 case K_C_LEFT:
1181 ins_s_left();
1182 break;
1183
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001184 case K_RIGHT: /* <Right> */
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00001185 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
1186 ins_s_right();
1187 else
1188 ins_right();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189 break;
1190
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001191 case K_S_RIGHT: /* <S-Right> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192 case K_C_RIGHT:
1193 ins_s_right();
1194 break;
1195
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001196 case K_UP: /* <Up> */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00001197#ifdef FEAT_INS_EXPAND
1198 if (pum_visible())
1199 goto docomplete;
1200#endif
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00001201 if (mod_mask & MOD_MASK_SHIFT)
1202 ins_pageup();
1203 else
1204 ins_up(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205 break;
1206
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001207 case K_S_UP: /* <S-Up> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208 case K_PAGEUP:
1209 case K_KPAGEUP:
Bram Moolenaara9b1e742005-12-19 22:14:58 +00001210#ifdef FEAT_INS_EXPAND
Bram Moolenaare3226be2005-12-18 22:10:00 +00001211 if (pum_visible())
1212 goto docomplete;
Bram Moolenaara9b1e742005-12-19 22:14:58 +00001213#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214 ins_pageup();
1215 break;
1216
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001217 case K_DOWN: /* <Down> */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00001218#ifdef FEAT_INS_EXPAND
1219 if (pum_visible())
1220 goto docomplete;
1221#endif
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00001222 if (mod_mask & MOD_MASK_SHIFT)
1223 ins_pagedown();
1224 else
1225 ins_down(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001226 break;
1227
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001228 case K_S_DOWN: /* <S-Down> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229 case K_PAGEDOWN:
1230 case K_KPAGEDOWN:
Bram Moolenaara9b1e742005-12-19 22:14:58 +00001231#ifdef FEAT_INS_EXPAND
Bram Moolenaare3226be2005-12-18 22:10:00 +00001232 if (pum_visible())
1233 goto docomplete;
Bram Moolenaara9b1e742005-12-19 22:14:58 +00001234#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001235 ins_pagedown();
1236 break;
1237
1238#ifdef FEAT_DND
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001239 case K_DROP: /* drag-n-drop event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240 ins_drop();
1241 break;
1242#endif
1243
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001244 case K_S_TAB: /* When not mapped, use like a normal TAB */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001245 c = TAB;
1246 /* FALLTHROUGH */
1247
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001248 case TAB: /* TAB or Complete patterns along path */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001249#if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
1250 if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
1251 goto docomplete;
1252#endif
1253 inserted_space = FALSE;
1254 if (ins_tab())
1255 goto normalchar; /* insert TAB as a normal char */
1256 auto_format(FALSE, TRUE);
1257 break;
1258
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001259 case K_KENTER: /* <Enter> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001260 c = CAR;
1261 /* FALLTHROUGH */
1262 case CAR:
1263 case NL:
1264#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
1265 /* In a quickfix window a <CR> jumps to the error under the
1266 * cursor. */
1267 if (bt_quickfix(curbuf) && c == CAR)
1268 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00001269 if (curwin->w_llist_ref == NULL) /* quickfix window */
1270 do_cmdline_cmd((char_u *)".cc");
1271 else /* location list window */
1272 do_cmdline_cmd((char_u *)".ll");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001273 break;
1274 }
1275#endif
1276#ifdef FEAT_CMDWIN
1277 if (cmdwin_type != 0)
1278 {
1279 /* Execute the command in the cmdline window. */
1280 cmdwin_result = CAR;
1281 goto doESCkey;
1282 }
1283#endif
1284 if (ins_eol(c) && !p_im)
1285 goto doESCkey; /* out of memory */
1286 auto_format(FALSE, FALSE);
1287 inserted_space = FALSE;
1288 break;
1289
Bram Moolenaar860cae12010-06-05 23:22:07 +02001290#if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001291 case Ctrl_K: /* digraph or keyword completion */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001292# ifdef FEAT_INS_EXPAND
1293 if (ctrl_x_mode == CTRL_X_DICTIONARY)
1294 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001295 if (has_compl_option(TRUE))
1296 goto docomplete;
1297 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298 }
1299# endif
1300# ifdef FEAT_DIGRAPHS
1301 c = ins_digraph();
1302 if (c == NUL)
1303 break;
1304# endif
1305 goto normalchar;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001306#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001307
1308#ifdef FEAT_INS_EXPAND
Bram Moolenaar572cb562005-08-05 21:35:02 +00001309 case Ctrl_X: /* Enter CTRL-X mode */
1310 ins_ctrl_x();
1311 break;
1312
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001313 case Ctrl_RSB: /* Tag name completion after ^X */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001314 if (ctrl_x_mode != CTRL_X_TAGS)
1315 goto normalchar;
1316 goto docomplete;
1317
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001318 case Ctrl_F: /* File name completion after ^X */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001319 if (ctrl_x_mode != CTRL_X_FILES)
1320 goto normalchar;
1321 goto docomplete;
Bram Moolenaar488c6512005-08-11 20:09:58 +00001322
1323 case 's': /* Spelling completion after ^X */
1324 case Ctrl_S:
1325 if (ctrl_x_mode != CTRL_X_SPELL)
1326 goto normalchar;
1327 goto docomplete;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328#endif
1329
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001330 case Ctrl_L: /* Whole line completion after ^X */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331#ifdef FEAT_INS_EXPAND
1332 if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
1333#endif
1334 {
1335 /* CTRL-L with 'insertmode' set: Leave Insert mode */
1336 if (p_im)
1337 {
1338 if (echeck_abbr(Ctrl_L + ABBR_OFF))
1339 break;
1340 goto doESCkey;
1341 }
1342 goto normalchar;
1343 }
1344#ifdef FEAT_INS_EXPAND
1345 /* FALLTHROUGH */
1346
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001347 case Ctrl_P: /* Do previous/next pattern completion */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001348 case Ctrl_N:
1349 /* if 'complete' is empty then plain ^P is no longer special,
1350 * but it is under other ^X modes */
1351 if (*curbuf->b_p_cpt == NUL
1352 && ctrl_x_mode != 0
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001353 && !(compl_cont_status & CONT_LOCAL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354 goto normalchar;
1355
1356docomplete:
Bram Moolenaar031e0dd2009-07-09 16:15:16 +00001357 compl_busy = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001358 if (ins_complete(c) == FAIL)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001359 compl_cont_status = 0;
Bram Moolenaar031e0dd2009-07-09 16:15:16 +00001360 compl_busy = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001361 break;
1362#endif /* FEAT_INS_EXPAND */
1363
Bram Moolenaar4be06f92005-07-29 22:36:03 +00001364 case Ctrl_Y: /* copy from previous line or scroll down */
1365 case Ctrl_E: /* copy from next line or scroll up */
1366 c = ins_ctrl_ey(c);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001367 break;
1368
1369 default:
1370#ifdef UNIX
1371 if (c == intr_char) /* special interrupt char */
1372 goto do_intr;
1373#endif
1374
1375 /*
1376 * Insert a nomal character.
1377 */
1378normalchar:
1379#ifdef FEAT_SMARTINDENT
1380 /* Try to perform smart-indenting. */
1381 ins_try_si(c);
1382#endif
1383
1384 if (c == ' ')
1385 {
1386 inserted_space = TRUE;
1387#ifdef FEAT_CINDENT
1388 if (inindent(0))
1389 can_cindent = FALSE;
1390#endif
1391 if (Insstart_blank_vcol == MAXCOL
1392 && curwin->w_cursor.lnum == Insstart.lnum)
1393 Insstart_blank_vcol = get_nolist_virtcol();
1394 }
1395
1396 if (vim_iswordc(c) || !echeck_abbr(
1397#ifdef FEAT_MBYTE
1398 /* Add ABBR_OFF for characters above 0x100, this is
1399 * what check_abbr() expects. */
1400 (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) :
1401#endif
1402 c))
1403 {
1404 insert_special(c, FALSE, FALSE);
1405#ifdef FEAT_RIGHTLEFT
1406 revins_legal++;
1407 revins_chars++;
1408#endif
1409 }
1410
1411 auto_format(FALSE, TRUE);
1412
1413#ifdef FEAT_FOLDING
1414 /* When inserting a character the cursor line must never be in a
1415 * closed fold. */
1416 foldOpenCursor();
1417#endif
1418 break;
1419 } /* end of switch (c) */
1420
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00001421#ifdef FEAT_AUTOCMD
1422 /* If typed something may trigger CursorHoldI again. */
1423 if (c != K_CURSORHOLD)
1424 did_cursorhold = FALSE;
1425#endif
1426
Bram Moolenaar071d4272004-06-13 20:20:40 +00001427 /* If the cursor was moved we didn't just insert a space */
1428 if (arrow_used)
1429 inserted_space = FALSE;
1430
1431#ifdef FEAT_CINDENT
1432 if (can_cindent && cindent_on()
1433# ifdef FEAT_INS_EXPAND
1434 && ctrl_x_mode == 0
1435# endif
1436 )
1437 {
1438force_cindent:
1439 /*
1440 * Indent now if a key was typed that is in 'cinkeys'.
1441 */
1442 if (in_cinkeys(c, ' ', line_is_white))
1443 {
1444 if (stop_arrow() == OK)
1445 /* re-indent the current line */
1446 do_c_expr_indent();
1447 }
1448 }
1449#endif /* FEAT_CINDENT */
1450
1451 } /* for (;;) */
1452 /* NOTREACHED */
1453}
1454
1455/*
1456 * Redraw for Insert mode.
1457 * This is postponed until getting the next character to make '$' in the 'cpo'
1458 * option work correctly.
1459 * Only redraw when there are no characters available. This speeds up
1460 * inserting sequences of characters (e.g., for CTRL-R).
1461 */
1462 static void
Bram Moolenaar754b5602006-02-09 23:53:20 +00001463ins_redraw(ready)
Bram Moolenaar0c094b92009-05-14 20:20:33 +00001464 int ready UNUSED; /* not busy with something */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001465{
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001466#ifdef FEAT_CONCEAL
1467 linenr_T conceal_old_cursor_line = 0;
1468 linenr_T conceal_new_cursor_line = 0;
1469 int conceal_update_lines = FALSE;
1470#endif
1471
Bram Moolenaar071d4272004-06-13 20:20:40 +00001472 if (!char_avail())
1473 {
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001474#if defined(FEAT_AUTOCMD) || defined(FEAT_CONCEAL)
Bram Moolenaar433f7c82006-03-21 21:29:36 +00001475 /* Trigger CursorMoved if the cursor moved. Not when the popup menu is
1476 * visible, the command might delete it. */
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001477 if (ready && (
1478# ifdef FEAT_AUTOCMD
1479 has_cursormovedI()
Bram Moolenaar433f7c82006-03-21 21:29:36 +00001480# endif
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001481# if defined(FEAT_AUTOCMD) && defined(FEAT_CONCEAL)
1482 ||
1483# endif
1484# ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001485 curwin->w_p_cole > 0
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001486# endif
1487 )
1488 && !equalpos(last_cursormoved, curwin->w_cursor)
1489# ifdef FEAT_INS_EXPAND
1490 && !pum_visible()
1491# endif
1492 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00001493 {
Bram Moolenaare77c7602008-01-12 17:13:50 +00001494# ifdef FEAT_SYN_HL
1495 /* Need to update the screen first, to make sure syntax
1496 * highlighting is correct after making a change (e.g., inserting
1497 * a "(". The autocommand may also require a redraw, so it's done
1498 * again below, unfortunately. */
Bram Moolenaar860cae12010-06-05 23:22:07 +02001499 if (syntax_present(curwin) && must_redraw)
Bram Moolenaare77c7602008-01-12 17:13:50 +00001500 update_screen(0);
1501# endif
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001502# ifdef FEAT_AUTOCMD
1503 if (has_cursormovedI())
1504 apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf);
1505# endif
1506# ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001507 if (curwin->w_p_cole > 0)
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001508 {
1509 conceal_old_cursor_line = last_cursormoved.lnum;
1510 conceal_new_cursor_line = curwin->w_cursor.lnum;
1511 conceal_update_lines = TRUE;
1512 }
1513# endif
Bram Moolenaar754b5602006-02-09 23:53:20 +00001514 last_cursormoved = curwin->w_cursor;
1515 }
1516#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001517 if (must_redraw)
1518 update_screen(0);
1519 else if (clear_cmdline || redraw_cmdline)
1520 showmode(); /* clear cmdline and show mode */
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001521# if defined(FEAT_CONCEAL)
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001522 if ((conceal_update_lines
1523 && (conceal_old_cursor_line != conceal_new_cursor_line
1524 || conceal_cursor_line(curwin)))
1525 || need_cursor_line_redraw)
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001526 {
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001527 if (conceal_old_cursor_line != conceal_new_cursor_line)
1528 update_single_line(curwin, conceal_old_cursor_line);
1529 update_single_line(curwin, conceal_new_cursor_line == 0
1530 ? curwin->w_cursor.lnum : conceal_new_cursor_line);
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001531 curwin->w_valid &= ~VALID_CROW;
1532 }
1533# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001534 showruler(FALSE);
1535 setcursor();
1536 emsg_on_display = FALSE; /* may remove error message now */
1537 }
1538}
1539
1540/*
1541 * Handle a CTRL-V or CTRL-Q typed in Insert mode.
1542 */
1543 static void
1544ins_ctrl_v()
1545{
1546 int c;
1547
1548 /* may need to redraw when no more chars available now */
Bram Moolenaar754b5602006-02-09 23:53:20 +00001549 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001550
1551 if (redrawing() && !char_avail())
1552 edit_putchar('^', TRUE);
1553 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
1554
1555#ifdef FEAT_CMDL_INFO
1556 add_to_showcmd_c(Ctrl_V);
1557#endif
1558
1559 c = get_literal();
Bram Moolenaar26dcc7e2010-07-14 22:35:55 +02001560 edit_unputchar(); /* when line fits in 'columns' the '^' is at the start
1561 of the next line and will not be redrawn */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001562#ifdef FEAT_CMDL_INFO
1563 clear_showcmd();
1564#endif
1565 insert_special(c, FALSE, TRUE);
1566#ifdef FEAT_RIGHTLEFT
1567 revins_chars++;
1568 revins_legal++;
1569#endif
1570}
1571
1572/*
1573 * Put a character directly onto the screen. It's not stored in a buffer.
1574 * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
1575 */
1576static int pc_status;
1577#define PC_STATUS_UNSET 0 /* pc_bytes was not set */
1578#define PC_STATUS_RIGHT 1 /* right halve of double-wide char */
1579#define PC_STATUS_LEFT 2 /* left halve of double-wide char */
1580#define PC_STATUS_SET 3 /* pc_bytes was filled */
1581#ifdef FEAT_MBYTE
1582static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */
1583#else
1584static char_u pc_bytes[2]; /* saved bytes */
1585#endif
1586static int pc_attr;
1587static int pc_row;
1588static int pc_col;
1589
1590 void
1591edit_putchar(c, highlight)
1592 int c;
1593 int highlight;
1594{
1595 int attr;
1596
1597 if (ScreenLines != NULL)
1598 {
1599 update_topline(); /* just in case w_topline isn't valid */
1600 validate_cursor();
1601 if (highlight)
1602 attr = hl_attr(HLF_8);
1603 else
1604 attr = 0;
1605 pc_row = W_WINROW(curwin) + curwin->w_wrow;
1606 pc_col = W_WINCOL(curwin);
1607#if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
1608 pc_status = PC_STATUS_UNSET;
1609#endif
1610#ifdef FEAT_RIGHTLEFT
1611 if (curwin->w_p_rl)
1612 {
1613 pc_col += W_WIDTH(curwin) - 1 - curwin->w_wcol;
1614# ifdef FEAT_MBYTE
1615 if (has_mbyte)
1616 {
1617 int fix_col = mb_fix_col(pc_col, pc_row);
1618
1619 if (fix_col != pc_col)
1620 {
1621 screen_putchar(' ', pc_row, fix_col, attr);
1622 --curwin->w_wcol;
1623 pc_status = PC_STATUS_RIGHT;
1624 }
1625 }
1626# endif
1627 }
1628 else
1629#endif
1630 {
1631 pc_col += curwin->w_wcol;
1632#ifdef FEAT_MBYTE
1633 if (mb_lefthalve(pc_row, pc_col))
1634 pc_status = PC_STATUS_LEFT;
1635#endif
1636 }
1637
1638 /* save the character to be able to put it back */
1639#if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
1640 if (pc_status == PC_STATUS_UNSET)
1641#endif
1642 {
1643 screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
1644 pc_status = PC_STATUS_SET;
1645 }
1646 screen_putchar(c, pc_row, pc_col, attr);
1647 }
1648}
1649
1650/*
1651 * Undo the previous edit_putchar().
1652 */
1653 void
1654edit_unputchar()
1655{
1656 if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled)
1657 {
1658#if defined(FEAT_MBYTE)
1659 if (pc_status == PC_STATUS_RIGHT)
1660 ++curwin->w_wcol;
1661 if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT)
1662 redrawWinline(curwin->w_cursor.lnum, FALSE);
1663 else
1664#endif
1665 screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
1666 }
1667}
1668
1669/*
1670 * Called when p_dollar is set: display a '$' at the end of the changed text
1671 * Only works when cursor is in the line that changes.
1672 */
1673 void
1674display_dollar(col)
1675 colnr_T col;
1676{
1677 colnr_T save_col;
1678
1679 if (!redrawing())
1680 return;
1681
1682 cursor_off();
1683 save_col = curwin->w_cursor.col;
1684 curwin->w_cursor.col = col;
1685#ifdef FEAT_MBYTE
1686 if (has_mbyte)
1687 {
1688 char_u *p;
1689
1690 /* If on the last byte of a multi-byte move to the first byte. */
1691 p = ml_get_curline();
1692 curwin->w_cursor.col -= (*mb_head_off)(p, p + col);
1693 }
1694#endif
1695 curs_columns(FALSE); /* recompute w_wrow and w_wcol */
1696 if (curwin->w_wcol < W_WIDTH(curwin))
1697 {
1698 edit_putchar('$', FALSE);
1699 dollar_vcol = curwin->w_virtcol;
1700 }
1701 curwin->w_cursor.col = save_col;
1702}
1703
1704/*
1705 * Call this function before moving the cursor from the normal insert position
1706 * in insert mode.
1707 */
1708 static void
1709undisplay_dollar()
1710{
1711 if (dollar_vcol)
1712 {
1713 dollar_vcol = 0;
1714 redrawWinline(curwin->w_cursor.lnum, FALSE);
1715 }
1716}
1717
1718/*
1719 * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
1720 * Keep the cursor on the same character.
1721 * type == INDENT_INC increase indent (for CTRL-T or <Tab>)
1722 * type == INDENT_DEC decrease indent (for CTRL-D)
1723 * type == INDENT_SET set indent to "amount"
1724 * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
1725 */
1726 void
Bram Moolenaar21b17e72008-01-16 19:03:13 +00001727change_indent(type, amount, round, replaced, call_changed_bytes)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001728 int type;
1729 int amount;
1730 int round;
1731 int replaced; /* replaced character, put on replace stack */
Bram Moolenaar21b17e72008-01-16 19:03:13 +00001732 int call_changed_bytes; /* call changed_bytes() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001733{
1734 int vcol;
1735 int last_vcol;
1736 int insstart_less; /* reduction for Insstart.col */
1737 int new_cursor_col;
1738 int i;
1739 char_u *ptr;
1740 int save_p_list;
1741 int start_col;
1742 colnr_T vc;
1743#ifdef FEAT_VREPLACE
1744 colnr_T orig_col = 0; /* init for GCC */
1745 char_u *new_line, *orig_line = NULL; /* init for GCC */
1746
1747 /* VREPLACE mode needs to know what the line was like before changing */
1748 if (State & VREPLACE_FLAG)
1749 {
1750 orig_line = vim_strsave(ml_get_curline()); /* Deal with NULL below */
1751 orig_col = curwin->w_cursor.col;
1752 }
1753#endif
1754
1755 /* for the following tricks we don't want list mode */
1756 save_p_list = curwin->w_p_list;
1757 curwin->w_p_list = FALSE;
1758 vc = getvcol_nolist(&curwin->w_cursor);
1759 vcol = vc;
1760
1761 /*
1762 * For Replace mode we need to fix the replace stack later, which is only
1763 * possible when the cursor is in the indent. Remember the number of
1764 * characters before the cursor if it's possible.
1765 */
1766 start_col = curwin->w_cursor.col;
1767
1768 /* determine offset from first non-blank */
1769 new_cursor_col = curwin->w_cursor.col;
1770 beginline(BL_WHITE);
1771 new_cursor_col -= curwin->w_cursor.col;
1772
1773 insstart_less = curwin->w_cursor.col;
1774
1775 /*
1776 * If the cursor is in the indent, compute how many screen columns the
1777 * cursor is to the left of the first non-blank.
1778 */
1779 if (new_cursor_col < 0)
1780 vcol = get_indent() - vcol;
1781
1782 if (new_cursor_col > 0) /* can't fix replace stack */
1783 start_col = -1;
1784
1785 /*
1786 * Set the new indent. The cursor will be put on the first non-blank.
1787 */
1788 if (type == INDENT_SET)
Bram Moolenaar21b17e72008-01-16 19:03:13 +00001789 (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790 else
1791 {
1792#ifdef FEAT_VREPLACE
1793 int save_State = State;
1794
1795 /* Avoid being called recursively. */
1796 if (State & VREPLACE_FLAG)
1797 State = INSERT;
1798#endif
Bram Moolenaar21b17e72008-01-16 19:03:13 +00001799 shift_line(type == INDENT_DEC, round, 1, call_changed_bytes);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001800#ifdef FEAT_VREPLACE
1801 State = save_State;
1802#endif
1803 }
1804 insstart_less -= curwin->w_cursor.col;
1805
1806 /*
1807 * Try to put cursor on same character.
1808 * If the cursor is at or after the first non-blank in the line,
1809 * compute the cursor column relative to the column of the first
1810 * non-blank character.
1811 * If we are not in insert mode, leave the cursor on the first non-blank.
1812 * If the cursor is before the first non-blank, position it relative
1813 * to the first non-blank, counted in screen columns.
1814 */
1815 if (new_cursor_col >= 0)
1816 {
1817 /*
1818 * When changing the indent while the cursor is touching it, reset
1819 * Insstart_col to 0.
1820 */
1821 if (new_cursor_col == 0)
1822 insstart_less = MAXCOL;
1823 new_cursor_col += curwin->w_cursor.col;
1824 }
1825 else if (!(State & INSERT))
1826 new_cursor_col = curwin->w_cursor.col;
1827 else
1828 {
1829 /*
1830 * Compute the screen column where the cursor should be.
1831 */
1832 vcol = get_indent() - vcol;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001833 curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001834
1835 /*
1836 * Advance the cursor until we reach the right screen column.
1837 */
1838 vcol = last_vcol = 0;
1839 new_cursor_col = -1;
1840 ptr = ml_get_curline();
1841 while (vcol <= (int)curwin->w_virtcol)
1842 {
1843 last_vcol = vcol;
1844#ifdef FEAT_MBYTE
1845 if (has_mbyte && new_cursor_col >= 0)
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00001846 new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847 else
1848#endif
1849 ++new_cursor_col;
1850 vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol);
1851 }
1852 vcol = last_vcol;
1853
1854 /*
1855 * May need to insert spaces to be able to position the cursor on
1856 * the right screen column.
1857 */
1858 if (vcol != (int)curwin->w_virtcol)
1859 {
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001860 curwin->w_cursor.col = (colnr_T)new_cursor_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001861 i = (int)curwin->w_virtcol - vcol;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001862 ptr = alloc((unsigned)(i + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 if (ptr != NULL)
1864 {
1865 new_cursor_col += i;
1866 ptr[i] = NUL;
1867 while (--i >= 0)
1868 ptr[i] = ' ';
1869 ins_str(ptr);
1870 vim_free(ptr);
1871 }
1872 }
1873
1874 /*
1875 * When changing the indent while the cursor is in it, reset
1876 * Insstart_col to 0.
1877 */
1878 insstart_less = MAXCOL;
1879 }
1880
1881 curwin->w_p_list = save_p_list;
1882
1883 if (new_cursor_col <= 0)
1884 curwin->w_cursor.col = 0;
1885 else
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001886 curwin->w_cursor.col = (colnr_T)new_cursor_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001887 curwin->w_set_curswant = TRUE;
1888 changed_cline_bef_curs();
1889
1890 /*
1891 * May have to adjust the start of the insert.
1892 */
1893 if (State & INSERT)
1894 {
1895 if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
1896 {
1897 if ((int)Insstart.col <= insstart_less)
1898 Insstart.col = 0;
1899 else
1900 Insstart.col -= insstart_less;
1901 }
1902 if ((int)ai_col <= insstart_less)
1903 ai_col = 0;
1904 else
1905 ai_col -= insstart_less;
1906 }
1907
1908 /*
1909 * For REPLACE mode, may have to fix the replace stack, if it's possible.
1910 * If the number of characters before the cursor decreased, need to pop a
1911 * few characters from the replace stack.
1912 * If the number of characters before the cursor increased, need to push a
1913 * few NULs onto the replace stack.
1914 */
1915 if (REPLACE_NORMAL(State) && start_col >= 0)
1916 {
1917 while (start_col > (int)curwin->w_cursor.col)
1918 {
1919 replace_join(0); /* remove a NUL from the replace stack */
1920 --start_col;
1921 }
1922 while (start_col < (int)curwin->w_cursor.col || replaced)
1923 {
1924 replace_push(NUL);
1925 if (replaced)
1926 {
1927 replace_push(replaced);
1928 replaced = NUL;
1929 }
1930 ++start_col;
1931 }
1932 }
1933
1934#ifdef FEAT_VREPLACE
1935 /*
1936 * For VREPLACE mode, we also have to fix the replace stack. In this case
1937 * it is always possible because we backspace over the whole line and then
1938 * put it back again the way we wanted it.
1939 */
1940 if (State & VREPLACE_FLAG)
1941 {
1942 /* If orig_line didn't allocate, just return. At least we did the job,
1943 * even if you can't backspace. */
1944 if (orig_line == NULL)
1945 return;
1946
1947 /* Save new line */
1948 new_line = vim_strsave(ml_get_curline());
1949 if (new_line == NULL)
1950 return;
1951
1952 /* We only put back the new line up to the cursor */
1953 new_line[curwin->w_cursor.col] = NUL;
1954
1955 /* Put back original line */
1956 ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
1957 curwin->w_cursor.col = orig_col;
1958
1959 /* Backspace from cursor to start of line */
1960 backspace_until_column(0);
1961
1962 /* Insert new stuff into line again */
1963 ins_bytes(new_line);
1964
1965 vim_free(new_line);
1966 }
1967#endif
1968}
1969
1970/*
1971 * Truncate the space at the end of a line. This is to be used only in an
1972 * insert mode. It handles fixing the replace stack for REPLACE and VREPLACE
1973 * modes.
1974 */
1975 void
1976truncate_spaces(line)
1977 char_u *line;
1978{
1979 int i;
1980
1981 /* find start of trailing white space */
1982 for (i = (int)STRLEN(line) - 1; i >= 0 && vim_iswhite(line[i]); i--)
1983 {
1984 if (State & REPLACE_FLAG)
1985 replace_join(0); /* remove a NUL from the replace stack */
1986 }
1987 line[i + 1] = NUL;
1988}
1989
1990#if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
1991 || defined(FEAT_COMMENTS) || defined(PROTO)
1992/*
1993 * Backspace the cursor until the given column. Handles REPLACE and VREPLACE
1994 * modes correctly. May also be used when not in insert mode at all.
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00001995 * Will attempt not to go before "col" even when there is a composing
1996 * character.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001997 */
1998 void
1999backspace_until_column(col)
2000 int col;
2001{
2002 while ((int)curwin->w_cursor.col > col)
2003 {
2004 curwin->w_cursor.col--;
2005 if (State & REPLACE_FLAG)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002006 replace_do_bs(col);
2007 else if (!del_char_after_col(col))
2008 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002009 }
2010}
2011#endif
2012
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002013/*
2014 * Like del_char(), but make sure not to go before column "limit_col".
2015 * Only matters when there are composing characters.
2016 * Return TRUE when something was deleted.
2017 */
2018 static int
2019del_char_after_col(limit_col)
Bram Moolenaar0c094b92009-05-14 20:20:33 +00002020 int limit_col UNUSED;
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002021{
2022#ifdef FEAT_MBYTE
2023 if (enc_utf8 && limit_col >= 0)
2024 {
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002025 colnr_T ecol = curwin->w_cursor.col + 1;
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002026
2027 /* Make sure the cursor is at the start of a character, but
2028 * skip forward again when going too far back because of a
2029 * composing character. */
2030 mb_adjust_cursor();
Bram Moolenaar5b3e4602009-02-04 10:20:58 +00002031 while (curwin->w_cursor.col < (colnr_T)limit_col)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002032 {
2033 int l = utf_ptr2len(ml_get_cursor());
2034
2035 if (l == 0) /* end of line */
2036 break;
2037 curwin->w_cursor.col += l;
2038 }
2039 if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol)
2040 return FALSE;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002041 del_bytes((long)((int)ecol - curwin->w_cursor.col), FALSE, TRUE);
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002042 }
2043 else
2044#endif
2045 (void)del_char(FALSE);
2046 return TRUE;
2047}
2048
Bram Moolenaar071d4272004-06-13 20:20:40 +00002049#if defined(FEAT_INS_EXPAND) || defined(PROTO)
2050/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002051 * CTRL-X pressed in Insert mode.
2052 */
2053 static void
2054ins_ctrl_x()
2055{
2056 /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X
2057 * CTRL-V works like CTRL-N */
2058 if (ctrl_x_mode != CTRL_X_CMDLINE)
2059 {
2060 /* if the next ^X<> won't ADD nothing, then reset
2061 * compl_cont_status */
2062 if (compl_cont_status & CONT_N_ADDS)
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002063 compl_cont_status |= CONT_INTRPT;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002064 else
2065 compl_cont_status = 0;
2066 /* We're not sure which CTRL-X mode it will be yet */
2067 ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
2068 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
2069 edit_submode_pre = NULL;
2070 showmode();
2071 }
2072}
2073
2074/*
2075 * Return TRUE if the 'dict' or 'tsr' option can be used.
2076 */
2077 static int
2078has_compl_option(dict_opt)
2079 int dict_opt;
2080{
Bram Moolenaar0b238792006-03-02 22:49:12 +00002081 if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002082# ifdef FEAT_SPELL
2083 && !curwin->w_p_spell
2084# endif
2085 )
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002086 : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL))
2087 {
2088 ctrl_x_mode = 0;
2089 edit_submode = NULL;
2090 msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty")
2091 : (char_u *)_("'thesaurus' option is empty"),
2092 hl_attr(HLF_E));
2093 if (emsg_silent == 0)
2094 {
2095 vim_beep();
2096 setcursor();
2097 out_flush();
2098 ui_delay(2000L, FALSE);
2099 }
2100 return FALSE;
2101 }
2102 return TRUE;
2103}
2104
2105/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002106 * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
2107 * This depends on the current mode.
2108 */
2109 int
2110vim_is_ctrl_x_key(c)
2111 int c;
2112{
2113 /* Always allow ^R - let it's results then be checked */
2114 if (c == Ctrl_R)
2115 return TRUE;
2116
Bram Moolenaare3226be2005-12-18 22:10:00 +00002117 /* Accept <PageUp> and <PageDown> if the popup menu is visible. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002118 if (ins_compl_pum_key(c))
Bram Moolenaare3226be2005-12-18 22:10:00 +00002119 return TRUE;
2120
Bram Moolenaar071d4272004-06-13 20:20:40 +00002121 switch (ctrl_x_mode)
2122 {
2123 case 0: /* Not in any CTRL-X mode */
2124 return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
2125 case CTRL_X_NOT_DEFINED_YET:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002126 return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
Bram Moolenaar071d4272004-06-13 20:20:40 +00002127 || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
2128 || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
2129 || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
Bram Moolenaar488c6512005-08-11 20:09:58 +00002130 || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
2131 || c == Ctrl_S || c == 's');
Bram Moolenaar071d4272004-06-13 20:20:40 +00002132 case CTRL_X_SCROLL:
2133 return (c == Ctrl_Y || c == Ctrl_E);
2134 case CTRL_X_WHOLE_LINE:
2135 return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
2136 case CTRL_X_FILES:
2137 return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
2138 case CTRL_X_DICTIONARY:
2139 return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
2140 case CTRL_X_THESAURUS:
2141 return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
2142 case CTRL_X_TAGS:
2143 return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
2144#ifdef FEAT_FIND_ID
2145 case CTRL_X_PATH_PATTERNS:
2146 return (c == Ctrl_P || c == Ctrl_N);
2147 case CTRL_X_PATH_DEFINES:
2148 return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
2149#endif
2150 case CTRL_X_CMDLINE:
2151 return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
2152 || c == Ctrl_X);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00002153#ifdef FEAT_COMPL_FUNC
2154 case CTRL_X_FUNCTION:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002155 return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N);
Bram Moolenaarf75a9632005-09-13 21:20:47 +00002156 case CTRL_X_OMNI:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002157 return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N);
Bram Moolenaare344bea2005-09-01 20:46:49 +00002158#endif
Bram Moolenaar488c6512005-08-11 20:09:58 +00002159 case CTRL_X_SPELL:
2160 return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002161 }
2162 EMSG(_(e_internal));
2163 return FALSE;
2164}
2165
2166/*
Bram Moolenaar711d5b52007-10-19 18:40:51 +00002167 * Return TRUE when character "c" is part of the item currently being
2168 * completed. Used to decide whether to abandon complete mode when the menu
2169 * is visible.
2170 */
2171 static int
2172ins_compl_accept_char(c)
2173 int c;
2174{
2175 if (ctrl_x_mode & CTRL_X_WANT_IDENT)
2176 /* When expanding an identifier only accept identifier chars. */
2177 return vim_isIDc(c);
2178
2179 switch (ctrl_x_mode)
2180 {
2181 case CTRL_X_FILES:
2182 /* When expanding file name only accept file name chars. But not
2183 * path separators, so that "proto/<Tab>" expands files in
2184 * "proto", not "proto/" as a whole */
2185 return vim_isfilec(c) && !vim_ispathsep(c);
2186
2187 case CTRL_X_CMDLINE:
2188 case CTRL_X_OMNI:
2189 /* Command line and Omni completion can work with just about any
2190 * printable character, but do stop at white space. */
2191 return vim_isprintc(c) && !vim_iswhite(c);
2192
2193 case CTRL_X_WHOLE_LINE:
2194 /* For while line completion a space can be part of the line. */
2195 return vim_isprintc(c);
2196 }
2197 return vim_iswordc(c);
2198}
2199
2200/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002201 * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
Bram Moolenaar071d4272004-06-13 20:20:40 +00002202 * case of the originally typed text is used, and the case of the completed
Bram Moolenaar34e0bfa2007-05-10 18:44:18 +00002203 * text is inferred, ie this tries to work out what case you probably wanted
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204 * the rest of the word to be in -- webb
2205 */
2206 int
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002207ins_compl_add_infercase(str, len, icase, fname, dir, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002208 char_u *str;
2209 int len;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002210 int icase;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002211 char_u *fname;
2212 int dir;
Bram Moolenaar572cb562005-08-05 21:35:02 +00002213 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002214{
Bram Moolenaara2993e12007-08-12 14:38:46 +00002215 char_u *p;
2216 int i, c;
2217 int actual_len; /* Take multi-byte characters */
2218 int actual_compl_length; /* into account. */
Bram Moolenaar04fa5422010-05-28 21:31:58 +02002219 int min_len;
Bram Moolenaar97b98102009-11-17 16:41:01 +00002220 int *wca; /* Wide character array. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221 int has_lower = FALSE;
2222 int was_letter = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223
Bram Moolenaare40e57c2007-11-08 12:04:26 +00002224 if (p_ic && curbuf->b_p_inf && len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002225 {
Bram Moolenaara2993e12007-08-12 14:38:46 +00002226 /* Infer case of completed part. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227
Bram Moolenaara2993e12007-08-12 14:38:46 +00002228 /* Find actual length of completion. */
2229#ifdef FEAT_MBYTE
2230 if (has_mbyte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002231 {
Bram Moolenaara2993e12007-08-12 14:38:46 +00002232 p = str;
2233 actual_len = 0;
2234 while (*p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002235 {
Bram Moolenaara2993e12007-08-12 14:38:46 +00002236 mb_ptr_adv(p);
2237 ++actual_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 }
2239 }
Bram Moolenaara2993e12007-08-12 14:38:46 +00002240 else
2241#endif
2242 actual_len = len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002243
Bram Moolenaara2993e12007-08-12 14:38:46 +00002244 /* Find actual length of original text. */
2245#ifdef FEAT_MBYTE
2246 if (has_mbyte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002247 {
Bram Moolenaara2993e12007-08-12 14:38:46 +00002248 p = compl_orig_text;
2249 actual_compl_length = 0;
2250 while (*p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002251 {
Bram Moolenaara2993e12007-08-12 14:38:46 +00002252 mb_ptr_adv(p);
2253 ++actual_compl_length;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002254 }
2255 }
Bram Moolenaara2993e12007-08-12 14:38:46 +00002256 else
2257#endif
2258 actual_compl_length = compl_length;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002259
Bram Moolenaar04fa5422010-05-28 21:31:58 +02002260 /* "actual_len" may be smaller than "actual_compl_length" when using
2261 * thesaurus, only use the minimum when comparing. */
2262 min_len = actual_len < actual_compl_length
2263 ? actual_len : actual_compl_length;
2264
Bram Moolenaara2993e12007-08-12 14:38:46 +00002265 /* Allocate wide character array for the completion and fill it. */
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002266 wca = (int *)alloc((unsigned)(actual_len * sizeof(int)));
Bram Moolenaara2993e12007-08-12 14:38:46 +00002267 if (wca != NULL)
2268 {
2269 p = str;
2270 for (i = 0; i < actual_len; ++i)
2271#ifdef FEAT_MBYTE
2272 if (has_mbyte)
2273 wca[i] = mb_ptr2char_adv(&p);
2274 else
2275#endif
2276 wca[i] = *(p++);
2277
2278 /* Rule 1: Were any chars converted to lower? */
2279 p = compl_orig_text;
Bram Moolenaar04fa5422010-05-28 21:31:58 +02002280 for (i = 0; i < min_len; ++i)
Bram Moolenaara2993e12007-08-12 14:38:46 +00002281 {
2282#ifdef FEAT_MBYTE
2283 if (has_mbyte)
2284 c = mb_ptr2char_adv(&p);
2285 else
2286#endif
2287 c = *(p++);
2288 if (MB_ISLOWER(c))
2289 {
2290 has_lower = TRUE;
2291 if (MB_ISUPPER(wca[i]))
2292 {
2293 /* Rule 1 is satisfied. */
2294 for (i = actual_compl_length; i < actual_len; ++i)
2295 wca[i] = MB_TOLOWER(wca[i]);
2296 break;
2297 }
2298 }
2299 }
2300
2301 /*
2302 * Rule 2: No lower case, 2nd consecutive letter converted to
2303 * upper case.
2304 */
2305 if (!has_lower)
2306 {
2307 p = compl_orig_text;
Bram Moolenaar04fa5422010-05-28 21:31:58 +02002308 for (i = 0; i < min_len; ++i)
Bram Moolenaara2993e12007-08-12 14:38:46 +00002309 {
2310#ifdef FEAT_MBYTE
2311 if (has_mbyte)
2312 c = mb_ptr2char_adv(&p);
2313 else
2314#endif
2315 c = *(p++);
2316 if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
2317 {
2318 /* Rule 2 is satisfied. */
2319 for (i = actual_compl_length; i < actual_len; ++i)
2320 wca[i] = MB_TOUPPER(wca[i]);
2321 break;
2322 }
2323 was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
2324 }
2325 }
2326
2327 /* Copy the original case of the part we typed. */
2328 p = compl_orig_text;
Bram Moolenaar04fa5422010-05-28 21:31:58 +02002329 for (i = 0; i < min_len; ++i)
Bram Moolenaara2993e12007-08-12 14:38:46 +00002330 {
2331#ifdef FEAT_MBYTE
2332 if (has_mbyte)
2333 c = mb_ptr2char_adv(&p);
2334 else
2335#endif
2336 c = *(p++);
2337 if (MB_ISLOWER(c))
2338 wca[i] = MB_TOLOWER(wca[i]);
2339 else if (MB_ISUPPER(c))
2340 wca[i] = MB_TOUPPER(wca[i]);
2341 }
2342
Bram Moolenaare40e57c2007-11-08 12:04:26 +00002343 /*
Bram Moolenaara2993e12007-08-12 14:38:46 +00002344 * Generate encoding specific output from wide character array.
2345 * Multi-byte characters can occupy up to five bytes more than
2346 * ASCII characters, and we also need one byte for NUL, so stay
2347 * six bytes away from the edge of IObuff.
2348 */
2349 p = IObuff;
2350 i = 0;
2351 while (i < actual_len && (p - IObuff + 6) < IOSIZE)
2352#ifdef FEAT_MBYTE
2353 if (has_mbyte)
Bram Moolenaare0ca7b22007-11-24 20:28:24 +00002354 p += (*mb_char2bytes)(wca[i++], p);
Bram Moolenaara2993e12007-08-12 14:38:46 +00002355 else
2356#endif
2357 *(p++) = wca[i++];
2358 *p = NUL;
2359
2360 vim_free(wca);
2361 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002362
Bram Moolenaar4a85b412006-04-23 22:40:29 +00002363 return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
2364 flags, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002365 }
Bram Moolenaar4a85b412006-04-23 22:40:29 +00002366 return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002367}
2368
2369/*
2370 * Add a match to the list of matches.
2371 * If the given string is already in the list of completions, then return
Bram Moolenaar572cb562005-08-05 21:35:02 +00002372 * NOTDONE, otherwise add it to the list and return OK. If there is an error,
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002373 * maybe because alloc() returns NULL, then FAIL is returned.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002374 */
Bram Moolenaar4a85b412006-04-23 22:40:29 +00002375 static int
Bram Moolenaar89d40322006-08-29 15:30:07 +00002376ins_compl_add(str, len, icase, fname, cptext, cdir, flags, adup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002377 char_u *str;
2378 int len;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002379 int icase;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380 char_u *fname;
Bram Moolenaar4a85b412006-04-23 22:40:29 +00002381 char_u **cptext; /* extra text for popup menu or NULL */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002382 int cdir;
Bram Moolenaar572cb562005-08-05 21:35:02 +00002383 int flags;
Bram Moolenaar89d40322006-08-29 15:30:07 +00002384 int adup; /* accept duplicate match */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002385{
Bram Moolenaar572cb562005-08-05 21:35:02 +00002386 compl_T *match;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002387 int dir = (cdir == 0 ? compl_direction : cdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002388
2389 ui_breakcheck();
2390 if (got_int)
Bram Moolenaar572cb562005-08-05 21:35:02 +00002391 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002392 if (len < 0)
2393 len = (int)STRLEN(str);
2394
2395 /*
2396 * If the same match is already present, don't add it.
2397 */
Bram Moolenaar89d40322006-08-29 15:30:07 +00002398 if (compl_first_match != NULL && !adup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002399 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002400 match = compl_first_match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002401 do
2402 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00002403 if ( !(match->cp_flags & ORIGINAL_TEXT)
Bram Moolenaar5948a572006-10-03 13:49:29 +00002404 && STRNCMP(match->cp_str, str, len) == 0
Bram Moolenaar572cb562005-08-05 21:35:02 +00002405 && match->cp_str[len] == NUL)
2406 return NOTDONE;
2407 match = match->cp_next;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002408 } while (match != NULL && match != compl_first_match);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002409 }
2410
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002411 /* Remove any popup menu before changing the list of matches. */
2412 ins_compl_del_pum();
2413
Bram Moolenaar071d4272004-06-13 20:20:40 +00002414 /*
2415 * Allocate a new match structure.
2416 * Copy the values to the new match structure.
2417 */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002418 match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002419 if (match == NULL)
Bram Moolenaar572cb562005-08-05 21:35:02 +00002420 return FAIL;
2421 match->cp_number = -1;
2422 if (flags & ORIGINAL_TEXT)
Bram Moolenaar572cb562005-08-05 21:35:02 +00002423 match->cp_number = 0;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002424 if ((match->cp_str = vim_strnsave(str, len)) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002425 {
2426 vim_free(match);
Bram Moolenaar572cb562005-08-05 21:35:02 +00002427 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002428 }
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002429 match->cp_icase = icase;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002430
Bram Moolenaar071d4272004-06-13 20:20:40 +00002431 /* match-fname is:
Bram Moolenaar572cb562005-08-05 21:35:02 +00002432 * - compl_curr_match->cp_fname if it is a string equal to fname.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002433 * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
2434 * - NULL otherwise. --Acevedo */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002435 if (fname != NULL
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00002436 && compl_curr_match != NULL
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002437 && compl_curr_match->cp_fname != NULL
2438 && STRCMP(fname, compl_curr_match->cp_fname) == 0)
Bram Moolenaar572cb562005-08-05 21:35:02 +00002439 match->cp_fname = compl_curr_match->cp_fname;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002440 else if (fname != NULL)
2441 {
2442 match->cp_fname = vim_strsave(fname);
Bram Moolenaar572cb562005-08-05 21:35:02 +00002443 flags |= FREE_FNAME;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002444 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445 else
Bram Moolenaar572cb562005-08-05 21:35:02 +00002446 match->cp_fname = NULL;
2447 match->cp_flags = flags;
Bram Moolenaar39f05632006-03-19 22:15:26 +00002448
2449 if (cptext != NULL)
2450 {
2451 int i;
2452
2453 for (i = 0; i < CPT_COUNT; ++i)
2454 if (cptext[i] != NULL && *cptext[i] != NUL)
2455 match->cp_text[i] = vim_strsave(cptext[i]);
2456 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002457
2458 /*
2459 * Link the new match structure in the list of matches.
2460 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002461 if (compl_first_match == NULL)
Bram Moolenaar572cb562005-08-05 21:35:02 +00002462 match->cp_next = match->cp_prev = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463 else if (dir == FORWARD)
2464 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00002465 match->cp_next = compl_curr_match->cp_next;
2466 match->cp_prev = compl_curr_match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002467 }
2468 else /* BACKWARD */
2469 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00002470 match->cp_next = compl_curr_match;
2471 match->cp_prev = compl_curr_match->cp_prev;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002472 }
Bram Moolenaar572cb562005-08-05 21:35:02 +00002473 if (match->cp_next)
2474 match->cp_next->cp_prev = match;
2475 if (match->cp_prev)
2476 match->cp_prev->cp_next = match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002477 else /* if there's nothing before, it is the first match */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002478 compl_first_match = match;
2479 compl_curr_match = match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002481 /*
2482 * Find the longest common string if still doing that.
2483 */
2484 if (compl_get_longest && (flags & ORIGINAL_TEXT) == 0)
2485 ins_compl_longest_match(match);
2486
Bram Moolenaar071d4272004-06-13 20:20:40 +00002487 return OK;
2488}
2489
2490/*
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002491 * Return TRUE if "str[len]" matches with match->cp_str, considering
2492 * match->cp_icase.
2493 */
2494 static int
2495ins_compl_equal(match, str, len)
2496 compl_T *match;
2497 char_u *str;
2498 int len;
2499{
2500 if (match->cp_icase)
2501 return STRNICMP(match->cp_str, str, (size_t)len) == 0;
2502 return STRNCMP(match->cp_str, str, (size_t)len) == 0;
2503}
2504
2505/*
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002506 * Reduce the longest common string for match "match".
2507 */
2508 static void
2509ins_compl_longest_match(match)
2510 compl_T *match;
2511{
2512 char_u *p, *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002513 int c1, c2;
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002514 int had_match;
2515
2516 if (compl_leader == NULL)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002517 {
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002518 /* First match, use it as a whole. */
2519 compl_leader = vim_strsave(match->cp_str);
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002520 if (compl_leader != NULL)
2521 {
2522 had_match = (curwin->w_cursor.col > compl_col);
2523 ins_compl_delete();
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002524 ins_bytes(compl_leader + ins_compl_len());
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002525 ins_redraw(FALSE);
2526
2527 /* When the match isn't there (to avoid matching itself) remove it
2528 * again after redrawing. */
2529 if (!had_match)
2530 ins_compl_delete();
2531 compl_used_match = FALSE;
2532 }
2533 }
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002534 else
2535 {
2536 /* Reduce the text if this match differs from compl_leader. */
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002537 p = compl_leader;
2538 s = match->cp_str;
2539 while (*p != NUL)
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002540 {
2541#ifdef FEAT_MBYTE
2542 if (has_mbyte)
2543 {
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002544 c1 = mb_ptr2char(p);
2545 c2 = mb_ptr2char(s);
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002546 }
2547 else
2548#endif
2549 {
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002550 c1 = *p;
2551 c2 = *s;
2552 }
2553 if (match->cp_icase ? (MB_TOLOWER(c1) != MB_TOLOWER(c2))
2554 : (c1 != c2))
2555 break;
2556#ifdef FEAT_MBYTE
2557 if (has_mbyte)
2558 {
2559 mb_ptr_adv(p);
2560 mb_ptr_adv(s);
2561 }
2562 else
2563#endif
2564 {
2565 ++p;
2566 ++s;
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002567 }
2568 }
2569
2570 if (*p != NUL)
2571 {
2572 /* Leader was shortened, need to change the inserted text. */
2573 *p = NUL;
2574 had_match = (curwin->w_cursor.col > compl_col);
2575 ins_compl_delete();
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00002576 ins_bytes(compl_leader + ins_compl_len());
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002577 ins_redraw(FALSE);
2578
2579 /* When the match isn't there (to avoid matching itself) remove it
2580 * again after redrawing. */
2581 if (!had_match)
2582 ins_compl_delete();
2583 }
2584
2585 compl_used_match = FALSE;
2586 }
2587}
2588
2589/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002590 * Add an array of matches to the list of matches.
2591 * Frees matches[].
2592 */
2593 static void
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002594ins_compl_add_matches(num_matches, matches, icase)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002595 int num_matches;
2596 char_u **matches;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002597 int icase;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002598{
2599 int i;
2600 int add_r = OK;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002601 int dir = compl_direction;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002602
Bram Moolenaar572cb562005-08-05 21:35:02 +00002603 for (i = 0; i < num_matches && add_r != FAIL; i++)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002604 if ((add_r = ins_compl_add(matches[i], -1, icase,
Bram Moolenaar4a85b412006-04-23 22:40:29 +00002605 NULL, NULL, dir, 0, FALSE)) == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 /* if dir was BACKWARD then honor it just once */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002607 dir = FORWARD;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002608 FreeWild(num_matches, matches);
2609}
2610
2611/* Make the completion list cyclic.
2612 * Return the number of matches (excluding the original).
2613 */
2614 static int
2615ins_compl_make_cyclic()
2616{
Bram Moolenaar572cb562005-08-05 21:35:02 +00002617 compl_T *match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002618 int count = 0;
2619
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002620 if (compl_first_match != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621 {
2622 /*
2623 * Find the end of the list.
2624 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00002625 match = compl_first_match;
2626 /* there's always an entry for the compl_orig_text, it doesn't count. */
Bram Moolenaar572cb562005-08-05 21:35:02 +00002627 while (match->cp_next != NULL && match->cp_next != compl_first_match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00002629 match = match->cp_next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002630 ++count;
2631 }
Bram Moolenaar572cb562005-08-05 21:35:02 +00002632 match->cp_next = compl_first_match;
2633 compl_first_match->cp_prev = match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 }
2635 return count;
2636}
2637
Bram Moolenaara94bc432006-03-10 21:42:59 +00002638/*
2639 * Start completion for the complete() function.
2640 * "startcol" is where the matched text starts (1 is first column).
2641 * "list" is the list of matches.
2642 */
2643 void
2644set_completion(startcol, list)
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002645 colnr_T startcol;
Bram Moolenaara94bc432006-03-10 21:42:59 +00002646 list_T *list;
2647{
2648 /* If already doing completions stop it. */
2649 if (ctrl_x_mode != 0)
2650 ins_compl_prep(' ');
2651 ins_compl_clear();
2652
2653 if (stop_arrow() == FAIL)
2654 return;
2655
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002656 if (startcol > curwin->w_cursor.col)
Bram Moolenaara94bc432006-03-10 21:42:59 +00002657 startcol = curwin->w_cursor.col;
2658 compl_col = startcol;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002659 compl_length = (int)curwin->w_cursor.col - (int)startcol;
Bram Moolenaara94bc432006-03-10 21:42:59 +00002660 /* compl_pattern doesn't need to be set */
2661 compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
2662 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
Bram Moolenaare8c3a142006-08-29 14:30:35 +00002663 -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
Bram Moolenaara94bc432006-03-10 21:42:59 +00002664 return;
2665
2666 /* Handle like dictionary completion. */
2667 ctrl_x_mode = CTRL_X_WHOLE_LINE;
2668
2669 ins_compl_add_list(list);
2670 compl_matches = ins_compl_make_cyclic();
2671 compl_started = TRUE;
2672 compl_used_match = TRUE;
Bram Moolenaar5495cc92006-08-16 14:23:04 +00002673 compl_cont_status = 0;
Bram Moolenaara94bc432006-03-10 21:42:59 +00002674
2675 compl_curr_match = compl_first_match;
2676 ins_complete(Ctrl_N);
2677 out_flush();
2678}
2679
2680
Bram Moolenaar9372a112005-12-06 19:59:18 +00002681/* "compl_match_array" points the currently displayed list of entries in the
2682 * popup menu. It is NULL when there is no popup menu. */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002683static pumitem_T *compl_match_array = NULL;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002684static int compl_match_arraysize;
2685
2686/*
2687 * Update the screen and when there is any scrolling remove the popup menu.
2688 */
2689 static void
2690ins_compl_upd_pum()
2691{
2692 int h;
2693
2694 if (compl_match_array != NULL)
2695 {
2696 h = curwin->w_cline_height;
2697 update_screen(0);
2698 if (h != curwin->w_cline_height)
2699 ins_compl_del_pum();
2700 }
2701}
2702
2703/*
2704 * Remove any popup menu.
2705 */
2706 static void
2707ins_compl_del_pum()
2708{
2709 if (compl_match_array != NULL)
2710 {
2711 pum_undisplay();
2712 vim_free(compl_match_array);
2713 compl_match_array = NULL;
2714 }
2715}
2716
2717/*
2718 * Return TRUE if the popup menu should be displayed.
2719 */
2720 static int
2721pum_wanted()
2722{
Bram Moolenaar65c923a2006-03-03 22:56:30 +00002723 /* 'completeopt' must contain "menu" or "menuone" */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00002724 if (vim_strchr(p_cot, 'm') == NULL)
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002725 return FALSE;
2726
2727 /* The display looks bad on a B&W display. */
2728 if (t_colors < 8
2729#ifdef FEAT_GUI
2730 && !gui.in_use
2731#endif
2732 )
2733 return FALSE;
Bram Moolenaara6557602006-02-04 22:43:20 +00002734 return TRUE;
2735}
2736
2737/*
2738 * Return TRUE if there are two or more matches to be shown in the popup menu.
Bram Moolenaar65c923a2006-03-03 22:56:30 +00002739 * One if 'completopt' contains "menuone".
Bram Moolenaara6557602006-02-04 22:43:20 +00002740 */
2741 static int
Bram Moolenaar65c923a2006-03-03 22:56:30 +00002742pum_enough_matches()
Bram Moolenaara6557602006-02-04 22:43:20 +00002743{
2744 compl_T *compl;
2745 int i;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002746
2747 /* Don't display the popup menu if there are no matches or there is only
2748 * one (ignoring the original text). */
2749 compl = compl_first_match;
2750 i = 0;
2751 do
2752 {
2753 if (compl == NULL
2754 || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2))
2755 break;
2756 compl = compl->cp_next;
2757 } while (compl != compl_first_match);
2758
Bram Moolenaar65c923a2006-03-03 22:56:30 +00002759 if (strstr((char *)p_cot, "menuone") != NULL)
2760 return (i >= 1);
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002761 return (i >= 2);
2762}
2763
2764/*
2765 * Show the popup menu for the list of matches.
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002766 * Also adjusts "compl_shown_match" to an entry that is actually displayed.
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002767 */
Bram Moolenaar280f1262006-01-30 00:14:18 +00002768 void
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002769ins_compl_show_pum()
2770{
2771 compl_T *compl;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002772 compl_T *shown_compl = NULL;
2773 int did_find_shown_match = FALSE;
2774 int shown_match_ok = FALSE;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002775 int i;
2776 int cur = -1;
2777 colnr_T col;
Bram Moolenaara6557602006-02-04 22:43:20 +00002778 int lead_len = 0;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002779
Bram Moolenaar65c923a2006-03-03 22:56:30 +00002780 if (!pum_wanted() || !pum_enough_matches())
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002781 return;
2782
Bram Moolenaar433f7c82006-03-21 21:29:36 +00002783#if defined(FEAT_EVAL)
2784 /* Dirty hard-coded hack: remove any matchparen highlighting. */
2785 do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif");
2786#endif
2787
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002788 /* Update the screen before drawing the popup menu over it. */
2789 update_screen(0);
2790
2791 if (compl_match_array == NULL)
2792 {
2793 /* Need to build the popup menu list. */
2794 compl_match_arraysize = 0;
2795 compl = compl_first_match;
Bram Moolenaara6557602006-02-04 22:43:20 +00002796 if (compl_leader != NULL)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002797 lead_len = (int)STRLEN(compl_leader);
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002798 do
2799 {
Bram Moolenaara6557602006-02-04 22:43:20 +00002800 if ((compl->cp_flags & ORIGINAL_TEXT) == 0
2801 && (compl_leader == NULL
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002802 || ins_compl_equal(compl, compl_leader, lead_len)))
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002803 ++compl_match_arraysize;
2804 compl = compl->cp_next;
2805 } while (compl != NULL && compl != compl_first_match);
Bram Moolenaara6557602006-02-04 22:43:20 +00002806 if (compl_match_arraysize == 0)
2807 return;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002808 compl_match_array = (pumitem_T *)alloc_clear(
2809 (unsigned)(sizeof(pumitem_T)
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002810 * compl_match_arraysize));
2811 if (compl_match_array != NULL)
2812 {
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00002813 /* If the current match is the original text don't find the first
2814 * match after it, don't highlight anything. */
2815 if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
2816 shown_match_ok = TRUE;
2817
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002818 i = 0;
2819 compl = compl_first_match;
2820 do
2821 {
Bram Moolenaara6557602006-02-04 22:43:20 +00002822 if ((compl->cp_flags & ORIGINAL_TEXT) == 0
2823 && (compl_leader == NULL
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002824 || ins_compl_equal(compl, compl_leader, lead_len)))
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002825 {
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002826 if (!shown_match_ok)
2827 {
2828 if (compl == compl_shown_match || did_find_shown_match)
2829 {
2830 /* This item is the shown match or this is the
2831 * first displayed item after the shown match. */
2832 compl_shown_match = compl;
2833 did_find_shown_match = TRUE;
2834 shown_match_ok = TRUE;
2835 }
2836 else
2837 /* Remember this displayed match for when the
2838 * shown match is just below it. */
2839 shown_compl = compl;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002840 cur = i;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002841 }
Bram Moolenaar39f05632006-03-19 22:15:26 +00002842
2843 if (compl->cp_text[CPT_ABBR] != NULL)
2844 compl_match_array[i].pum_text =
2845 compl->cp_text[CPT_ABBR];
2846 else
2847 compl_match_array[i].pum_text = compl->cp_str;
2848 compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
2849 compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
2850 if (compl->cp_text[CPT_MENU] != NULL)
2851 compl_match_array[i++].pum_extra =
2852 compl->cp_text[CPT_MENU];
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002853 else
2854 compl_match_array[i++].pum_extra = compl->cp_fname;
2855 }
2856
2857 if (compl == compl_shown_match)
2858 {
2859 did_find_shown_match = TRUE;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00002860
2861 /* When the original text is the shown match don't set
2862 * compl_shown_match. */
2863 if (compl->cp_flags & ORIGINAL_TEXT)
2864 shown_match_ok = TRUE;
2865
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002866 if (!shown_match_ok && shown_compl != NULL)
2867 {
2868 /* The shown match isn't displayed, set it to the
2869 * previously displayed match. */
2870 compl_shown_match = shown_compl;
2871 shown_match_ok = TRUE;
2872 }
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002873 }
2874 compl = compl->cp_next;
2875 } while (compl != NULL && compl != compl_first_match);
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002876
2877 if (!shown_match_ok) /* no displayed match at all */
2878 cur = -1;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002879 }
2880 }
2881 else
2882 {
2883 /* popup menu already exists, only need to find the current item.*/
Bram Moolenaara6557602006-02-04 22:43:20 +00002884 for (i = 0; i < compl_match_arraysize; ++i)
Bram Moolenaar39f05632006-03-19 22:15:26 +00002885 if (compl_match_array[i].pum_text == compl_shown_match->cp_str
2886 || compl_match_array[i].pum_text
2887 == compl_shown_match->cp_text[CPT_ABBR])
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00002888 {
2889 cur = i;
Bram Moolenaara6557602006-02-04 22:43:20 +00002890 break;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00002891 }
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002892 }
2893
2894 if (compl_match_array != NULL)
2895 {
2896 /* Compute the screen column of the start of the completed text.
2897 * Use the cursor to get all wrapping and other settings right. */
2898 col = curwin->w_cursor.col;
2899 curwin->w_cursor.col = compl_col;
Bram Moolenaard289f132006-03-11 21:30:53 +00002900 pum_display(compl_match_array, compl_match_arraysize, cur);
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002901 curwin->w_cursor.col = col;
2902 }
2903}
2904
Bram Moolenaar071d4272004-06-13 20:20:40 +00002905#define DICT_FIRST (1) /* use just first element in "dict" */
2906#define DICT_EXACT (2) /* "dict" is the exact name of a file */
Bram Moolenaar280f1262006-01-30 00:14:18 +00002907
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908/*
Bram Moolenaar0b238792006-03-02 22:49:12 +00002909 * Add any identifiers that match the given pattern in the list of dictionary
2910 * files "dict_start" to the list of completions.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002911 */
2912 static void
Bram Moolenaar0b238792006-03-02 22:49:12 +00002913ins_compl_dictionaries(dict_start, pat, flags, thesaurus)
2914 char_u *dict_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915 char_u *pat;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002916 int flags; /* DICT_FIRST and/or DICT_EXACT */
Bram Moolenaar0b238792006-03-02 22:49:12 +00002917 int thesaurus; /* Thesaurus completion */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918{
Bram Moolenaar0b238792006-03-02 22:49:12 +00002919 char_u *dict = dict_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920 char_u *ptr;
2921 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002922 regmatch_T regmatch;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 char_u **files;
2924 int count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002925 int save_p_scs;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002926 int dir = compl_direction;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002927
Bram Moolenaar0b238792006-03-02 22:49:12 +00002928 if (*dict == NUL)
2929 {
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002930#ifdef FEAT_SPELL
Bram Moolenaar0b238792006-03-02 22:49:12 +00002931 /* When 'dictionary' is empty and spell checking is enabled use
2932 * "spell". */
2933 if (!thesaurus && curwin->w_p_spell)
2934 dict = (char_u *)"spell";
2935 else
2936#endif
2937 return;
2938 }
2939
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940 buf = alloc(LSIZE);
Bram Moolenaar0b238792006-03-02 22:49:12 +00002941 if (buf == NULL)
2942 return;
Bram Moolenaarfa3491a2007-02-20 02:49:19 +00002943 regmatch.regprog = NULL; /* so that we can goto theend */
Bram Moolenaar0b238792006-03-02 22:49:12 +00002944
Bram Moolenaar071d4272004-06-13 20:20:40 +00002945 /* If 'infercase' is set, don't use 'smartcase' here */
2946 save_p_scs = p_scs;
2947 if (curbuf->b_p_inf)
2948 p_scs = FALSE;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002949
2950 /* When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
2951 * to only match at the start of a line. Otherwise just match the
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002952 * pattern. Also need to double backslashes. */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002953 if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
2954 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002955 char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\");
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002956 size_t len;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002957
2958 if (pat_esc == NULL)
Bram Moolenaar6519ac82007-05-06 13:45:52 +00002959 goto theend;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002960 len = STRLEN(pat_esc) + 10;
2961 ptr = alloc((unsigned)len);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002962 if (ptr == NULL)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002963 {
2964 vim_free(pat_esc);
Bram Moolenaarfa3491a2007-02-20 02:49:19 +00002965 goto theend;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002966 }
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00002967 vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc);
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002968 regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
2969 vim_free(pat_esc);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002970 vim_free(ptr);
2971 }
2972 else
Bram Moolenaar0b238792006-03-02 22:49:12 +00002973 {
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002974 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
Bram Moolenaar0b238792006-03-02 22:49:12 +00002975 if (regmatch.regprog == NULL)
2976 goto theend;
2977 }
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002978
Bram Moolenaar071d4272004-06-13 20:20:40 +00002979 /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
2980 regmatch.rm_ic = ignorecase(pat);
Bram Moolenaar0b238792006-03-02 22:49:12 +00002981 while (*dict != NUL && !got_int && !compl_interrupted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982 {
2983 /* copy one dictionary file name into buf */
2984 if (flags == DICT_EXACT)
2985 {
2986 count = 1;
2987 files = &dict;
2988 }
2989 else
2990 {
2991 /* Expand wildcards in the dictionary name, but do not allow
2992 * backticks (for security, the 'dict' option may have been set in
2993 * a modeline). */
2994 copy_option_part(&dict, buf, LSIZE, ",");
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002995# ifdef FEAT_SPELL
Bram Moolenaar0b238792006-03-02 22:49:12 +00002996 if (!thesaurus && STRCMP(buf, "spell") == 0)
2997 count = -1;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002998 else
2999# endif
3000 if (vim_strchr(buf, '`') != NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00003001 || expand_wildcards(1, &buf, &count, &files,
3002 EW_FILE|EW_SILENT) != OK)
3003 count = 0;
3004 }
3005
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00003006# ifdef FEAT_SPELL
Bram Moolenaar0b238792006-03-02 22:49:12 +00003007 if (count == -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003008 {
Bram Moolenaar87b5ca52006-03-04 21:55:31 +00003009 /* Complete from active spelling. Skip "\<" in the pattern, we
3010 * don't use it as a RE. */
Bram Moolenaar0b238792006-03-02 22:49:12 +00003011 if (pat[0] == '\\' && pat[1] == '<')
3012 ptr = pat + 2;
3013 else
3014 ptr = pat;
Bram Moolenaar860cae12010-06-05 23:22:07 +02003015 spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003016 }
Bram Moolenaar0b238792006-03-02 22:49:12 +00003017 else
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00003018# endif
Bram Moolenaard7fd0c42006-08-22 17:55:55 +00003019 if (count > 0) /* avoid warning for using "files" uninit */
Bram Moolenaar0b238792006-03-02 22:49:12 +00003020 {
3021 ins_compl_files(count, files, thesaurus, flags,
3022 &regmatch, buf, &dir);
3023 if (flags != DICT_EXACT)
3024 FreeWild(count, files);
3025 }
3026 if (flags != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003027 break;
3028 }
Bram Moolenaar0b238792006-03-02 22:49:12 +00003029
3030theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +00003031 p_scs = save_p_scs;
3032 vim_free(regmatch.regprog);
3033 vim_free(buf);
3034}
3035
Bram Moolenaar0b238792006-03-02 22:49:12 +00003036 static void
3037ins_compl_files(count, files, thesaurus, flags, regmatch, buf, dir)
3038 int count;
3039 char_u **files;
3040 int thesaurus;
3041 int flags;
3042 regmatch_T *regmatch;
3043 char_u *buf;
3044 int *dir;
3045{
3046 char_u *ptr;
3047 int i;
3048 FILE *fp;
3049 int add_r;
3050
3051 for (i = 0; i < count && !got_int && !compl_interrupted; i++)
3052 {
3053 fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */
3054 if (flags != DICT_EXACT)
3055 {
3056 vim_snprintf((char *)IObuff, IOSIZE,
3057 _("Scanning dictionary: %s"), (char *)files[i]);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00003058 (void)msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
Bram Moolenaar0b238792006-03-02 22:49:12 +00003059 }
3060
3061 if (fp != NULL)
3062 {
3063 /*
3064 * Read dictionary file line by line.
3065 * Check each line for a match.
3066 */
3067 while (!got_int && !compl_interrupted
3068 && !vim_fgets(buf, LSIZE, fp))
3069 {
3070 ptr = buf;
3071 while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf)))
3072 {
3073 ptr = regmatch->startp[0];
3074 if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
3075 ptr = find_line_end(ptr);
3076 else
3077 ptr = find_word_end(ptr);
3078 add_r = ins_compl_add_infercase(regmatch->startp[0],
3079 (int)(ptr - regmatch->startp[0]),
Bram Moolenaare8c3a142006-08-29 14:30:35 +00003080 p_ic, files[i], *dir, 0);
Bram Moolenaar0b238792006-03-02 22:49:12 +00003081 if (thesaurus)
3082 {
3083 char_u *wstart;
3084
3085 /*
3086 * Add the other matches on the line
3087 */
Bram Moolenaara2993e12007-08-12 14:38:46 +00003088 ptr = buf;
Bram Moolenaar0b238792006-03-02 22:49:12 +00003089 while (!got_int)
3090 {
3091 /* Find start of the next word. Skip white
3092 * space and punctuation. */
3093 ptr = find_word_start(ptr);
3094 if (*ptr == NUL || *ptr == NL)
3095 break;
3096 wstart = ptr;
3097
Bram Moolenaara2993e12007-08-12 14:38:46 +00003098 /* Find end of the word. */
Bram Moolenaar0b238792006-03-02 22:49:12 +00003099#ifdef FEAT_MBYTE
3100 if (has_mbyte)
3101 /* Japanese words may have characters in
3102 * different classes, only separate words
3103 * with single-byte non-word characters. */
3104 while (*ptr != NUL)
3105 {
3106 int l = (*mb_ptr2len)(ptr);
3107
3108 if (l < 2 && !vim_iswordc(*ptr))
3109 break;
3110 ptr += l;
3111 }
3112 else
3113#endif
3114 ptr = find_word_end(ptr);
Bram Moolenaara2993e12007-08-12 14:38:46 +00003115
3116 /* Add the word. Skip the regexp match. */
3117 if (wstart != regmatch->startp[0])
3118 add_r = ins_compl_add_infercase(wstart,
3119 (int)(ptr - wstart),
3120 p_ic, files[i], *dir, 0);
Bram Moolenaar0b238792006-03-02 22:49:12 +00003121 }
3122 }
3123 if (add_r == OK)
3124 /* if dir was BACKWARD then honor it just once */
3125 *dir = FORWARD;
3126 else if (add_r == FAIL)
3127 break;
3128 /* avoid expensive call to vim_regexec() when at end
3129 * of line */
3130 if (*ptr == '\n' || got_int)
3131 break;
3132 }
3133 line_breakcheck();
3134 ins_compl_check_keys(50);
3135 }
3136 fclose(fp);
3137 }
3138 }
3139}
3140
Bram Moolenaar071d4272004-06-13 20:20:40 +00003141/*
3142 * Find the start of the next word.
3143 * Returns a pointer to the first char of the word. Also stops at a NUL.
3144 */
3145 char_u *
3146find_word_start(ptr)
3147 char_u *ptr;
3148{
3149#ifdef FEAT_MBYTE
3150 if (has_mbyte)
3151 while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00003152 ptr += (*mb_ptr2len)(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003153 else
3154#endif
3155 while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
3156 ++ptr;
3157 return ptr;
3158}
3159
3160/*
3161 * Find the end of the word. Assumes it starts inside a word.
3162 * Returns a pointer to just after the word.
3163 */
3164 char_u *
3165find_word_end(ptr)
3166 char_u *ptr;
3167{
3168#ifdef FEAT_MBYTE
3169 int start_class;
3170
3171 if (has_mbyte)
3172 {
3173 start_class = mb_get_class(ptr);
3174 if (start_class > 1)
3175 while (*ptr != NUL)
3176 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00003177 ptr += (*mb_ptr2len)(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 if (mb_get_class(ptr) != start_class)
3179 break;
3180 }
3181 }
3182 else
3183#endif
3184 while (vim_iswordc(*ptr))
3185 ++ptr;
3186 return ptr;
3187}
3188
3189/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00003190 * Find the end of the line, omitting CR and NL at the end.
3191 * Returns a pointer to just after the line.
3192 */
3193 static char_u *
3194find_line_end(ptr)
3195 char_u *ptr;
3196{
3197 char_u *s;
3198
3199 s = ptr + STRLEN(ptr);
3200 while (s > ptr && (s[-1] == CAR || s[-1] == NL))
3201 --s;
3202 return s;
3203}
3204
3205/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003206 * Free the list of completions
3207 */
3208 static void
3209ins_compl_free()
3210{
Bram Moolenaar572cb562005-08-05 21:35:02 +00003211 compl_T *match;
Bram Moolenaar39f05632006-03-19 22:15:26 +00003212 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003213
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003214 vim_free(compl_pattern);
3215 compl_pattern = NULL;
Bram Moolenaara6557602006-02-04 22:43:20 +00003216 vim_free(compl_leader);
3217 compl_leader = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003218
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003219 if (compl_first_match == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220 return;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003221
3222 ins_compl_del_pum();
3223 pum_clear();
3224
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003225 compl_curr_match = compl_first_match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003226 do
3227 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003228 match = compl_curr_match;
Bram Moolenaar572cb562005-08-05 21:35:02 +00003229 compl_curr_match = compl_curr_match->cp_next;
3230 vim_free(match->cp_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003231 /* several entries may use the same fname, free it just once. */
Bram Moolenaar572cb562005-08-05 21:35:02 +00003232 if (match->cp_flags & FREE_FNAME)
3233 vim_free(match->cp_fname);
Bram Moolenaar39f05632006-03-19 22:15:26 +00003234 for (i = 0; i < CPT_COUNT; ++i)
3235 vim_free(match->cp_text[i]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236 vim_free(match);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003237 } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
3238 compl_first_match = compl_curr_match = NULL;
Bram Moolenaar031e0dd2009-07-09 16:15:16 +00003239 compl_shown_match = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240}
3241
3242 static void
3243ins_compl_clear()
3244{
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003245 compl_cont_status = 0;
3246 compl_started = FALSE;
3247 compl_matches = 0;
3248 vim_free(compl_pattern);
3249 compl_pattern = NULL;
Bram Moolenaara6557602006-02-04 22:43:20 +00003250 vim_free(compl_leader);
3251 compl_leader = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003252 edit_submode_extra = NULL;
Bram Moolenaara94bc432006-03-10 21:42:59 +00003253 vim_free(compl_orig_text);
3254 compl_orig_text = NULL;
Bram Moolenaar779b74b2006-04-10 14:55:34 +00003255 compl_enter_selects = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003256}
3257
3258/*
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00003259 * Return TRUE when Insert completion is active.
3260 */
3261 int
3262ins_compl_active()
3263{
3264 return compl_started;
3265}
3266
3267/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003268 * Delete one character before the cursor and show the subset of the matches
3269 * that match the word that is now before the cursor.
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003270 * Returns the character to be used, NUL if the work is done and another char
3271 * to be got from the user.
Bram Moolenaara6557602006-02-04 22:43:20 +00003272 */
3273 static int
3274ins_compl_bs()
3275{
3276 char_u *line;
3277 char_u *p;
3278
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003279 line = ml_get_curline();
3280 p = line + curwin->w_cursor.col;
3281 mb_ptr_back(line, p);
3282
Bram Moolenaar711d5b52007-10-19 18:40:51 +00003283 /* Stop completion when the whole word was deleted. For Omni completion
3284 * allow the word to be deleted, we won't match everything. */
3285 if ((int)(p - line) - (int)compl_col < 0
3286 || ((int)(p - line) - (int)compl_col == 0
3287 && (ctrl_x_mode & CTRL_X_OMNI) == 0))
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003288 return K_BS;
3289
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003290 /* Deleted more than what was used to find matches or didn't finish
3291 * finding all matches: need to look for matches all over again. */
3292 if (curwin->w_cursor.col <= compl_col + compl_length
3293 || compl_was_interrupted)
3294 ins_compl_restart();
Bram Moolenaara6557602006-02-04 22:43:20 +00003295
Bram Moolenaara6557602006-02-04 22:43:20 +00003296 vim_free(compl_leader);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003297 compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col);
Bram Moolenaara6557602006-02-04 22:43:20 +00003298 if (compl_leader != NULL)
3299 {
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003300 ins_compl_new_leader();
3301 return NUL;
3302 }
3303 return K_BS;
3304}
Bram Moolenaara6557602006-02-04 22:43:20 +00003305
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003306/*
3307 * Called after changing "compl_leader".
3308 * Show the popup menu with a different set of matches.
3309 * May also search for matches again if the previous search was interrupted.
3310 */
3311 static void
3312ins_compl_new_leader()
3313{
3314 ins_compl_del_pum();
3315 ins_compl_delete();
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00003316 ins_bytes(compl_leader + ins_compl_len());
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003317 compl_used_match = FALSE;
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003318
3319 if (compl_started)
3320 ins_compl_set_original_text(compl_leader);
3321 else
3322 {
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00003323#ifdef FEAT_SPELL
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003324 spell_bad_len = 0; /* need to redetect bad word */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00003325#endif
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003326 /*
3327 * Matches were cleared, need to search for them now. First display
3328 * the changed text before the cursor. Set "compl_restarting" to
3329 * avoid that the first match is inserted.
3330 */
3331 update_screen(0);
3332#ifdef FEAT_GUI
3333 if (gui.in_use)
3334 {
3335 /* Show the cursor after the match, not after the redrawn text. */
3336 setcursor();
3337 out_flush();
3338 gui_update_cursor(FALSE, FALSE);
Bram Moolenaara6557602006-02-04 22:43:20 +00003339 }
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003340#endif
3341 compl_restarting = TRUE;
3342 if (ins_complete(Ctrl_N) == FAIL)
3343 compl_cont_status = 0;
3344 compl_restarting = FALSE;
3345 }
Bram Moolenaara6557602006-02-04 22:43:20 +00003346
Bram Moolenaar0440ca32006-05-13 13:24:33 +00003347#if 0 /* disabled, made CTRL-L, BS and typing char jump to original text. */
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003348 if (!compl_used_match)
3349 {
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00003350 /* Go to the original text, since none of the matches is inserted. */
3351 if (compl_first_match->cp_prev != NULL
3352 && (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT))
3353 compl_shown_match = compl_first_match->cp_prev;
3354 else
3355 compl_shown_match = compl_first_match;
3356 compl_curr_match = compl_shown_match;
3357 compl_shows_dir = compl_direction;
Bram Moolenaara6557602006-02-04 22:43:20 +00003358 }
Bram Moolenaar0440ca32006-05-13 13:24:33 +00003359#endif
3360 compl_enter_selects = !compl_used_match;
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003361
3362 /* Show the popup menu with a different set of matches. */
3363 ins_compl_show_pum();
Bram Moolenaar7073cc82006-08-29 16:33:06 +00003364
3365 /* Don't let Enter select the original text when there is no popup menu. */
3366 if (compl_match_array == NULL)
3367 compl_enter_selects = FALSE;
Bram Moolenaara6557602006-02-04 22:43:20 +00003368}
3369
3370/*
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00003371 * Return the length of the completion, from the completion start column to
3372 * the cursor column. Making sure it never goes below zero.
3373 */
3374 static int
3375ins_compl_len()
3376{
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00003377 int off = (int)curwin->w_cursor.col - (int)compl_col;
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00003378
3379 if (off < 0)
3380 return 0;
3381 return off;
3382}
3383
3384/*
Bram Moolenaara6557602006-02-04 22:43:20 +00003385 * Append one character to the match leader. May reduce the number of
3386 * matches.
3387 */
3388 static void
3389ins_compl_addleader(c)
3390 int c;
3391{
3392#ifdef FEAT_MBYTE
3393 int cc;
3394
3395 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
3396 {
3397 char_u buf[MB_MAXBYTES + 1];
3398
3399 (*mb_char2bytes)(c, buf);
3400 buf[cc] = NUL;
3401 ins_char_bytes(buf, cc);
3402 }
3403 else
3404#endif
3405 ins_char(c);
3406
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003407 /* If we didn't complete finding matches we must search again. */
3408 if (compl_was_interrupted)
3409 ins_compl_restart();
3410
Bram Moolenaara6557602006-02-04 22:43:20 +00003411 vim_free(compl_leader);
3412 compl_leader = vim_strnsave(ml_get_curline() + compl_col,
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00003413 (int)(curwin->w_cursor.col - compl_col));
Bram Moolenaara6557602006-02-04 22:43:20 +00003414 if (compl_leader != NULL)
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00003415 ins_compl_new_leader();
3416}
3417
3418/*
3419 * Setup for finding completions again without leaving CTRL-X mode. Used when
3420 * BS or a key was typed while still searching for matches.
3421 */
3422 static void
3423ins_compl_restart()
3424{
3425 ins_compl_free();
3426 compl_started = FALSE;
3427 compl_matches = 0;
3428 compl_cont_status = 0;
3429 compl_cont_mode = 0;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00003430}
3431
3432/*
3433 * Set the first match, the original text.
3434 */
3435 static void
3436ins_compl_set_original_text(str)
3437 char_u *str;
3438{
3439 char_u *p;
3440
3441 /* Replace the original text entry. */
3442 if (compl_first_match->cp_flags & ORIGINAL_TEXT) /* safety check */
3443 {
3444 p = vim_strsave(str);
3445 if (p != NULL)
3446 {
3447 vim_free(compl_first_match->cp_str);
3448 compl_first_match->cp_str = p;
3449 }
Bram Moolenaara6557602006-02-04 22:43:20 +00003450 }
3451}
3452
3453/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003454 * Append one character to the match leader. May reduce the number of
3455 * matches.
3456 */
3457 static void
3458ins_compl_addfrommatch()
3459{
3460 char_u *p;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00003461 int len = (int)curwin->w_cursor.col - (int)compl_col;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003462 int c;
Bram Moolenaar0440ca32006-05-13 13:24:33 +00003463 compl_T *cp;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003464
3465 p = compl_shown_match->cp_str;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003466 if ((int)STRLEN(p) <= len) /* the match is too short */
Bram Moolenaar0440ca32006-05-13 13:24:33 +00003467 {
3468 /* When still at the original match use the first entry that matches
3469 * the leader. */
3470 if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
3471 {
3472 p = NULL;
3473 for (cp = compl_shown_match->cp_next; cp != NULL
3474 && cp != compl_first_match; cp = cp->cp_next)
3475 {
Bram Moolenaar132283f2006-10-03 13:22:23 +00003476 if (compl_leader == NULL
3477 || ins_compl_equal(cp, compl_leader,
Bram Moolenaar0440ca32006-05-13 13:24:33 +00003478 (int)STRLEN(compl_leader)))
3479 {
3480 p = cp->cp_str;
3481 break;
3482 }
3483 }
3484 if (p == NULL || (int)STRLEN(p) <= len)
3485 return;
3486 }
3487 else
3488 return;
3489 }
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003490 p += len;
3491#ifdef FEAT_MBYTE
3492 c = mb_ptr2char(p);
3493#else
3494 c = *p;
3495#endif
3496 ins_compl_addleader(c);
3497}
3498
3499/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003500 * Prepare for Insert mode completion, or stop it.
Bram Moolenaar572cb562005-08-05 21:35:02 +00003501 * Called just after typing a character in Insert mode.
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003502 * Returns TRUE when the character is not to be inserted;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503 */
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003504 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +00003505ins_compl_prep(c)
3506 int c;
3507{
3508 char_u *ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003509 int want_cindent;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003510 int retval = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003511
3512 /* Forget any previous 'special' messages if this is actually
3513 * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
3514 */
3515 if (c != Ctrl_R && vim_is_ctrl_x_key(c))
3516 edit_submode_extra = NULL;
3517
Bram Moolenaar9b25ffb2007-11-06 21:27:31 +00003518 /* Ignore end of Select mode mapping and mouse scroll buttons. */
3519 if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP)
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003520 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003521
Bram Moolenaarc7453f52006-02-10 23:20:28 +00003522 /* Set "compl_get_longest" when finding the first matches. */
3523 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
3524 || (ctrl_x_mode == 0 && !compl_started))
3525 {
3526 compl_get_longest = (vim_strchr(p_cot, 'l') != NULL);
3527 compl_used_match = TRUE;
3528 }
3529
Bram Moolenaar071d4272004-06-13 20:20:40 +00003530 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
3531 {
3532 /*
3533 * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
3534 * it will be yet. Now we decide.
3535 */
3536 switch (c)
3537 {
3538 case Ctrl_E:
3539 case Ctrl_Y:
3540 ctrl_x_mode = CTRL_X_SCROLL;
3541 if (!(State & REPLACE_FLAG))
3542 edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
3543 else
3544 edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
3545 edit_submode_pre = NULL;
3546 showmode();
3547 break;
3548 case Ctrl_L:
3549 ctrl_x_mode = CTRL_X_WHOLE_LINE;
3550 break;
3551 case Ctrl_F:
3552 ctrl_x_mode = CTRL_X_FILES;
3553 break;
3554 case Ctrl_K:
3555 ctrl_x_mode = CTRL_X_DICTIONARY;
3556 break;
3557 case Ctrl_R:
3558 /* Simply allow ^R to happen without affecting ^X mode */
3559 break;
3560 case Ctrl_T:
3561 ctrl_x_mode = CTRL_X_THESAURUS;
3562 break;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003563#ifdef FEAT_COMPL_FUNC
3564 case Ctrl_U:
3565 ctrl_x_mode = CTRL_X_FUNCTION;
3566 break;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003567 case Ctrl_O:
Bram Moolenaarf75a9632005-09-13 21:20:47 +00003568 ctrl_x_mode = CTRL_X_OMNI;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003569 break;
Bram Moolenaare344bea2005-09-01 20:46:49 +00003570#endif
Bram Moolenaar488c6512005-08-11 20:09:58 +00003571 case 's':
3572 case Ctrl_S:
3573 ctrl_x_mode = CTRL_X_SPELL;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00003574#ifdef FEAT_SPELL
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003575 ++emsg_off; /* Avoid getting the E756 error twice. */
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00003576 spell_back_to_badword();
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003577 --emsg_off;
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00003578#endif
Bram Moolenaar488c6512005-08-11 20:09:58 +00003579 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003580 case Ctrl_RSB:
3581 ctrl_x_mode = CTRL_X_TAGS;
3582 break;
3583#ifdef FEAT_FIND_ID
3584 case Ctrl_I:
3585 case K_S_TAB:
3586 ctrl_x_mode = CTRL_X_PATH_PATTERNS;
3587 break;
3588 case Ctrl_D:
3589 ctrl_x_mode = CTRL_X_PATH_DEFINES;
3590 break;
3591#endif
3592 case Ctrl_V:
3593 case Ctrl_Q:
3594 ctrl_x_mode = CTRL_X_CMDLINE;
3595 break;
3596 case Ctrl_P:
3597 case Ctrl_N:
3598 /* ^X^P means LOCAL expansion if nothing interrupted (eg we
3599 * just started ^X mode, or there were enough ^X's to cancel
3600 * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
3601 * do normal expansion when interrupting a different mode (say
3602 * ^X^F^X^P or ^P^X^X^P, see below)
3603 * nothing changes if interrupting mode 0, (eg, the flag
3604 * doesn't change when going to ADDING mode -- Acevedo */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003605 if (!(compl_cont_status & CONT_INTRPT))
3606 compl_cont_status |= CONT_LOCAL;
3607 else if (compl_cont_mode != 0)
3608 compl_cont_status &= ~CONT_LOCAL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003609 /* FALLTHROUGH */
3610 default:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003611 /* If we have typed at least 2 ^X's... for modes != 0, we set
3612 * compl_cont_status = 0 (eg, as if we had just started ^X
3613 * mode).
3614 * For mode 0, we set "compl_cont_mode" to an impossible
3615 * value, in both cases ^X^X can be used to restart the same
3616 * mode (avoiding ADDING mode).
3617 * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
3618 * 'complete' and local ^P expansions respectively.
3619 * In mode 0 an extra ^X is needed since ^X^P goes to ADDING
3620 * mode -- Acevedo */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003621 if (c == Ctrl_X)
3622 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003623 if (compl_cont_mode != 0)
3624 compl_cont_status = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003625 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003626 compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003627 }
3628 ctrl_x_mode = 0;
3629 edit_submode = NULL;
3630 showmode();
3631 break;
3632 }
3633 }
3634 else if (ctrl_x_mode != 0)
3635 {
3636 /* We're already in CTRL-X mode, do we stay in it? */
3637 if (!vim_is_ctrl_x_key(c))
3638 {
3639 if (ctrl_x_mode == CTRL_X_SCROLL)
3640 ctrl_x_mode = 0;
3641 else
3642 ctrl_x_mode = CTRL_X_FINISHED;
3643 edit_submode = NULL;
3644 }
3645 showmode();
3646 }
3647
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003648 if (compl_started || ctrl_x_mode == CTRL_X_FINISHED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003649 {
3650 /* Show error message from attempted keyword completion (probably
3651 * 'Pattern not found') until another key is hit, then go back to
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003652 * showing what mode we are in. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003653 showmode();
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003654 if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R
3655 && !ins_compl_pum_key(c))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003656 || ctrl_x_mode == CTRL_X_FINISHED)
3657 {
3658 /* Get here when we have finished typing a sequence of ^N and
3659 * ^P or other completion characters in CTRL-X mode. Free up
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003660 * memory that was used, and make sure we can redo the insert. */
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003661 if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003662 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003663 char_u *p;
Bram Moolenaard7fd0c42006-08-22 17:55:55 +00003664 int temp = 0;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003665
Bram Moolenaar071d4272004-06-13 20:20:40 +00003666 /*
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003667 * If any of the original typed text has been changed, eg when
3668 * ignorecase is set, we must add back-spaces to the redo
3669 * buffer. We add as few as necessary to delete just the part
3670 * of the original text that has changed.
3671 * When using the longest match, edited the match or used
3672 * CTRL-E then don't use the current match.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003673 */
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003674 if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
3675 ptr = compl_curr_match->cp_str;
3676 else if (compl_leader != NULL)
3677 ptr = compl_leader;
3678 else
3679 ptr = compl_orig_text;
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00003680 if (compl_orig_text != NULL)
3681 {
3682 p = compl_orig_text;
3683 for (temp = 0; p[temp] != NUL && p[temp] == ptr[temp];
3684 ++temp)
3685 ;
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003686#ifdef FEAT_MBYTE
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00003687 if (temp > 0)
3688 temp -= (*mb_head_off)(compl_orig_text, p + temp);
Bram Moolenaarc1e37902006-04-18 21:55:01 +00003689#endif
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00003690 for (p += temp; *p != NUL; mb_ptr_adv(p))
3691 AppendCharToRedobuff(K_BS);
3692 }
3693 if (ptr != NULL)
3694 AppendToRedobuffLit(ptr + temp, -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003695 }
3696
3697#ifdef FEAT_CINDENT
3698 want_cindent = (can_cindent && cindent_on());
3699#endif
3700 /*
3701 * When completing whole lines: fix indent for 'cindent'.
3702 * Otherwise, break line if it's too long.
3703 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003704 if (compl_cont_mode == CTRL_X_WHOLE_LINE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003705 {
3706#ifdef FEAT_CINDENT
3707 /* re-indent the current line */
3708 if (want_cindent)
3709 {
3710 do_c_expr_indent();
3711 want_cindent = FALSE; /* don't do it again */
3712 }
3713#endif
3714 }
3715 else
3716 {
Bram Moolenaar09a16b52007-02-20 02:31:20 +00003717 int prev_col = curwin->w_cursor.col;
3718
Bram Moolenaar071d4272004-06-13 20:20:40 +00003719 /* put the cursor on the last char, for 'tw' formatting */
Bram Moolenaar09a16b52007-02-20 02:31:20 +00003720 if (prev_col > 0)
3721 dec_cursor();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003722 if (stop_arrow() == OK)
3723 insertchar(NUL, 0, -1);
Bram Moolenaar09a16b52007-02-20 02:31:20 +00003724 if (prev_col > 0
3725 && ml_get_curline()[curwin->w_cursor.col] != NUL)
3726 inc_cursor();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003727 }
3728
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00003729 /* If the popup menu is displayed pressing CTRL-Y means accepting
Bram Moolenaar779b74b2006-04-10 14:55:34 +00003730 * the selection without inserting anything. When
3731 * compl_enter_selects is set the Enter key does the same. */
3732 if ((c == Ctrl_Y || (compl_enter_selects
3733 && (c == CAR || c == K_KENTER || c == NL)))
3734 && pum_visible())
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003735 retval = TRUE;
3736
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00003737 /* CTRL-E means completion is Ended, go back to the typed text. */
3738 if (c == Ctrl_E)
3739 {
3740 ins_compl_delete();
3741 if (compl_leader != NULL)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00003742 ins_bytes(compl_leader + ins_compl_len());
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00003743 else if (compl_first_match != NULL)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00003744 ins_bytes(compl_orig_text + ins_compl_len());
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00003745 retval = TRUE;
3746 }
3747
Bram Moolenaare37d50a2008-08-06 17:06:04 +00003748 auto_format(FALSE, TRUE);
3749
Bram Moolenaar071d4272004-06-13 20:20:40 +00003750 ins_compl_free();
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003751 compl_started = FALSE;
3752 compl_matches = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003753 msg_clr_cmdline(); /* necessary for "noshowmode" */
3754 ctrl_x_mode = 0;
Bram Moolenaar779b74b2006-04-10 14:55:34 +00003755 compl_enter_selects = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003756 if (edit_submode != NULL)
3757 {
3758 edit_submode = NULL;
3759 showmode();
3760 }
3761
3762#ifdef FEAT_CINDENT
3763 /*
3764 * Indent now if a key was typed that is in 'cinkeys'.
3765 */
3766 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
3767 do_c_expr_indent();
3768#endif
3769 }
3770 }
3771
3772 /* reset continue_* if we left expansion-mode, if we stay they'll be
3773 * (re)set properly in ins_complete() */
3774 if (!vim_is_ctrl_x_key(c))
3775 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003776 compl_cont_status = 0;
3777 compl_cont_mode = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003778 }
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00003779
3780 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003781}
3782
3783/*
3784 * Loops through the list of windows, loaded-buffers or non-loaded-buffers
3785 * (depending on flag) starting from buf and looking for a non-scanned
3786 * buffer (other than curbuf). curbuf is special, if it is called with
3787 * buf=curbuf then it has to be the first call for a given flag/expansion.
3788 *
3789 * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
3790 */
3791 static buf_T *
3792ins_compl_next_buf(buf, flag)
3793 buf_T *buf;
3794 int flag;
3795{
3796#ifdef FEAT_WINDOWS
3797 static win_T *wp;
3798#endif
3799
3800 if (flag == 'w') /* just windows */
3801 {
3802#ifdef FEAT_WINDOWS
3803 if (buf == curbuf) /* first call for this flag/expansion */
3804 wp = curwin;
Bram Moolenaar1f8a5f02005-07-01 22:41:52 +00003805 while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
Bram Moolenaar071d4272004-06-13 20:20:40 +00003806 && wp->w_buffer->b_scanned)
3807 ;
3808 buf = wp->w_buffer;
3809#else
3810 buf = curbuf;
3811#endif
3812 }
3813 else
3814 /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
3815 * (unlisted buffers)
3816 * When completing whole lines skip unloaded buffers. */
Bram Moolenaar1f8a5f02005-07-01 22:41:52 +00003817 while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf
Bram Moolenaar071d4272004-06-13 20:20:40 +00003818 && ((flag == 'U'
3819 ? buf->b_p_bl
3820 : (!buf->b_p_bl
3821 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00003822 || buf->b_scanned))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003823 ;
3824 return buf;
3825}
3826
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003827#ifdef FEAT_COMPL_FUNC
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003828static void expand_by_function __ARGS((int type, char_u *base));
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003829
3830/*
Bram Moolenaarf75a9632005-09-13 21:20:47 +00003831 * Execute user defined complete function 'completefunc' or 'omnifunc', and
Bram Moolenaare344bea2005-09-01 20:46:49 +00003832 * get matches in "matches".
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003833 */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003834 static void
3835expand_by_function(type, base)
Bram Moolenaarf75a9632005-09-13 21:20:47 +00003836 int type; /* CTRL_X_OMNI or CTRL_X_FUNCTION */
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003837 char_u *base;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003838{
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00003839 list_T *matchlist;
Bram Moolenaare344bea2005-09-01 20:46:49 +00003840 char_u *args[2];
Bram Moolenaare344bea2005-09-01 20:46:49 +00003841 char_u *funcname;
3842 pos_T pos;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003843
Bram Moolenaare344bea2005-09-01 20:46:49 +00003844 funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
3845 if (*funcname == NUL)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003846 return;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003847
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00003848 /* Call 'completefunc' to obtain the list of matches. */
3849 args[0] = (char_u *)"0";
Bram Moolenaare344bea2005-09-01 20:46:49 +00003850 args[1] = base;
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00003851
Bram Moolenaare344bea2005-09-01 20:46:49 +00003852 pos = curwin->w_cursor;
3853 matchlist = call_func_retlist(funcname, 2, args, FALSE);
3854 curwin->w_cursor = pos; /* restore the cursor position */
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00003855 if (matchlist == NULL)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003856 return;
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00003857
Bram Moolenaara94bc432006-03-10 21:42:59 +00003858 ins_compl_add_list(matchlist);
3859 list_unref(matchlist);
3860}
3861#endif /* FEAT_COMPL_FUNC */
3862
Bram Moolenaar39f05632006-03-19 22:15:26 +00003863#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaara94bc432006-03-10 21:42:59 +00003864/*
3865 * Add completions from a list.
Bram Moolenaara94bc432006-03-10 21:42:59 +00003866 */
3867 static void
3868ins_compl_add_list(list)
3869 list_T *list;
3870{
3871 listitem_T *li;
Bram Moolenaara94bc432006-03-10 21:42:59 +00003872 int dir = compl_direction;
3873
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003874 /* Go through the List with matches and add each of them. */
Bram Moolenaara94bc432006-03-10 21:42:59 +00003875 for (li = list->lv_first; li != NULL; li = li->li_next)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003876 {
Bram Moolenaar39f05632006-03-19 22:15:26 +00003877 if (ins_compl_add_tv(&li->li_tv, dir) == OK)
3878 /* if dir was BACKWARD then honor it just once */
3879 dir = FORWARD;
Bram Moolenaar280f1262006-01-30 00:14:18 +00003880 else if (did_emsg)
3881 break;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003882 }
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003883}
Bram Moolenaar39f05632006-03-19 22:15:26 +00003884
3885/*
3886 * Add a match to the list of matches from a typeval_T.
3887 * If the given string is already in the list of completions, then return
3888 * NOTDONE, otherwise add it to the list and return OK. If there is an error,
3889 * maybe because alloc() returns NULL, then FAIL is returned.
3890 */
3891 int
3892ins_compl_add_tv(tv, dir)
3893 typval_T *tv;
3894 int dir;
3895{
3896 char_u *word;
Bram Moolenaar91170f82006-05-05 21:15:17 +00003897 int icase = FALSE;
Bram Moolenaar89d40322006-08-29 15:30:07 +00003898 int adup = FALSE;
Bram Moolenaar39f05632006-03-19 22:15:26 +00003899 char_u *(cptext[CPT_COUNT]);
3900
3901 if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
3902 {
3903 word = get_dict_string(tv->vval.v_dict, (char_u *)"word", FALSE);
3904 cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict,
3905 (char_u *)"abbr", FALSE);
3906 cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict,
3907 (char_u *)"menu", FALSE);
3908 cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict,
3909 (char_u *)"kind", FALSE);
3910 cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict,
3911 (char_u *)"info", FALSE);
3912 if (get_dict_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL)
3913 icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase");
Bram Moolenaar4a85b412006-04-23 22:40:29 +00003914 if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
Bram Moolenaar89d40322006-08-29 15:30:07 +00003915 adup = get_dict_number(tv->vval.v_dict, (char_u *)"dup");
Bram Moolenaar39f05632006-03-19 22:15:26 +00003916 }
3917 else
3918 {
3919 word = get_tv_string_chk(tv);
3920 vim_memset(cptext, 0, sizeof(cptext));
3921 }
3922 if (word == NULL || *word == NUL)
3923 return FAIL;
Bram Moolenaar89d40322006-08-29 15:30:07 +00003924 return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
Bram Moolenaar39f05632006-03-19 22:15:26 +00003925}
Bram Moolenaara94bc432006-03-10 21:42:59 +00003926#endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003927
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003928/*
3929 * Get the next expansion(s), using "compl_pattern".
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003930 * The search starts at position "ini" in curbuf and in the direction
3931 * compl_direction.
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00003932 * When "compl_started" is FALSE start at that position, otherwise continue
3933 * where we stopped searching before.
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003934 * This may return before finding all the matches.
3935 * Return the total number of matches or -1 if still unknown -- Acevedo
Bram Moolenaar071d4272004-06-13 20:20:40 +00003936 */
3937 static int
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003938ins_compl_get_exp(ini)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003939 pos_T *ini;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003940{
3941 static pos_T first_match_pos;
3942 static pos_T last_match_pos;
3943 static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003944 static int found_all = FALSE; /* Found all matches of a
3945 certain type. */
3946 static buf_T *ins_buf = NULL; /* buffer being scanned */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003947
Bram Moolenaar572cb562005-08-05 21:35:02 +00003948 pos_T *pos;
3949 char_u **matches;
3950 int save_p_scs;
3951 int save_p_ws;
3952 int save_p_ic;
3953 int i;
3954 int num_matches;
3955 int len;
3956 int found_new_match;
3957 int type = ctrl_x_mode;
3958 char_u *ptr;
3959 char_u *dict = NULL;
3960 int dict_f = 0;
3961 compl_T *old_match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003962
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003963 if (!compl_started)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003964 {
3965 for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next)
3966 ins_buf->b_scanned = 0;
3967 found_all = FALSE;
3968 ins_buf = curbuf;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003969 e_cpt = (compl_cont_status & CONT_LOCAL)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00003970 ? (char_u *)"." : curbuf->b_p_cpt;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003971 last_match_pos = first_match_pos = *ini;
3972 }
3973
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003974 old_match = compl_curr_match; /* remember the last current match */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00003975 pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003976 /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
3977 for (;;)
3978 {
3979 found_new_match = FAIL;
3980
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003981 /* For ^N/^P pick a new entry from e_cpt if compl_started is off,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003982 * or if found_all says this entry is done. For ^X^L only use the
3983 * entries from 'complete' that look in loaded buffers. */
3984 if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00003985 && (!compl_started || found_all))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003986 {
3987 found_all = FALSE;
3988 while (*e_cpt == ',' || *e_cpt == ' ')
3989 e_cpt++;
3990 if (*e_cpt == '.' && !curbuf->b_scanned)
3991 {
3992 ins_buf = curbuf;
3993 first_match_pos = *ini;
3994 /* So that ^N can match word immediately after cursor */
3995 if (ctrl_x_mode == 0)
3996 dec(&first_match_pos);
3997 last_match_pos = first_match_pos;
3998 type = 0;
3999 }
4000 else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
4001 && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
4002 {
4003 /* Scan a buffer, but not the current one. */
4004 if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */
4005 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004006 compl_started = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004007 first_match_pos.col = last_match_pos.col = 0;
4008 first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
4009 last_match_pos.lnum = 0;
4010 type = 0;
4011 }
4012 else /* unloaded buffer, scan like dictionary */
4013 {
4014 found_all = TRUE;
4015 if (ins_buf->b_fname == NULL)
4016 continue;
4017 type = CTRL_X_DICTIONARY;
4018 dict = ins_buf->b_fname;
4019 dict_f = DICT_EXACT;
4020 }
Bram Moolenaar555b2802005-05-19 21:08:39 +00004021 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
Bram Moolenaar071d4272004-06-13 20:20:40 +00004022 ins_buf->b_fname == NULL
4023 ? buf_spname(ins_buf)
4024 : ins_buf->b_sfname == NULL
4025 ? (char *)ins_buf->b_fname
4026 : (char *)ins_buf->b_sfname);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00004027 (void)msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004028 }
4029 else if (*e_cpt == NUL)
4030 break;
4031 else
4032 {
4033 if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
4034 type = -1;
4035 else if (*e_cpt == 'k' || *e_cpt == 's')
4036 {
4037 if (*e_cpt == 'k')
4038 type = CTRL_X_DICTIONARY;
4039 else
4040 type = CTRL_X_THESAURUS;
4041 if (*++e_cpt != ',' && *e_cpt != NUL)
4042 {
4043 dict = e_cpt;
4044 dict_f = DICT_FIRST;
4045 }
4046 }
4047#ifdef FEAT_FIND_ID
4048 else if (*e_cpt == 'i')
4049 type = CTRL_X_PATH_PATTERNS;
4050 else if (*e_cpt == 'd')
4051 type = CTRL_X_PATH_DEFINES;
4052#endif
4053 else if (*e_cpt == ']' || *e_cpt == 't')
4054 {
4055 type = CTRL_X_TAGS;
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00004056 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags."));
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00004057 (void)msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004058 }
4059 else
4060 type = -1;
4061
4062 /* in any case e_cpt is advanced to the next entry */
4063 (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
4064
4065 found_all = TRUE;
4066 if (type == -1)
4067 continue;
4068 }
4069 }
4070
4071 switch (type)
4072 {
4073 case -1:
4074 break;
4075#ifdef FEAT_FIND_ID
4076 case CTRL_X_PATH_PATTERNS:
4077 case CTRL_X_PATH_DEFINES:
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004078 find_pattern_in_path(compl_pattern, compl_direction,
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004079 (int)STRLEN(compl_pattern), FALSE, FALSE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004080 (type == CTRL_X_PATH_DEFINES
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004081 && !(compl_cont_status & CONT_SOL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004082 ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
4083 (linenr_T)1, (linenr_T)MAXLNUM);
4084 break;
4085#endif
4086
4087 case CTRL_X_DICTIONARY:
4088 case CTRL_X_THESAURUS:
4089 ins_compl_dictionaries(
Bram Moolenaar0b238792006-03-02 22:49:12 +00004090 dict != NULL ? dict
Bram Moolenaar071d4272004-06-13 20:20:40 +00004091 : (type == CTRL_X_THESAURUS
4092 ? (*curbuf->b_p_tsr == NUL
4093 ? p_tsr
4094 : curbuf->b_p_tsr)
4095 : (*curbuf->b_p_dict == NUL
4096 ? p_dict
4097 : curbuf->b_p_dict)),
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004098 compl_pattern,
Bram Moolenaar0b238792006-03-02 22:49:12 +00004099 dict != NULL ? dict_f
4100 : 0, type == CTRL_X_THESAURUS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004101 dict = NULL;
4102 break;
4103
4104 case CTRL_X_TAGS:
4105 /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
4106 save_p_ic = p_ic;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004107 p_ic = ignorecase(compl_pattern);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004108
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01004109 /* Find up to TAG_MANY matches. Avoids that an enormous number
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004110 * of matches is found when compl_pattern is empty */
4111 if (find_tags(compl_pattern, &num_matches, &matches,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004112 TAG_REGEXP | TAG_NAMES | TAG_NOIC |
4113 TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
4114 TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
4115 {
Bram Moolenaare8c3a142006-08-29 14:30:35 +00004116 ins_compl_add_matches(num_matches, matches, p_ic);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004117 }
4118 p_ic = save_p_ic;
4119 break;
4120
4121 case CTRL_X_FILES:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004122 if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004123 EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
4124 {
4125
4126 /* May change home directory back to "~". */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004127 tilde_replace(compl_pattern, num_matches, matches);
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004128 ins_compl_add_matches(num_matches, matches,
4129#ifdef CASE_INSENSITIVE_FILENAME
4130 TRUE
4131#else
4132 FALSE
4133#endif
4134 );
Bram Moolenaar071d4272004-06-13 20:20:40 +00004135 }
4136 break;
4137
4138 case CTRL_X_CMDLINE:
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004139 if (expand_cmdline(&compl_xp, compl_pattern,
4140 (int)STRLEN(compl_pattern),
Bram Moolenaar071d4272004-06-13 20:20:40 +00004141 &num_matches, &matches) == EXPAND_OK)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004142 ins_compl_add_matches(num_matches, matches, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004143 break;
4144
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00004145#ifdef FEAT_COMPL_FUNC
4146 case CTRL_X_FUNCTION:
Bram Moolenaarf75a9632005-09-13 21:20:47 +00004147 case CTRL_X_OMNI:
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004148 expand_by_function(type, compl_pattern);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00004149 break;
4150#endif
4151
Bram Moolenaar488c6512005-08-11 20:09:58 +00004152 case CTRL_X_SPELL:
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00004153#ifdef FEAT_SPELL
Bram Moolenaar488c6512005-08-11 20:09:58 +00004154 num_matches = expand_spelling(first_match_pos.lnum,
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00004155 compl_pattern, &matches);
Bram Moolenaar488c6512005-08-11 20:09:58 +00004156 if (num_matches > 0)
Bram Moolenaare8c3a142006-08-29 14:30:35 +00004157 ins_compl_add_matches(num_matches, matches, p_ic);
Bram Moolenaar488c6512005-08-11 20:09:58 +00004158#endif
4159 break;
4160
Bram Moolenaar071d4272004-06-13 20:20:40 +00004161 default: /* normal ^P/^N and ^X^L */
4162 /*
4163 * If 'infercase' is set, don't use 'smartcase' here
4164 */
4165 save_p_scs = p_scs;
4166 if (ins_buf->b_p_inf)
4167 p_scs = FALSE;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004168
Bram Moolenaar071d4272004-06-13 20:20:40 +00004169 /* buffers other than curbuf are scanned from the beginning or the
4170 * end but never from the middle, thus setting nowrapscan in this
4171 * buffers is a good idea, on the other hand, we always set
4172 * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
4173 save_p_ws = p_ws;
4174 if (ins_buf != curbuf)
4175 p_ws = FALSE;
4176 else if (*e_cpt == '.')
4177 p_ws = TRUE;
4178 for (;;)
4179 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00004180 int flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004181
Bram Moolenaardf40adf2006-10-14 12:32:39 +00004182 ++msg_silent; /* Don't want messages for wrapscan. */
4183
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004184 /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that
4185 * has added a word that was at the beginning of the line */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186 if ( ctrl_x_mode == CTRL_X_WHOLE_LINE
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004187 || (compl_cont_status & CONT_SOL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004188 found_new_match = search_for_exact_line(ins_buf, pos,
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004189 compl_direction, compl_pattern);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004190 else
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004191 found_new_match = searchit(NULL, ins_buf, pos,
4192 compl_direction,
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004193 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
Bram Moolenaar76929292008-01-06 19:07:36 +00004194 RE_LAST, (linenr_T)0, NULL);
Bram Moolenaardf40adf2006-10-14 12:32:39 +00004195 --msg_silent;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004196 if (!compl_started)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 {
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00004198 /* set "compl_started" even on fail */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004199 compl_started = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004200 first_match_pos = *pos;
4201 last_match_pos = *pos;
4202 }
4203 else if (first_match_pos.lnum == last_match_pos.lnum
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004204 && first_match_pos.col == last_match_pos.col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004205 found_new_match = FAIL;
4206 if (found_new_match == FAIL)
4207 {
4208 if (ins_buf == curbuf)
4209 found_all = TRUE;
4210 break;
4211 }
4212
4213 /* when ADDING, the text before the cursor matches, skip it */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004214 if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215 && ini->lnum == pos->lnum
4216 && ini->col == pos->col)
4217 continue;
4218 ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
4219 if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
4220 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004221 if (compl_cont_status & CONT_ADDING)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004222 {
4223 if (pos->lnum >= ins_buf->b_ml.ml_line_count)
4224 continue;
4225 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
4226 if (!p_paste)
4227 ptr = skipwhite(ptr);
4228 }
4229 len = (int)STRLEN(ptr);
4230 }
4231 else
4232 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004233 char_u *tmp_ptr = ptr;
4234
4235 if (compl_cont_status & CONT_ADDING)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004236 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004237 tmp_ptr += compl_length;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004238 /* Skip if already inside a word. */
4239 if (vim_iswordp(tmp_ptr))
4240 continue;
4241 /* Find start of next word. */
4242 tmp_ptr = find_word_start(tmp_ptr);
4243 }
4244 /* Find end of this word. */
4245 tmp_ptr = find_word_end(tmp_ptr);
4246 len = (int)(tmp_ptr - ptr);
4247
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004248 if ((compl_cont_status & CONT_ADDING)
4249 && len == compl_length)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004250 {
4251 if (pos->lnum < ins_buf->b_ml.ml_line_count)
4252 {
4253 /* Try next line, if any. the new word will be
4254 * "join" as if the normal command "J" was used.
4255 * IOSIZE is always greater than
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004256 * compl_length, so the next STRNCPY always
Bram Moolenaar071d4272004-06-13 20:20:40 +00004257 * works -- Acevedo */
4258 STRNCPY(IObuff, ptr, len);
4259 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
4260 tmp_ptr = ptr = skipwhite(ptr);
4261 /* Find start of next word. */
4262 tmp_ptr = find_word_start(tmp_ptr);
4263 /* Find end of next word. */
4264 tmp_ptr = find_word_end(tmp_ptr);
4265 if (tmp_ptr > ptr)
4266 {
Bram Moolenaarce0842a2005-07-18 21:58:11 +00004267 if (*ptr != ')' && IObuff[len - 1] != TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004268 {
Bram Moolenaarce0842a2005-07-18 21:58:11 +00004269 if (IObuff[len - 1] != ' ')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004270 IObuff[len++] = ' ';
4271 /* IObuf =~ "\k.* ", thus len >= 2 */
4272 if (p_js
Bram Moolenaarce0842a2005-07-18 21:58:11 +00004273 && (IObuff[len - 2] == '.'
Bram Moolenaar071d4272004-06-13 20:20:40 +00004274 || (vim_strchr(p_cpo, CPO_JOINSP)
4275 == NULL
Bram Moolenaarce0842a2005-07-18 21:58:11 +00004276 && (IObuff[len - 2] == '?'
4277 || IObuff[len - 2] == '!'))))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004278 IObuff[len++] = ' ';
4279 }
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01004280 /* copy as much as possible of the new word */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004281 if (tmp_ptr - ptr >= IOSIZE - len)
4282 tmp_ptr = ptr + IOSIZE - len - 1;
4283 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
4284 len += (int)(tmp_ptr - ptr);
Bram Moolenaar572cb562005-08-05 21:35:02 +00004285 flags |= CONT_S_IPOS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004286 }
4287 IObuff[len] = NUL;
4288 ptr = IObuff;
4289 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004290 if (len == compl_length)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 continue;
4292 }
4293 }
Bram Moolenaare8c3a142006-08-29 14:30:35 +00004294 if (ins_compl_add_infercase(ptr, len, p_ic,
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004295 ins_buf == curbuf ? NULL : ins_buf->b_sfname,
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004296 0, flags) != NOTDONE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004297 {
4298 found_new_match = OK;
4299 break;
4300 }
4301 }
4302 p_scs = save_p_scs;
4303 p_ws = save_p_ws;
4304 }
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004305
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004306 /* check if compl_curr_match has changed, (e.g. other type of
Bram Moolenaar5b3e4602009-02-04 10:20:58 +00004307 * expansion added something) */
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004308 if (type != 0 && compl_curr_match != old_match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309 found_new_match = OK;
4310
4311 /* break the loop for specialized modes (use 'complete' just for the
4312 * generic ctrl_x_mode == 0) or when we've found a new match */
4313 if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004314 || found_new_match != FAIL)
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004315 {
4316 if (got_int)
4317 break;
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004318 /* Fill the popup menu as soon as possible. */
Bram Moolenaar5948a572006-10-03 13:49:29 +00004319 if (type != -1)
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004320 ins_compl_check_keys(0);
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004321
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004322 if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
4323 || compl_interrupted)
4324 break;
4325 compl_started = TRUE;
4326 }
4327 else
4328 {
4329 /* Mark a buffer scanned when it has been scanned completely */
4330 if (type == 0 || type == CTRL_X_PATH_PATTERNS)
4331 ins_buf->b_scanned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004333 compl_started = FALSE;
4334 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004335 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004336 compl_started = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004337
4338 if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
4339 && *e_cpt == NUL) /* Got to end of 'complete' */
4340 found_new_match = FAIL;
4341
4342 i = -1; /* total of matches, unknown */
4343 if (found_new_match == FAIL
4344 || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
4345 i = ins_compl_make_cyclic();
4346
4347 /* If several matches were added (FORWARD) or the search failed and has
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004348 * just been made cyclic then we have to move compl_curr_match to the next
4349 * or previous entry (if any) -- Acevedo */
Bram Moolenaara94bc432006-03-10 21:42:59 +00004350 compl_curr_match = compl_direction == FORWARD ? old_match->cp_next
4351 : old_match->cp_prev;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004352 if (compl_curr_match == NULL)
4353 compl_curr_match = old_match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004354 return i;
4355}
4356
4357/* Delete the old text being completed. */
4358 static void
4359ins_compl_delete()
4360{
4361 int i;
4362
4363 /*
4364 * In insert mode: Delete the typed part.
4365 * In replace mode: Put the old characters back, if any.
4366 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004367 i = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004368 backspace_until_column(i);
4369 changed_cline_bef_curs();
4370}
4371
4372/* Insert the new text being completed. */
4373 static void
4374ins_compl_insert()
4375{
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00004376 ins_bytes(compl_shown_match->cp_str + ins_compl_len());
Bram Moolenaardf1bdc92006-02-23 21:32:16 +00004377 if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
4378 compl_used_match = FALSE;
4379 else
4380 compl_used_match = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381}
4382
4383/*
4384 * Fill in the next completion in the current direction.
Bram Moolenaar572cb562005-08-05 21:35:02 +00004385 * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to
4386 * get more completions. If it is FALSE, then we just do nothing when there
4387 * are no more completions in a given direction. The latter case is used when
4388 * we are still in the middle of finding completions, to allow browsing
4389 * through the ones found so far.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004390 * Return the total number of matches, or -1 if still unknown -- webb.
4391 *
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004392 * compl_curr_match is currently being used by ins_compl_get_exp(), so we use
4393 * compl_shown_match here.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004394 *
4395 * Note that this function may be called recursively once only. First with
Bram Moolenaar572cb562005-08-05 21:35:02 +00004396 * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn
4397 * calls this function with "allow_get_expansion" FALSE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004398 */
4399 static int
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004400ins_compl_next(allow_get_expansion, count, insert_match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004401 int allow_get_expansion;
Bram Moolenaare3226be2005-12-18 22:10:00 +00004402 int count; /* repeat completion this many times; should
4403 be at least 1 */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004404 int insert_match; /* Insert the newly selected match */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004405{
4406 int num_matches = -1;
4407 int i;
Bram Moolenaare3226be2005-12-18 22:10:00 +00004408 int todo = count;
Bram Moolenaara6557602006-02-04 22:43:20 +00004409 compl_T *found_compl = NULL;
4410 int found_end = FALSE;
Bram Moolenaarc1e37902006-04-18 21:55:01 +00004411 int advance;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004412
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004413 if (compl_leader != NULL
4414 && (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004415 {
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004416 /* Set "compl_shown_match" to the actually shown match, it may differ
4417 * when "compl_leader" is used to omit some of the matches. */
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004418 while (!ins_compl_equal(compl_shown_match,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004419 compl_leader, (int)STRLEN(compl_leader))
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004420 && compl_shown_match->cp_next != NULL
4421 && compl_shown_match->cp_next != compl_first_match)
4422 compl_shown_match = compl_shown_match->cp_next;
Bram Moolenaar0440ca32006-05-13 13:24:33 +00004423
4424 /* If we didn't find it searching forward, and compl_shows_dir is
4425 * backward, find the last match. */
4426 if (compl_shows_dir == BACKWARD
4427 && !ins_compl_equal(compl_shown_match,
4428 compl_leader, (int)STRLEN(compl_leader))
4429 && (compl_shown_match->cp_next == NULL
4430 || compl_shown_match->cp_next == compl_first_match))
4431 {
4432 while (!ins_compl_equal(compl_shown_match,
4433 compl_leader, (int)STRLEN(compl_leader))
4434 && compl_shown_match->cp_prev != NULL
4435 && compl_shown_match->cp_prev != compl_first_match)
4436 compl_shown_match = compl_shown_match->cp_prev;
4437 }
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004438 }
4439
4440 if (allow_get_expansion && insert_match
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00004441 && (!(compl_get_longest || compl_restarting) || compl_used_match))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 /* Delete old text to be replaced */
4443 ins_compl_delete();
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004444
Bram Moolenaarc1e37902006-04-18 21:55:01 +00004445 /* When finding the longest common text we stick at the original text,
4446 * don't let CTRL-N or CTRL-P move to the first match. */
4447 advance = count != 1 || !allow_get_expansion || !compl_get_longest;
4448
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00004449 /* When restarting the search don't insert the first match either. */
4450 if (compl_restarting)
4451 {
4452 advance = FALSE;
4453 compl_restarting = FALSE;
4454 }
4455
Bram Moolenaare3226be2005-12-18 22:10:00 +00004456 /* Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
4457 * around. */
4458 while (--todo >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004459 {
Bram Moolenaare3226be2005-12-18 22:10:00 +00004460 if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004461 {
Bram Moolenaare3226be2005-12-18 22:10:00 +00004462 compl_shown_match = compl_shown_match->cp_next;
Bram Moolenaara6557602006-02-04 22:43:20 +00004463 found_end = (compl_first_match != NULL
4464 && (compl_shown_match->cp_next == compl_first_match
4465 || compl_shown_match == compl_first_match));
Bram Moolenaare3226be2005-12-18 22:10:00 +00004466 }
4467 else if (compl_shows_dir == BACKWARD
4468 && compl_shown_match->cp_prev != NULL)
4469 {
Bram Moolenaara6557602006-02-04 22:43:20 +00004470 found_end = (compl_shown_match == compl_first_match);
Bram Moolenaare3226be2005-12-18 22:10:00 +00004471 compl_shown_match = compl_shown_match->cp_prev;
Bram Moolenaara6557602006-02-04 22:43:20 +00004472 found_end |= (compl_shown_match == compl_first_match);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473 }
4474 else
Bram Moolenaare3226be2005-12-18 22:10:00 +00004475 {
Bram Moolenaara260a972006-06-23 19:36:29 +00004476 if (!allow_get_expansion)
4477 {
4478 if (advance)
4479 {
4480 if (compl_shows_dir == BACKWARD)
4481 compl_pending -= todo + 1;
4482 else
4483 compl_pending += todo + 1;
4484 }
4485 return -1;
4486 }
4487
Bram Moolenaarc1e37902006-04-18 21:55:01 +00004488 if (advance)
4489 {
4490 if (compl_shows_dir == BACKWARD)
4491 --compl_pending;
4492 else
4493 ++compl_pending;
4494 }
Bram Moolenaara6557602006-02-04 22:43:20 +00004495
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00004496 /* Find matches. */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00004497 num_matches = ins_compl_get_exp(&compl_startpos);
Bram Moolenaara260a972006-06-23 19:36:29 +00004498
4499 /* handle any pending completions */
4500 while (compl_pending != 0 && compl_direction == compl_shows_dir
Bram Moolenaarc1e37902006-04-18 21:55:01 +00004501 && advance)
Bram Moolenaara260a972006-06-23 19:36:29 +00004502 {
4503 if (compl_pending > 0 && compl_shown_match->cp_next != NULL)
4504 {
4505 compl_shown_match = compl_shown_match->cp_next;
4506 --compl_pending;
4507 }
4508 if (compl_pending < 0 && compl_shown_match->cp_prev != NULL)
4509 {
4510 compl_shown_match = compl_shown_match->cp_prev;
4511 ++compl_pending;
4512 }
4513 else
4514 break;
4515 }
Bram Moolenaara6557602006-02-04 22:43:20 +00004516 found_end = FALSE;
4517 }
4518 if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0
4519 && compl_leader != NULL
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004520 && !ins_compl_equal(compl_shown_match,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004521 compl_leader, (int)STRLEN(compl_leader)))
Bram Moolenaara6557602006-02-04 22:43:20 +00004522 ++todo;
4523 else
4524 /* Remember a matching item. */
4525 found_compl = compl_shown_match;
4526
4527 /* Stop at the end of the list when we found a usable match. */
4528 if (found_end)
4529 {
4530 if (found_compl != NULL)
4531 {
4532 compl_shown_match = found_compl;
4533 break;
4534 }
4535 todo = 1; /* use first usable match after wrapping around */
Bram Moolenaare3226be2005-12-18 22:10:00 +00004536 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004537 }
4538
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004539 /* Insert the text of the new completion, or the compl_leader. */
4540 if (insert_match)
4541 {
4542 if (!compl_get_longest || compl_used_match)
4543 ins_compl_insert();
4544 else
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00004545 ins_bytes(compl_leader + ins_compl_len());
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004546 }
4547 else
4548 compl_used_match = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549
4550 if (!allow_get_expansion)
4551 {
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004552 /* may undisplay the popup menu first */
4553 ins_compl_upd_pum();
4554
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004555 /* redraw to show the user what was inserted */
4556 update_screen(0);
4557
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004558 /* display the updated popup menu */
4559 ins_compl_show_pum();
Bram Moolenaar14716812006-05-04 21:54:08 +00004560#ifdef FEAT_GUI
4561 if (gui.in_use)
4562 {
4563 /* Show the cursor after the match, not after the redrawn text. */
4564 setcursor();
4565 out_flush();
4566 gui_update_cursor(FALSE, FALSE);
4567 }
4568#endif
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004569
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570 /* Delete old text to be replaced, since we're still searching and
4571 * don't want to match ourselves! */
4572 ins_compl_delete();
4573 }
4574
Bram Moolenaar779b74b2006-04-10 14:55:34 +00004575 /* Enter will select a match when the match wasn't inserted and the popup
Bram Moolenaar34e0bfa2007-05-10 18:44:18 +00004576 * menu is visible. */
Bram Moolenaar779b74b2006-04-10 14:55:34 +00004577 compl_enter_selects = !insert_match && compl_match_array != NULL;
4578
Bram Moolenaar071d4272004-06-13 20:20:40 +00004579 /*
4580 * Show the file name for the match (if any)
4581 * Truncate the file name to avoid a wait for return.
4582 */
Bram Moolenaar572cb562005-08-05 21:35:02 +00004583 if (compl_shown_match->cp_fname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004584 {
4585 STRCPY(IObuff, "match in file ");
Bram Moolenaar572cb562005-08-05 21:35:02 +00004586 i = (vim_strsize(compl_shown_match->cp_fname) + 16) - sc_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004587 if (i <= 0)
4588 i = 0;
4589 else
4590 STRCAT(IObuff, "<");
Bram Moolenaar572cb562005-08-05 21:35:02 +00004591 STRCAT(IObuff, compl_shown_match->cp_fname + i);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004592 msg(IObuff);
4593 redraw_cmdline = FALSE; /* don't overwrite! */
4594 }
4595
4596 return num_matches;
4597}
4598
4599/*
4600 * Call this while finding completions, to check whether the user has hit a key
4601 * that should change the currently displayed completion, or exit completion
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004602 * mode. Also, when compl_pending is not zero, show a completion as soon as
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603 * possible. -- webb
Bram Moolenaar572cb562005-08-05 21:35:02 +00004604 * "frequency" specifies out of how many calls we actually check.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004605 */
4606 void
Bram Moolenaar572cb562005-08-05 21:35:02 +00004607ins_compl_check_keys(frequency)
4608 int frequency;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609{
4610 static int count = 0;
4611
4612 int c;
4613
4614 /* Don't check when reading keys from a script. That would break the test
4615 * scripts */
4616 if (using_script())
4617 return;
4618
4619 /* Only do this at regular intervals */
Bram Moolenaar572cb562005-08-05 21:35:02 +00004620 if (++count < frequency)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004621 return;
4622 count = 0;
4623
Bram Moolenaara260a972006-06-23 19:36:29 +00004624 /* Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key()
4625 * can't do its work correctly. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004626 c = vpeekc_any();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004627 if (c != NUL)
4628 {
4629 if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
4630 {
4631 c = safe_vgetc(); /* Eat the character */
Bram Moolenaare3226be2005-12-18 22:10:00 +00004632 compl_shows_dir = ins_compl_key2dir(c);
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004633 (void)ins_compl_next(FALSE, ins_compl_key2count(c),
4634 c != K_UP && c != K_DOWN);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004635 }
Bram Moolenaara260a972006-06-23 19:36:29 +00004636 else
4637 {
4638 /* Need to get the character to have KeyTyped set. We'll put it
Bram Moolenaard4e20a72008-01-22 16:50:03 +00004639 * back with vungetc() below. But skip K_IGNORE. */
Bram Moolenaara260a972006-06-23 19:36:29 +00004640 c = safe_vgetc();
Bram Moolenaard4e20a72008-01-22 16:50:03 +00004641 if (c != K_IGNORE)
4642 {
4643 /* Don't interrupt completion when the character wasn't typed,
4644 * e.g., when doing @q to replay keys. */
4645 if (c != Ctrl_R && KeyTyped)
4646 compl_interrupted = TRUE;
Bram Moolenaara260a972006-06-23 19:36:29 +00004647
Bram Moolenaard4e20a72008-01-22 16:50:03 +00004648 vungetc(c);
4649 }
Bram Moolenaara260a972006-06-23 19:36:29 +00004650 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004651 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004652 if (compl_pending != 0 && !got_int)
Bram Moolenaara260a972006-06-23 19:36:29 +00004653 {
4654 int todo = compl_pending > 0 ? compl_pending : -compl_pending;
4655
4656 compl_pending = 0;
4657 (void)ins_compl_next(FALSE, todo, TRUE);
4658 }
Bram Moolenaare3226be2005-12-18 22:10:00 +00004659}
4660
4661/*
4662 * Decide the direction of Insert mode complete from the key typed.
4663 * Returns BACKWARD or FORWARD.
4664 */
4665 static int
4666ins_compl_key2dir(c)
4667 int c;
4668{
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004669 if (c == Ctrl_P || c == Ctrl_L
4670 || (pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP
4671 || c == K_S_UP || c == K_UP)))
Bram Moolenaare3226be2005-12-18 22:10:00 +00004672 return BACKWARD;
4673 return FORWARD;
4674}
4675
4676/*
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004677 * Return TRUE for keys that are used for completion only when the popup menu
4678 * is visible.
4679 */
4680 static int
4681ins_compl_pum_key(c)
4682 int c;
4683{
4684 return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004685 || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN
4686 || c == K_UP || c == K_DOWN);
Bram Moolenaard12f5c12006-01-25 22:10:52 +00004687}
4688
4689/*
Bram Moolenaare3226be2005-12-18 22:10:00 +00004690 * Decide the number of completions to move forward.
4691 * Returns 1 for most keys, height of the popup menu for page-up/down keys.
4692 */
4693 static int
4694ins_compl_key2count(c)
4695 int c;
4696{
4697 int h;
4698
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004699 if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN)
Bram Moolenaare3226be2005-12-18 22:10:00 +00004700 {
4701 h = pum_get_height();
4702 if (h > 3)
4703 h -= 2; /* keep some context */
4704 return h;
4705 }
4706 return 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004707}
4708
4709/*
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004710 * Return TRUE if completion with "c" should insert the match, FALSE if only
4711 * to change the currently selected completion.
4712 */
4713 static int
4714ins_compl_use_match(c)
4715 int c;
4716{
4717 switch (c)
4718 {
4719 case K_UP:
4720 case K_DOWN:
4721 case K_PAGEDOWN:
4722 case K_KPAGEDOWN:
4723 case K_S_DOWN:
4724 case K_PAGEUP:
4725 case K_KPAGEUP:
4726 case K_S_UP:
4727 return FALSE;
4728 }
4729 return TRUE;
4730}
4731
4732/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004733 * Do Insert mode completion.
4734 * Called when character "c" was typed, which has a meaning for completion.
4735 * Returns OK if completion was done, FAIL if something failed (out of mem).
4736 */
4737 static int
4738ins_complete(c)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004739 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004740{
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004741 char_u *line;
4742 int startcol = 0; /* column where searched text starts */
4743 colnr_T curs_col; /* cursor column */
4744 int n;
Bram Moolenaarbe678f82010-03-10 14:15:54 +01004745 int save_w_wrow;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004746
Bram Moolenaare3226be2005-12-18 22:10:00 +00004747 compl_direction = ins_compl_key2dir(c);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004748 if (!compl_started)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749 {
4750 /* First time we hit ^N or ^P (in a row, I mean) */
4751
Bram Moolenaar071d4272004-06-13 20:20:40 +00004752 did_ai = FALSE;
4753#ifdef FEAT_SMARTINDENT
4754 did_si = FALSE;
4755 can_si = FALSE;
4756 can_si_back = FALSE;
4757#endif
4758 if (stop_arrow() == FAIL)
4759 return FAIL;
4760
4761 line = ml_get(curwin->w_cursor.lnum);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004762 curs_col = curwin->w_cursor.col;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00004763 compl_pending = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764
Bram Moolenaar711d5b52007-10-19 18:40:51 +00004765 /* If this same ctrl_x_mode has been interrupted use the text from
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004766 * "compl_startpos" to the cursor as a pattern to add a new word
4767 * instead of expand the one before the cursor, in word-wise if
Bram Moolenaar711d5b52007-10-19 18:40:51 +00004768 * "compl_startpos" is not in the same line as the cursor then fix it
4769 * (the line has been split because it was longer than 'tw'). if SOL
4770 * is set then skip the previous pattern, a word at the beginning of
4771 * the line has been inserted, we'll look for that -- Acevedo. */
Bram Moolenaarc7453f52006-02-10 23:20:28 +00004772 if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
4773 && compl_cont_mode == ctrl_x_mode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004774 {
4775 /*
4776 * it is a continued search
4777 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004778 compl_cont_status &= ~CONT_INTRPT; /* remove INTRPT */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004779 if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
4780 || ctrl_x_mode == CTRL_X_PATH_DEFINES)
4781 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004782 if (compl_startpos.lnum != curwin->w_cursor.lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004783 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004784 /* line (probably) wrapped, set compl_startpos to the
4785 * first non_blank in the line, if it is not a wordchar
4786 * include it to get a better pattern, but then we don't
4787 * want the "\\<" prefix, check it bellow */
4788 compl_col = (colnr_T)(skipwhite(line) - line);
4789 compl_startpos.col = compl_col;
4790 compl_startpos.lnum = curwin->w_cursor.lnum;
4791 compl_cont_status &= ~CONT_SOL; /* clear SOL if present */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 }
4793 else
4794 {
4795 /* S_IPOS was set when we inserted a word that was at the
4796 * beginning of the line, which means that we'll go to SOL
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004797 * mode but first we need to redefine compl_startpos */
4798 if (compl_cont_status & CONT_S_IPOS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004799 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004800 compl_cont_status |= CONT_SOL;
4801 compl_startpos.col = (colnr_T)(skipwhite(
4802 line + compl_length
4803 + compl_startpos.col) - line);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004804 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004805 compl_col = compl_startpos.col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004806 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004807 compl_length = curwin->w_cursor.col - (int)compl_col;
Bram Moolenaare344bea2005-09-01 20:46:49 +00004808 /* IObuff is used to add a "word from the next line" would we
Bram Moolenaar5b3e4602009-02-04 10:20:58 +00004809 * have enough space? just being paranoid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004810#define MIN_SPACE 75
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004811 if (compl_length > (IOSIZE - MIN_SPACE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004812 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004813 compl_cont_status &= ~CONT_SOL;
4814 compl_length = (IOSIZE - MIN_SPACE);
4815 compl_col = curwin->w_cursor.col - compl_length;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004817 compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
4818 if (compl_length < 1)
4819 compl_cont_status &= CONT_LOCAL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820 }
4821 else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004822 compl_cont_status = CONT_ADDING | CONT_N_ADDS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004824 compl_cont_status = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004825 }
4826 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004827 compl_cont_status &= CONT_LOCAL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004828
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004829 if (!(compl_cont_status & CONT_ADDING)) /* normal expansion */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004830 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004831 compl_cont_mode = ctrl_x_mode;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004832 if (ctrl_x_mode != 0) /* Remove LOCAL if ctrl_x_mode != 0 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004833 compl_cont_status = 0;
4834 compl_cont_status |= CONT_N_ADDS;
4835 compl_startpos = curwin->w_cursor;
4836 startcol = (int)curs_col;
4837 compl_col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004838 }
4839
4840 /* Work out completion pattern and original text -- webb */
4841 if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
4842 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004843 if ((compl_cont_status & CONT_SOL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004844 || ctrl_x_mode == CTRL_X_PATH_DEFINES)
4845 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004846 if (!(compl_cont_status & CONT_ADDING))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004847 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004848 while (--startcol >= 0 && vim_isIDc(line[startcol]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004849 ;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004850 compl_col += ++startcol;
4851 compl_length = curs_col - startcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 }
4853 if (p_ic)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004854 compl_pattern = str_foldcase(line + compl_col,
4855 compl_length, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004857 compl_pattern = vim_strnsave(line + compl_col,
4858 compl_length);
4859 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860 return FAIL;
4861 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004862 else if (compl_cont_status & CONT_ADDING)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004863 {
4864 char_u *prefix = (char_u *)"\\<";
4865
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00004866 /* we need up to 2 extra chars for the prefix */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004867 compl_pattern = alloc(quote_meta(NULL, line + compl_col,
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00004868 compl_length) + 2);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004869 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004870 return FAIL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004871 if (!vim_iswordp(line + compl_col)
4872 || (compl_col > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00004873 && (
4874#ifdef FEAT_MBYTE
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004875 vim_iswordp(mb_prevptr(line, line + compl_col))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876#else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004877 vim_iswordc(line[compl_col - 1])
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878#endif
4879 )))
4880 prefix = (char_u *)"";
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004881 STRCPY((char *)compl_pattern, prefix);
4882 (void)quote_meta(compl_pattern + STRLEN(prefix),
4883 line + compl_col, compl_length);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004885 else if (--startcol < 0 ||
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886#ifdef FEAT_MBYTE
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004887 !vim_iswordp(mb_prevptr(line, line + startcol + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004888#else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004889 !vim_iswordc(line[startcol])
Bram Moolenaar071d4272004-06-13 20:20:40 +00004890#endif
4891 )
4892 {
4893 /* Match any word of at least two chars */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004894 compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
4895 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004896 return FAIL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004897 compl_col += curs_col;
4898 compl_length = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004899 }
4900 else
4901 {
4902#ifdef FEAT_MBYTE
4903 /* Search the point of change class of multibyte character
4904 * or not a word single byte character backward. */
4905 if (has_mbyte)
4906 {
4907 int base_class;
4908 int head_off;
4909
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004910 startcol -= (*mb_head_off)(line, line + startcol);
4911 base_class = mb_get_class(line + startcol);
4912 while (--startcol >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004913 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004914 head_off = (*mb_head_off)(line, line + startcol);
4915 if (base_class != mb_get_class(line + startcol
4916 - head_off))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004917 break;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004918 startcol -= head_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004919 }
4920 }
4921 else
4922#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004923 while (--startcol >= 0 && vim_iswordc(line[startcol]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004924 ;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004925 compl_col += ++startcol;
4926 compl_length = (int)curs_col - startcol;
4927 if (compl_length == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004928 {
4929 /* Only match word with at least two chars -- webb
4930 * there's no need to call quote_meta,
4931 * alloc(7) is enough -- Acevedo
4932 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004933 compl_pattern = alloc(7);
4934 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004935 return FAIL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004936 STRCPY((char *)compl_pattern, "\\<");
4937 (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
4938 STRCAT((char *)compl_pattern, "\\k");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004939 }
4940 else
4941 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004942 compl_pattern = alloc(quote_meta(NULL, line + compl_col,
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00004943 compl_length) + 2);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004944 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945 return FAIL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004946 STRCPY((char *)compl_pattern, "\\<");
4947 (void)quote_meta(compl_pattern + 2, line + compl_col,
4948 compl_length);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 }
4950 }
4951 }
4952 else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
4953 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004954 compl_col = (colnr_T)(skipwhite(line) - line);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004955 compl_length = (int)curs_col - (int)compl_col;
4956 if (compl_length < 0) /* cursor in indent: empty pattern */
4957 compl_length = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004958 if (p_ic)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004959 compl_pattern = str_foldcase(line + compl_col, compl_length,
4960 NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004961 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004962 compl_pattern = vim_strnsave(line + compl_col, compl_length);
4963 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004964 return FAIL;
4965 }
4966 else if (ctrl_x_mode == CTRL_X_FILES)
4967 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004968 while (--startcol >= 0 && vim_isfilec(line[startcol]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004969 ;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004970 compl_col += ++startcol;
4971 compl_length = (int)curs_col - startcol;
4972 compl_pattern = addstar(line + compl_col, compl_length,
4973 EXPAND_FILES);
4974 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004975 return FAIL;
4976 }
4977 else if (ctrl_x_mode == CTRL_X_CMDLINE)
4978 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004979 compl_pattern = vim_strnsave(line, curs_col);
4980 if (compl_pattern == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981 return FAIL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00004982 set_cmd_context(&compl_xp, compl_pattern,
4983 (int)STRLEN(compl_pattern), curs_col);
4984 if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
4985 || compl_xp.xp_context == EXPAND_NOTHING)
Bram Moolenaarf83c5c02006-08-16 19:24:22 +00004986 /* No completion possible, use an empty pattern to get a
4987 * "pattern not found" message. */
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00004988 compl_col = curs_col;
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00004989 else
Bram Moolenaarf83c5c02006-08-16 19:24:22 +00004990 compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
4991 compl_length = curs_col - compl_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004992 }
Bram Moolenaarf75a9632005-09-13 21:20:47 +00004993 else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00004994 {
Bram Moolenaare344bea2005-09-01 20:46:49 +00004995#ifdef FEAT_COMPL_FUNC
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00004996 /*
Bram Moolenaare344bea2005-09-01 20:46:49 +00004997 * Call user defined function 'completefunc' with "a:findstart"
4998 * set to 1 to obtain the length of text to use for completion.
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00004999 */
Bram Moolenaare344bea2005-09-01 20:46:49 +00005000 char_u *args[2];
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005001 int col;
Bram Moolenaare344bea2005-09-01 20:46:49 +00005002 char_u *funcname;
5003 pos_T pos;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005004
Bram Moolenaarf75a9632005-09-13 21:20:47 +00005005 /* Call 'completefunc' or 'omnifunc' and get pattern length as a
Bram Moolenaare344bea2005-09-01 20:46:49 +00005006 * string */
5007 funcname = ctrl_x_mode == CTRL_X_FUNCTION
5008 ? curbuf->b_p_cfu : curbuf->b_p_ofu;
5009 if (*funcname == NUL)
Bram Moolenaarf75a9632005-09-13 21:20:47 +00005010 {
5011 EMSG2(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION
5012 ? "completefunc" : "omnifunc");
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005013 return FAIL;
Bram Moolenaarf75a9632005-09-13 21:20:47 +00005014 }
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005015
5016 args[0] = (char_u *)"1";
Bram Moolenaare344bea2005-09-01 20:46:49 +00005017 args[1] = NULL;
5018 pos = curwin->w_cursor;
5019 col = call_func_retnr(funcname, 2, args, FALSE);
5020 curwin->w_cursor = pos; /* restore the cursor position */
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005021
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005022 if (col < 0)
Bram Moolenaarf75a9632005-09-13 21:20:47 +00005023 col = curs_col;
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005024 compl_col = col;
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00005025 if (compl_col > curs_col)
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005026 compl_col = curs_col;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005027
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005028 /* Setup variables for completion. Need to obtain "line" again,
5029 * it may have become invalid. */
5030 line = ml_get(curwin->w_cursor.lnum);
Bram Moolenaar5a8684e2005-07-30 22:43:24 +00005031 compl_length = curs_col - compl_col;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005032 compl_pattern = vim_strnsave(line + compl_col, compl_length);
5033 if (compl_pattern == NULL)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005034#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005035 return FAIL;
5036 }
Bram Moolenaar488c6512005-08-11 20:09:58 +00005037 else if (ctrl_x_mode == CTRL_X_SPELL)
5038 {
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005039#ifdef FEAT_SPELL
Bram Moolenaar6e7c7f32005-08-24 22:16:11 +00005040 if (spell_bad_len > 0)
5041 compl_col = curs_col - spell_bad_len;
5042 else
5043 compl_col = spell_word_start(startcol);
5044 if (compl_col >= (colnr_T)startcol)
Bram Moolenaarbe46a1e2006-06-22 15:13:21 +00005045 {
5046 compl_length = 0;
5047 compl_col = curs_col;
5048 }
5049 else
5050 {
5051 spell_expand_check_cap(compl_col);
5052 compl_length = (int)curs_col - compl_col;
5053 }
Bram Moolenaare2f98b92006-03-29 21:18:24 +00005054 /* Need to obtain "line" again, it may have become invalid. */
5055 line = ml_get(curwin->w_cursor.lnum);
Bram Moolenaar488c6512005-08-11 20:09:58 +00005056 compl_pattern = vim_strnsave(line + compl_col, compl_length);
5057 if (compl_pattern == NULL)
5058#endif
5059 return FAIL;
5060 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005061 else
5062 {
5063 EMSG2(_(e_intern2), "ins_complete()");
5064 return FAIL;
5065 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005066
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005067 if (compl_cont_status & CONT_ADDING)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005068 {
5069 edit_submode_pre = (char_u *)_(" Adding");
5070 if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
5071 {
5072 /* Insert a new line, keep indentation but ignore 'comments' */
5073#ifdef FEAT_COMMENTS
5074 char_u *old = curbuf->b_p_com;
5075
5076 curbuf->b_p_com = (char_u *)"";
5077#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005078 compl_startpos.lnum = curwin->w_cursor.lnum;
5079 compl_startpos.col = compl_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080 ins_eol('\r');
5081#ifdef FEAT_COMMENTS
5082 curbuf->b_p_com = old;
5083#endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005084 compl_length = 0;
5085 compl_col = curwin->w_cursor.col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005086 }
5087 }
5088 else
5089 {
5090 edit_submode_pre = NULL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005091 compl_startpos.col = compl_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005092 }
5093
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005094 if (compl_cont_status & CONT_LOCAL)
5095 edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005096 else
5097 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
5098
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005099 /* Always add completion for the original text. */
5100 vim_free(compl_orig_text);
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005101 compl_orig_text = vim_strnsave(line + compl_col, compl_length);
5102 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
Bram Moolenaare8c3a142006-08-29 14:30:35 +00005103 -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005104 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005105 vim_free(compl_pattern);
5106 compl_pattern = NULL;
5107 vim_free(compl_orig_text);
5108 compl_orig_text = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005109 return FAIL;
5110 }
5111
5112 /* showmode might reset the internal line pointers, so it must
5113 * be called before line = ml_get(), or when this address is no
5114 * longer needed. -- Acevedo.
5115 */
5116 edit_submode_extra = (char_u *)_("-- Searching...");
5117 edit_submode_highl = HLF_COUNT;
5118 showmode();
5119 edit_submode_extra = NULL;
5120 out_flush();
5121 }
5122
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005123 compl_shown_match = compl_curr_match;
5124 compl_shows_dir = compl_direction;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005125
5126 /*
Bram Moolenaarc7453f52006-02-10 23:20:28 +00005127 * Find next match (and following matches).
Bram Moolenaar071d4272004-06-13 20:20:40 +00005128 */
Bram Moolenaarbe678f82010-03-10 14:15:54 +01005129 save_w_wrow = curwin->w_wrow;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00005130 n = ins_compl_next(TRUE, ins_compl_key2count(c), ins_compl_use_match(c));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005131
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00005132 /* may undisplay the popup menu */
5133 ins_compl_upd_pum();
5134
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005135 if (n > 1) /* all matches have been found */
5136 compl_matches = n;
5137 compl_curr_match = compl_shown_match;
5138 compl_direction = compl_shows_dir;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005139
Bram Moolenaard68071d2006-05-02 22:08:30 +00005140 /* Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
5141 * mode. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005142 if (got_int && !global_busy)
5143 {
5144 (void)vgetc();
5145 got_int = FALSE;
5146 }
5147
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005148 /* we found no match if the list has only the "compl_orig_text"-entry */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005149 if (compl_first_match == compl_first_match->cp_next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005150 {
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005151 edit_submode_extra = (compl_cont_status & CONT_ADDING)
5152 && compl_length > 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00005153 ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
5154 edit_submode_highl = HLF_E;
5155 /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
5156 * because we couldn't expand anything at first place, but if we used
5157 * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
5158 * (such as M in M'exico) if not tried already. -- Acevedo */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005159 if ( compl_length > 1
5160 || (compl_cont_status & CONT_ADDING)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005161 || (ctrl_x_mode != 0
5162 && ctrl_x_mode != CTRL_X_PATH_PATTERNS
5163 && ctrl_x_mode != CTRL_X_PATH_DEFINES))
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005164 compl_cont_status &= ~CONT_N_ADDS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005165 }
5166
Bram Moolenaar572cb562005-08-05 21:35:02 +00005167 if (compl_curr_match->cp_flags & CONT_S_IPOS)
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005168 compl_cont_status |= CONT_S_IPOS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005169 else
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005170 compl_cont_status &= ~CONT_S_IPOS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005171
5172 if (edit_submode_extra == NULL)
5173 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00005174 if (compl_curr_match->cp_flags & ORIGINAL_TEXT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005175 {
5176 edit_submode_extra = (char_u *)_("Back at original");
5177 edit_submode_highl = HLF_W;
5178 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005179 else if (compl_cont_status & CONT_S_IPOS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005180 {
5181 edit_submode_extra = (char_u *)_("Word from other line");
5182 edit_submode_highl = HLF_COUNT;
5183 }
Bram Moolenaar572cb562005-08-05 21:35:02 +00005184 else if (compl_curr_match->cp_next == compl_curr_match->cp_prev)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005185 {
5186 edit_submode_extra = (char_u *)_("The only match");
5187 edit_submode_highl = HLF_COUNT;
5188 }
5189 else
5190 {
5191 /* Update completion sequence number when needed. */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005192 if (compl_curr_match->cp_number == -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005193 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00005194 int number = 0;
5195 compl_T *match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005196
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005197 if (compl_direction == FORWARD)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005198 {
5199 /* search backwards for the first valid (!= -1) number.
5200 * This should normally succeed already at the first loop
5201 * cycle, so it's fast! */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005202 for (match = compl_curr_match->cp_prev; match != NULL
5203 && match != compl_first_match;
5204 match = match->cp_prev)
5205 if (match->cp_number != -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00005207 number = match->cp_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 break;
5209 }
5210 if (match != NULL)
5211 /* go up and assign all numbers which are not assigned
5212 * yet */
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00005213 for (match = match->cp_next;
5214 match != NULL && match->cp_number == -1;
Bram Moolenaar572cb562005-08-05 21:35:02 +00005215 match = match->cp_next)
5216 match->cp_number = ++number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005217 }
5218 else /* BACKWARD */
5219 {
5220 /* search forwards (upwards) for the first valid (!= -1)
5221 * number. This should normally succeed already at the
5222 * first loop cycle, so it's fast! */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005223 for (match = compl_curr_match->cp_next; match != NULL
5224 && match != compl_first_match;
5225 match = match->cp_next)
5226 if (match->cp_number != -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005227 {
Bram Moolenaar572cb562005-08-05 21:35:02 +00005228 number = match->cp_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005229 break;
5230 }
5231 if (match != NULL)
5232 /* go down and assign all numbers which are not
5233 * assigned yet */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005234 for (match = match->cp_prev; match
5235 && match->cp_number == -1;
5236 match = match->cp_prev)
5237 match->cp_number = ++number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005238 }
5239 }
5240
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00005241 /* The match should always have a sequence number now, this is
5242 * just a safety check. */
Bram Moolenaar572cb562005-08-05 21:35:02 +00005243 if (compl_curr_match->cp_number != -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005244 {
Bram Moolenaar0739a1e2007-02-04 01:37:39 +00005245 /* Space for 10 text chars. + 2x10-digit no.s = 31.
5246 * Translations may need more than twice that. */
5247 static char_u match_ref[81];
Bram Moolenaar071d4272004-06-13 20:20:40 +00005248
Bram Moolenaar4be06f92005-07-29 22:36:03 +00005249 if (compl_matches > 0)
Bram Moolenaar0739a1e2007-02-04 01:37:39 +00005250 vim_snprintf((char *)match_ref, sizeof(match_ref),
5251 _("match %d of %d"),
Bram Moolenaar572cb562005-08-05 21:35:02 +00005252 compl_curr_match->cp_number, compl_matches);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005253 else
Bram Moolenaar0739a1e2007-02-04 01:37:39 +00005254 vim_snprintf((char *)match_ref, sizeof(match_ref),
5255 _("match %d"),
5256 compl_curr_match->cp_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257 edit_submode_extra = match_ref;
5258 edit_submode_highl = HLF_R;
5259 if (dollar_vcol)
5260 curs_columns(FALSE);
5261 }
5262 }
5263 }
5264
5265 /* Show a message about what (completion) mode we're in. */
5266 showmode();
5267 if (edit_submode_extra != NULL)
5268 {
5269 if (!p_smd)
5270 msg_attr(edit_submode_extra,
5271 edit_submode_highl < HLF_COUNT
5272 ? hl_attr(edit_submode_highl) : 0);
5273 }
5274 else
5275 msg_clr_cmdline(); /* necessary for "noshowmode" */
5276
Bram Moolenaard68071d2006-05-02 22:08:30 +00005277 /* Show the popup menu, unless we got interrupted. */
5278 if (!compl_interrupted)
5279 {
5280 /* RedrawingDisabled may be set when invoked through complete(). */
5281 n = RedrawingDisabled;
5282 RedrawingDisabled = 0;
Bram Moolenaarbe678f82010-03-10 14:15:54 +01005283
5284 /* If the cursor moved we need to remove the pum first. */
5285 setcursor();
5286 if (save_w_wrow != curwin->w_wrow)
5287 ins_compl_del_pum();
5288
Bram Moolenaard68071d2006-05-02 22:08:30 +00005289 ins_compl_show_pum();
5290 setcursor();
5291 RedrawingDisabled = n;
5292 }
Bram Moolenaar1423b9d2006-05-07 15:16:06 +00005293 compl_was_interrupted = compl_interrupted;
Bram Moolenaard68071d2006-05-02 22:08:30 +00005294 compl_interrupted = FALSE;
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00005295
Bram Moolenaar071d4272004-06-13 20:20:40 +00005296 return OK;
5297}
5298
5299/*
5300 * Looks in the first "len" chars. of "src" for search-metachars.
5301 * If dest is not NULL the chars. are copied there quoting (with
5302 * a backslash) the metachars, and dest would be NUL terminated.
5303 * Returns the length (needed) of dest
5304 */
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00005305 static unsigned
Bram Moolenaar071d4272004-06-13 20:20:40 +00005306quote_meta(dest, src, len)
5307 char_u *dest;
5308 char_u *src;
5309 int len;
5310{
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00005311 unsigned m = (unsigned)len + 1; /* one extra for the NUL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005312
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00005313 for ( ; --len >= 0; src++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005314 {
5315 switch (*src)
5316 {
5317 case '.':
5318 case '*':
5319 case '[':
5320 if (ctrl_x_mode == CTRL_X_DICTIONARY
5321 || ctrl_x_mode == CTRL_X_THESAURUS)
5322 break;
5323 case '~':
5324 if (!p_magic) /* quote these only if magic is set */
5325 break;
5326 case '\\':
5327 if (ctrl_x_mode == CTRL_X_DICTIONARY
5328 || ctrl_x_mode == CTRL_X_THESAURUS)
5329 break;
5330 case '^': /* currently it's not needed. */
5331 case '$':
5332 m++;
5333 if (dest != NULL)
5334 *dest++ = '\\';
5335 break;
5336 }
5337 if (dest != NULL)
5338 *dest++ = *src;
Bram Moolenaar572cb562005-08-05 21:35:02 +00005339# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00005340 /* Copy remaining bytes of a multibyte character. */
5341 if (has_mbyte)
5342 {
5343 int i, mb_len;
5344
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005345 mb_len = (*mb_ptr2len)(src) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005346 if (mb_len > 0 && len >= mb_len)
5347 for (i = 0; i < mb_len; ++i)
5348 {
5349 --len;
5350 ++src;
5351 if (dest != NULL)
5352 *dest++ = *src;
5353 }
5354 }
Bram Moolenaar572cb562005-08-05 21:35:02 +00005355# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005356 }
5357 if (dest != NULL)
5358 *dest = NUL;
5359
5360 return m;
5361}
5362#endif /* FEAT_INS_EXPAND */
5363
5364/*
5365 * Next character is interpreted literally.
5366 * A one, two or three digit decimal number is interpreted as its byte value.
5367 * If one or two digits are entered, the next character is given to vungetc().
5368 * For Unicode a character > 255 may be returned.
5369 */
5370 int
5371get_literal()
5372{
5373 int cc;
5374 int nc;
5375 int i;
5376 int hex = FALSE;
5377 int octal = FALSE;
5378#ifdef FEAT_MBYTE
5379 int unicode = 0;
5380#endif
5381
5382 if (got_int)
5383 return Ctrl_C;
5384
5385#ifdef FEAT_GUI
5386 /*
5387 * In GUI there is no point inserting the internal code for a special key.
5388 * It is more useful to insert the string "<KEY>" instead. This would
5389 * probably be useful in a text window too, but it would not be
5390 * vi-compatible (maybe there should be an option for it?) -- webb
5391 */
5392 if (gui.in_use)
5393 ++allow_keys;
5394#endif
5395#ifdef USE_ON_FLY_SCROLL
5396 dont_scroll = TRUE; /* disallow scrolling here */
5397#endif
5398 ++no_mapping; /* don't map the next key hits */
5399 cc = 0;
5400 i = 0;
5401 for (;;)
5402 {
Bram Moolenaar61abfd12007-09-13 16:26:47 +00005403 nc = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404#ifdef FEAT_CMDL_INFO
5405 if (!(State & CMDLINE)
5406# ifdef FEAT_MBYTE
5407 && MB_BYTE2LEN_CHECK(nc) == 1
5408# endif
5409 )
5410 add_to_showcmd(nc);
5411#endif
5412 if (nc == 'x' || nc == 'X')
5413 hex = TRUE;
5414 else if (nc == 'o' || nc == 'O')
5415 octal = TRUE;
5416#ifdef FEAT_MBYTE
5417 else if (nc == 'u' || nc == 'U')
5418 unicode = nc;
5419#endif
5420 else
5421 {
5422 if (hex
5423#ifdef FEAT_MBYTE
5424 || unicode != 0
5425#endif
5426 )
5427 {
5428 if (!vim_isxdigit(nc))
5429 break;
5430 cc = cc * 16 + hex2nr(nc);
5431 }
5432 else if (octal)
5433 {
5434 if (nc < '0' || nc > '7')
5435 break;
5436 cc = cc * 8 + nc - '0';
5437 }
5438 else
5439 {
5440 if (!VIM_ISDIGIT(nc))
5441 break;
5442 cc = cc * 10 + nc - '0';
5443 }
5444
5445 ++i;
5446 }
5447
5448 if (cc > 255
5449#ifdef FEAT_MBYTE
5450 && unicode == 0
5451#endif
5452 )
5453 cc = 255; /* limit range to 0-255 */
5454 nc = 0;
5455
5456 if (hex) /* hex: up to two chars */
5457 {
5458 if (i >= 2)
5459 break;
5460 }
5461#ifdef FEAT_MBYTE
5462 else if (unicode) /* Unicode: up to four or eight chars */
5463 {
5464 if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8))
5465 break;
5466 }
5467#endif
5468 else if (i >= 3) /* decimal or octal: up to three chars */
5469 break;
5470 }
5471 if (i == 0) /* no number entered */
5472 {
5473 if (nc == K_ZERO) /* NUL is stored as NL */
5474 {
5475 cc = '\n';
5476 nc = 0;
5477 }
5478 else
5479 {
5480 cc = nc;
5481 nc = 0;
5482 }
5483 }
5484
5485 if (cc == 0) /* NUL is stored as NL */
5486 cc = '\n';
Bram Moolenaar217ad922005-03-20 22:37:15 +00005487#ifdef FEAT_MBYTE
5488 if (enc_dbcs && (cc & 0xff) == 0)
5489 cc = '?'; /* don't accept an illegal DBCS char, the NUL in the
5490 second byte will cause trouble! */
5491#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005492
5493 --no_mapping;
5494#ifdef FEAT_GUI
5495 if (gui.in_use)
5496 --allow_keys;
5497#endif
5498 if (nc)
5499 vungetc(nc);
5500 got_int = FALSE; /* CTRL-C typed after CTRL-V is not an interrupt */
5501 return cc;
5502}
5503
5504/*
5505 * Insert character, taking care of special keys and mod_mask
5506 */
5507 static void
5508insert_special(c, allow_modmask, ctrlv)
5509 int c;
5510 int allow_modmask;
5511 int ctrlv; /* c was typed after CTRL-V */
5512{
5513 char_u *p;
5514 int len;
5515
5516 /*
5517 * Special function key, translate into "<Key>". Up to the last '>' is
5518 * inserted with ins_str(), so as not to replace characters in replace
5519 * mode.
5520 * Only use mod_mask for special keys, to avoid things like <S-Space>,
5521 * unless 'allow_modmask' is TRUE.
5522 */
5523#ifdef MACOS
5524 /* Command-key never produces a normal key */
5525 if (mod_mask & MOD_MASK_CMD)
5526 allow_modmask = TRUE;
5527#endif
5528 if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
5529 {
5530 p = get_special_key_name(c, mod_mask);
5531 len = (int)STRLEN(p);
5532 c = p[len - 1];
5533 if (len > 2)
5534 {
5535 if (stop_arrow() == FAIL)
5536 return;
5537 p[len - 1] = NUL;
5538 ins_str(p);
Bram Moolenaarebefac62005-12-28 22:39:57 +00005539 AppendToRedobuffLit(p, -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540 ctrlv = FALSE;
5541 }
5542 }
5543 if (stop_arrow() == OK)
5544 insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1);
5545}
5546
5547/*
5548 * Special characters in this context are those that need processing other
5549 * than the simple insertion that can be performed here. This includes ESC
5550 * which terminates the insert, and CR/NL which need special processing to
5551 * open up a new line. This routine tries to optimize insertions performed by
5552 * the "redo", "undo" or "put" commands, so it needs to know when it should
5553 * stop and defer processing to the "normal" mechanism.
5554 * '0' and '^' are special, because they can be followed by CTRL-D.
5555 */
5556#ifdef EBCDIC
5557# define ISSPECIAL(c) ((c) < ' ' || (c) == '0' || (c) == '^')
5558#else
5559# define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
5560#endif
5561
5562#ifdef FEAT_MBYTE
5563# define WHITECHAR(cc) (vim_iswhite(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
5564#else
5565# define WHITECHAR(cc) vim_iswhite(cc)
5566#endif
5567
5568 void
5569insertchar(c, flags, second_indent)
5570 int c; /* character to insert or NUL */
5571 int flags; /* INSCHAR_FORMAT, etc. */
5572 int second_indent; /* indent for second line if >= 0 */
5573{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005574 int textwidth;
5575#ifdef FEAT_COMMENTS
Bram Moolenaar071d4272004-06-13 20:20:40 +00005576 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005578 int fo_ins_blank;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579
5580 textwidth = comp_textwidth(flags & INSCHAR_FORMAT);
5581 fo_ins_blank = has_format_option(FO_INS_BLANK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005582
5583 /*
5584 * Try to break the line in two or more pieces when:
5585 * - Always do this if we have been called to do formatting only.
5586 * - Always do this when 'formatoptions' has the 'a' flag and the line
5587 * ends in white space.
5588 * - Otherwise:
5589 * - Don't do this if inserting a blank
5590 * - Don't do this if an existing character is being replaced, unless
5591 * we're in VREPLACE mode.
5592 * - Do this if the cursor is not on the line where insert started
5593 * or - 'formatoptions' doesn't have 'l' or the line was not too long
5594 * before the insert.
5595 * - 'formatoptions' doesn't have 'b' or a blank was inserted at or
5596 * before 'textwidth'
5597 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005598 if (textwidth > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00005599 && ((flags & INSCHAR_FORMAT)
5600 || (!vim_iswhite(c)
5601 && !((State & REPLACE_FLAG)
5602#ifdef FEAT_VREPLACE
5603 && !(State & VREPLACE_FLAG)
5604#endif
5605 && *ml_get_cursor() != NUL)
5606 && (curwin->w_cursor.lnum != Insstart.lnum
5607 || ((!has_format_option(FO_INS_LONG)
5608 || Insstart_textlen <= (colnr_T)textwidth)
5609 && (!fo_ins_blank
5610 || Insstart_blank_vcol <= (colnr_T)textwidth
5611 ))))))
5612 {
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005613 /* Format with 'formatexpr' when it's set. Use internal formatting
5614 * when 'formatexpr' isn't set or it returns non-zero. */
5615#if defined(FEAT_EVAL)
Bram Moolenaarf3442e72006-10-10 13:49:10 +00005616 int do_internal = TRUE;
5617
Bram Moolenaar81a82092008-03-12 16:27:00 +00005618 if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0)
Bram Moolenaarf3442e72006-10-10 13:49:10 +00005619 {
5620 do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0);
5621 /* It may be required to save for undo again, e.g. when setline()
5622 * was called. */
5623 ins_need_undo = TRUE;
5624 }
5625 if (do_internal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005626#endif
Bram Moolenaar97b98102009-11-17 16:41:01 +00005627 internal_format(textwidth, second_indent, flags, c == NUL, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005628 }
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005629
Bram Moolenaar071d4272004-06-13 20:20:40 +00005630 if (c == NUL) /* only formatting was wanted */
5631 return;
5632
5633#ifdef FEAT_COMMENTS
5634 /* Check whether this character should end a comment. */
5635 if (did_ai && (int)c == end_comment_pending)
5636 {
5637 char_u *line;
5638 char_u lead_end[COM_MAX_LEN]; /* end-comment string */
5639 int middle_len, end_len;
5640 int i;
5641
5642 /*
5643 * Need to remove existing (middle) comment leader and insert end
5644 * comment leader. First, check what comment leader we can find.
5645 */
5646 i = get_leader_len(line = ml_get_curline(), &p, FALSE);
5647 if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) /* Just checking */
5648 {
5649 /* Skip middle-comment string */
5650 while (*p && p[-1] != ':') /* find end of middle flags */
5651 ++p;
5652 middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
5653 /* Don't count trailing white space for middle_len */
5654 while (middle_len > 0 && vim_iswhite(lead_end[middle_len - 1]))
5655 --middle_len;
5656
5657 /* Find the end-comment string */
5658 while (*p && p[-1] != ':') /* find end of end flags */
5659 ++p;
5660 end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
5661
5662 /* Skip white space before the cursor */
5663 i = curwin->w_cursor.col;
5664 while (--i >= 0 && vim_iswhite(line[i]))
5665 ;
5666 i++;
5667
5668 /* Skip to before the middle leader */
5669 i -= middle_len;
5670
5671 /* Check some expected things before we go on */
5672 if (i >= 0 && lead_end[end_len - 1] == end_comment_pending)
5673 {
5674 /* Backspace over all the stuff we want to replace */
5675 backspace_until_column(i);
5676
5677 /*
5678 * Insert the end-comment string, except for the last
5679 * character, which will get inserted as normal later.
5680 */
5681 ins_bytes_len(lead_end, end_len - 1);
5682 }
5683 }
5684 }
5685 end_comment_pending = NUL;
5686#endif
5687
5688 did_ai = FALSE;
5689#ifdef FEAT_SMARTINDENT
5690 did_si = FALSE;
5691 can_si = FALSE;
5692 can_si_back = FALSE;
5693#endif
5694
5695 /*
5696 * If there's any pending input, grab up to INPUT_BUFLEN at once.
5697 * This speeds up normal text input considerably.
5698 * Don't do this when 'cindent' or 'indentexpr' is set, because we might
5699 * need to re-indent at a ':', or any other character (but not what
5700 * 'paste' is set)..
5701 */
5702#ifdef USE_ON_FLY_SCROLL
5703 dont_scroll = FALSE; /* allow scrolling here */
5704#endif
5705
5706 if ( !ISSPECIAL(c)
5707#ifdef FEAT_MBYTE
5708 && (!has_mbyte || (*mb_char2len)(c) == 1)
5709#endif
5710 && vpeekc() != NUL
5711 && !(State & REPLACE_FLAG)
5712#ifdef FEAT_CINDENT
5713 && !cindent_on()
5714#endif
5715#ifdef FEAT_RIGHTLEFT
5716 && !p_ri
5717#endif
5718 )
5719 {
5720#define INPUT_BUFLEN 100
5721 char_u buf[INPUT_BUFLEN + 1];
5722 int i;
5723 colnr_T virtcol = 0;
5724
5725 buf[0] = c;
5726 i = 1;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005727 if (textwidth > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005728 virtcol = get_nolist_virtcol();
5729 /*
5730 * Stop the string when:
5731 * - no more chars available
5732 * - finding a special character (command key)
5733 * - buffer is full
5734 * - running into the 'textwidth' boundary
5735 * - need to check for abbreviation: A non-word char after a word-char
5736 */
5737 while ( (c = vpeekc()) != NUL
5738 && !ISSPECIAL(c)
5739#ifdef FEAT_MBYTE
5740 && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
5741#endif
5742 && i < INPUT_BUFLEN
5743 && (textwidth == 0
5744 || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
5745 && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
5746 {
5747#ifdef FEAT_RIGHTLEFT
5748 c = vgetc();
5749 if (p_hkmap && KeyTyped)
5750 c = hkmap(c); /* Hebrew mode mapping */
5751# ifdef FEAT_FKMAP
5752 if (p_fkmap && KeyTyped)
5753 c = fkmap(c); /* Farsi mode mapping */
5754# endif
5755 buf[i++] = c;
5756#else
5757 buf[i++] = vgetc();
5758#endif
5759 }
5760
5761#ifdef FEAT_DIGRAPHS
5762 do_digraph(-1); /* clear digraphs */
5763 do_digraph(buf[i-1]); /* may be the start of a digraph */
5764#endif
5765 buf[i] = NUL;
5766 ins_str(buf);
5767 if (flags & INSCHAR_CTRLV)
5768 {
5769 redo_literal(*buf);
5770 i = 1;
5771 }
5772 else
5773 i = 0;
5774 if (buf[i] != NUL)
Bram Moolenaarebefac62005-12-28 22:39:57 +00005775 AppendToRedobuffLit(buf + i, -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005776 }
5777 else
5778 {
5779#ifdef FEAT_MBYTE
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005780 int cc;
5781
Bram Moolenaar071d4272004-06-13 20:20:40 +00005782 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
5783 {
5784 char_u buf[MB_MAXBYTES + 1];
5785
5786 (*mb_char2bytes)(c, buf);
5787 buf[cc] = NUL;
5788 ins_char_bytes(buf, cc);
5789 AppendCharToRedobuff(c);
5790 }
5791 else
5792#endif
5793 {
5794 ins_char(c);
5795 if (flags & INSCHAR_CTRLV)
5796 redo_literal(c);
5797 else
5798 AppendCharToRedobuff(c);
5799 }
5800 }
5801}
5802
5803/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005804 * Format text at the current insert position.
5805 */
5806 static void
Bram Moolenaar97b98102009-11-17 16:41:01 +00005807internal_format(textwidth, second_indent, flags, format_only, c)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005808 int textwidth;
5809 int second_indent;
5810 int flags;
5811 int format_only;
Bram Moolenaar97b98102009-11-17 16:41:01 +00005812 int c; /* character to be inserted (can be NUL) */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005813{
5814 int cc;
5815 int save_char = NUL;
5816 int haveto_redraw = FALSE;
5817 int fo_ins_blank = has_format_option(FO_INS_BLANK);
5818#ifdef FEAT_MBYTE
5819 int fo_multibyte = has_format_option(FO_MBYTE_BREAK);
5820#endif
5821 int fo_white_par = has_format_option(FO_WHITE_PAR);
5822 int first_line = TRUE;
5823#ifdef FEAT_COMMENTS
5824 colnr_T leader_len;
5825 int no_leader = FALSE;
5826 int do_comments = (flags & INSCHAR_DO_COM);
5827#endif
5828
5829 /*
5830 * When 'ai' is off we don't want a space under the cursor to be
5831 * deleted. Replace it with an 'x' temporarily.
5832 */
Bram Moolenaar97b98102009-11-17 16:41:01 +00005833 if (!curbuf->b_p_ai
5834#ifdef FEAT_VREPLACE
5835 && !(State & VREPLACE_FLAG)
5836#endif
5837 )
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005838 {
5839 cc = gchar_cursor();
5840 if (vim_iswhite(cc))
5841 {
5842 save_char = cc;
5843 pchar_cursor('x');
5844 }
5845 }
5846
5847 /*
5848 * Repeat breaking lines, until the current line is not too long.
5849 */
5850 while (!got_int)
5851 {
5852 int startcol; /* Cursor column at entry */
5853 int wantcol; /* column at textwidth border */
5854 int foundcol; /* column for start of spaces */
5855 int end_foundcol = 0; /* column for start of word */
5856 colnr_T len;
5857 colnr_T virtcol;
5858#ifdef FEAT_VREPLACE
5859 int orig_col = 0;
5860 char_u *saved_text = NULL;
5861#endif
5862 colnr_T col;
Bram Moolenaar97b98102009-11-17 16:41:01 +00005863 colnr_T end_col;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005864
Bram Moolenaar97b98102009-11-17 16:41:01 +00005865 virtcol = get_nolist_virtcol()
5866 + char2cells(c != NUL ? c : gchar_cursor());
5867 if (virtcol <= (colnr_T)textwidth)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005868 break;
5869
5870#ifdef FEAT_COMMENTS
5871 if (no_leader)
5872 do_comments = FALSE;
5873 else if (!(flags & INSCHAR_FORMAT)
5874 && has_format_option(FO_WRAP_COMS))
5875 do_comments = TRUE;
5876
5877 /* Don't break until after the comment leader */
5878 if (do_comments)
5879 leader_len = get_leader_len(ml_get_curline(), NULL, FALSE);
5880 else
5881 leader_len = 0;
5882
5883 /* If the line doesn't start with a comment leader, then don't
5884 * start one in a following broken line. Avoids that a %word
5885 * moved to the start of the next line causes all following lines
5886 * to start with %. */
5887 if (leader_len == 0)
5888 no_leader = TRUE;
5889#endif
5890 if (!(flags & INSCHAR_FORMAT)
5891#ifdef FEAT_COMMENTS
5892 && leader_len == 0
5893#endif
5894 && !has_format_option(FO_WRAP))
5895
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005896 break;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005897 if ((startcol = curwin->w_cursor.col) == 0)
5898 break;
5899
5900 /* find column of textwidth border */
5901 coladvance((colnr_T)textwidth);
5902 wantcol = curwin->w_cursor.col;
5903
Bram Moolenaar97b98102009-11-17 16:41:01 +00005904 curwin->w_cursor.col = startcol;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005905 foundcol = 0;
5906
5907 /*
5908 * Find position to break at.
5909 * Stop at first entered white when 'formatoptions' has 'v'
5910 */
5911 while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
5912 || curwin->w_cursor.lnum != Insstart.lnum
5913 || curwin->w_cursor.col >= Insstart.col)
5914 {
Bram Moolenaar97b98102009-11-17 16:41:01 +00005915 if (curwin->w_cursor.col == startcol && c != NUL)
5916 cc = c;
5917 else
5918 cc = gchar_cursor();
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005919 if (WHITECHAR(cc))
5920 {
5921 /* remember position of blank just before text */
Bram Moolenaar97b98102009-11-17 16:41:01 +00005922 end_col = curwin->w_cursor.col;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005923
5924 /* find start of sequence of blanks */
5925 while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
5926 {
5927 dec_cursor();
5928 cc = gchar_cursor();
5929 }
5930 if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
5931 break; /* only spaces in front of text */
5932#ifdef FEAT_COMMENTS
5933 /* Don't break until after the comment leader */
5934 if (curwin->w_cursor.col < leader_len)
5935 break;
5936#endif
5937 if (has_format_option(FO_ONE_LETTER))
5938 {
5939 /* do not break after one-letter words */
5940 if (curwin->w_cursor.col == 0)
5941 break; /* one-letter word at begin */
Bram Moolenaar97b98102009-11-17 16:41:01 +00005942#ifdef FEAT_COMMENTS
5943 /* do not break "#a b" when 'tw' is 2 */
5944 if (curwin->w_cursor.col <= leader_len)
5945 break;
5946#endif
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005947 col = curwin->w_cursor.col;
5948 dec_cursor();
5949 cc = gchar_cursor();
5950
5951 if (WHITECHAR(cc))
5952 continue; /* one-letter, continue */
5953 curwin->w_cursor.col = col;
5954 }
Bram Moolenaar97b98102009-11-17 16:41:01 +00005955
5956 inc_cursor();
5957
5958 end_foundcol = end_col + 1;
5959 foundcol = curwin->w_cursor.col;
5960 if (curwin->w_cursor.col <= (colnr_T)wantcol)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005961 break;
5962 }
5963#ifdef FEAT_MBYTE
Bram Moolenaar97b98102009-11-17 16:41:01 +00005964 else if (cc >= 0x100 && fo_multibyte)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005965 {
5966 /* Break after or before a multi-byte character. */
Bram Moolenaar97b98102009-11-17 16:41:01 +00005967 if (curwin->w_cursor.col != startcol)
5968 {
5969#ifdef FEAT_COMMENTS
5970 /* Don't break until after the comment leader */
5971 if (curwin->w_cursor.col < leader_len)
5972 break;
5973#endif
5974 col = curwin->w_cursor.col;
5975 inc_cursor();
5976 /* Don't change end_foundcol if already set. */
5977 if (foundcol != curwin->w_cursor.col)
5978 {
5979 foundcol = curwin->w_cursor.col;
5980 end_foundcol = foundcol;
5981 if (curwin->w_cursor.col <= (colnr_T)wantcol)
5982 break;
5983 }
5984 curwin->w_cursor.col = col;
5985 }
5986
5987 if (curwin->w_cursor.col == 0)
5988 break;
5989
5990 col = curwin->w_cursor.col;
5991
5992 dec_cursor();
5993 cc = gchar_cursor();
5994
5995 if (WHITECHAR(cc))
5996 continue; /* break with space */
5997#ifdef FEAT_COMMENTS
5998 /* Don't break until after the comment leader */
5999 if (curwin->w_cursor.col < leader_len)
6000 break;
6001#endif
6002
6003 curwin->w_cursor.col = col;
6004
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006005 foundcol = curwin->w_cursor.col;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006006 end_foundcol = foundcol;
Bram Moolenaar97b98102009-11-17 16:41:01 +00006007 if (curwin->w_cursor.col <= (colnr_T)wantcol)
6008 break;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006009 }
6010#endif
6011 if (curwin->w_cursor.col == 0)
6012 break;
6013 dec_cursor();
6014 }
6015
6016 if (foundcol == 0) /* no spaces, cannot break line */
6017 {
6018 curwin->w_cursor.col = startcol;
6019 break;
6020 }
6021
6022 /* Going to break the line, remove any "$" now. */
6023 undisplay_dollar();
6024
6025 /*
6026 * Offset between cursor position and line break is used by replace
6027 * stack functions. VREPLACE does not use this, and backspaces
6028 * over the text instead.
6029 */
6030#ifdef FEAT_VREPLACE
6031 if (State & VREPLACE_FLAG)
6032 orig_col = startcol; /* Will start backspacing from here */
6033 else
6034#endif
Bram Moolenaar97b98102009-11-17 16:41:01 +00006035 replace_offset = startcol - end_foundcol;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006036
6037 /*
6038 * adjust startcol for spaces that will be deleted and
6039 * characters that will remain on top line
6040 */
6041 curwin->w_cursor.col = foundcol;
Bram Moolenaar97b98102009-11-17 16:41:01 +00006042 while ((cc = gchar_cursor(), WHITECHAR(cc))
6043 && (!fo_white_par || curwin->w_cursor.col < startcol))
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006044 inc_cursor();
6045 startcol -= curwin->w_cursor.col;
6046 if (startcol < 0)
6047 startcol = 0;
6048
6049#ifdef FEAT_VREPLACE
6050 if (State & VREPLACE_FLAG)
6051 {
6052 /*
6053 * In VREPLACE mode, we will backspace over the text to be
6054 * wrapped, so save a copy now to put on the next line.
6055 */
6056 saved_text = vim_strsave(ml_get_cursor());
6057 curwin->w_cursor.col = orig_col;
6058 if (saved_text == NULL)
6059 break; /* Can't do it, out of memory */
6060 saved_text[startcol] = NUL;
6061
6062 /* Backspace over characters that will move to the next line */
6063 if (!fo_white_par)
6064 backspace_until_column(foundcol);
6065 }
6066 else
6067#endif
6068 {
6069 /* put cursor after pos. to break line */
6070 if (!fo_white_par)
6071 curwin->w_cursor.col = foundcol;
6072 }
6073
6074 /*
6075 * Split the line just before the margin.
6076 * Only insert/delete lines, but don't really redraw the window.
6077 */
6078 open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
6079 + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
6080#ifdef FEAT_COMMENTS
6081 + (do_comments ? OPENLINE_DO_COM : 0)
6082#endif
6083 , old_indent);
6084 old_indent = 0;
6085
6086 replace_offset = 0;
6087 if (first_line)
6088 {
6089 if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
6090 second_indent = get_number_indent(curwin->w_cursor.lnum -1);
6091 if (second_indent >= 0)
6092 {
6093#ifdef FEAT_VREPLACE
6094 if (State & VREPLACE_FLAG)
Bram Moolenaar21b17e72008-01-16 19:03:13 +00006095 change_indent(INDENT_SET, second_indent, FALSE, NUL, TRUE);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00006096 else
6097#endif
6098 (void)set_indent(second_indent, SIN_CHANGED);
6099 }
6100 first_line = FALSE;
6101 }
6102
6103#ifdef FEAT_VREPLACE
6104 if (State & VREPLACE_FLAG)
6105 {
6106 /*
6107 * In VREPLACE mode we have backspaced over the text to be
6108 * moved, now we re-insert it into the new line.
6109 */
6110 ins_bytes(saved_text);
6111 vim_free(saved_text);
6112 }
6113 else
6114#endif
6115 {
6116 /*
6117 * Check if cursor is not past the NUL off the line, cindent
6118 * may have added or removed indent.
6119 */
6120 curwin->w_cursor.col += startcol;
6121 len = (colnr_T)STRLEN(ml_get_curline());
6122 if (curwin->w_cursor.col > len)
6123 curwin->w_cursor.col = len;
6124 }
6125
6126 haveto_redraw = TRUE;
6127#ifdef FEAT_CINDENT
6128 can_cindent = TRUE;
6129#endif
6130 /* moved the cursor, don't autoindent or cindent now */
6131 did_ai = FALSE;
6132#ifdef FEAT_SMARTINDENT
6133 did_si = FALSE;
6134 can_si = FALSE;
6135 can_si_back = FALSE;
6136#endif
6137 line_breakcheck();
6138 }
6139
6140 if (save_char != NUL) /* put back space after cursor */
6141 pchar_cursor(save_char);
6142
6143 if (!format_only && haveto_redraw)
6144 {
6145 update_topline();
6146 redraw_curbuf_later(VALID);
6147 }
6148}
6149
6150/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006151 * Called after inserting or deleting text: When 'formatoptions' includes the
6152 * 'a' flag format from the current line until the end of the paragraph.
6153 * Keep the cursor at the same position relative to the text.
6154 * The caller must have saved the cursor line for undo, following ones will be
6155 * saved here.
6156 */
6157 void
6158auto_format(trailblank, prev_line)
6159 int trailblank; /* when TRUE also format with trailing blank */
6160 int prev_line; /* may start in previous line */
6161{
6162 pos_T pos;
6163 colnr_T len;
6164 char_u *old;
6165 char_u *new, *pnew;
6166 int wasatend;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006167 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006168
6169 if (!has_format_option(FO_AUTO))
6170 return;
6171
6172 pos = curwin->w_cursor;
6173 old = ml_get_curline();
6174
6175 /* may remove added space */
6176 check_auto_format(FALSE);
6177
6178 /* Don't format in Insert mode when the cursor is on a trailing blank, the
6179 * user might insert normal text next. Also skip formatting when "1" is
6180 * in 'formatoptions' and there is a single character before the cursor.
6181 * Otherwise the line would be broken and when typing another non-white
6182 * next they are not joined back together. */
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00006183 wasatend = (pos.col == (colnr_T)STRLEN(old));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006184 if (*old != NUL && !trailblank && wasatend)
6185 {
6186 dec_cursor();
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006187 cc = gchar_cursor();
6188 if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
6189 && has_format_option(FO_ONE_LETTER))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006190 dec_cursor();
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006191 cc = gchar_cursor();
6192 if (WHITECHAR(cc))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006193 {
6194 curwin->w_cursor = pos;
6195 return;
6196 }
6197 curwin->w_cursor = pos;
6198 }
6199
6200#ifdef FEAT_COMMENTS
6201 /* With the 'c' flag in 'formatoptions' and 't' missing: only format
6202 * comments. */
6203 if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
6204 && get_leader_len(old, NULL, FALSE) == 0)
6205 return;
6206#endif
6207
6208 /*
6209 * May start formatting in a previous line, so that after "x" a word is
6210 * moved to the previous line if it fits there now. Only when this is not
6211 * the start of a paragraph.
6212 */
6213 if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
6214 {
6215 --curwin->w_cursor.lnum;
6216 if (u_save_cursor() == FAIL)
6217 return;
6218 }
6219
6220 /*
6221 * Do the formatting and restore the cursor position. "saved_cursor" will
6222 * be adjusted for the text formatting.
6223 */
6224 saved_cursor = pos;
Bram Moolenaar81a82092008-03-12 16:27:00 +00006225 format_lines((linenr_T)-1, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006226 curwin->w_cursor = saved_cursor;
6227 saved_cursor.lnum = 0;
6228
6229 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
6230 {
6231 /* "cannot happen" */
6232 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
6233 coladvance((colnr_T)MAXCOL);
6234 }
6235 else
6236 check_cursor_col();
6237
6238 /* Insert mode: If the cursor is now after the end of the line while it
6239 * previously wasn't, the line was broken. Because of the rule above we
6240 * need to add a space when 'w' is in 'formatoptions' to keep a paragraph
6241 * formatted. */
6242 if (!wasatend && has_format_option(FO_WHITE_PAR))
6243 {
6244 new = ml_get_curline();
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006245 len = (colnr_T)STRLEN(new);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006246 if (curwin->w_cursor.col == len)
6247 {
6248 pnew = vim_strnsave(new, len + 2);
6249 pnew[len] = ' ';
6250 pnew[len + 1] = NUL;
6251 ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
6252 /* remove the space later */
6253 did_add_space = TRUE;
6254 }
6255 else
6256 /* may remove added space */
6257 check_auto_format(FALSE);
6258 }
6259
6260 check_cursor();
6261}
6262
6263/*
6264 * When an extra space was added to continue a paragraph for auto-formatting,
6265 * delete it now. The space must be under the cursor, just after the insert
6266 * position.
6267 */
6268 static void
6269check_auto_format(end_insert)
6270 int end_insert; /* TRUE when ending Insert mode */
6271{
6272 int c = ' ';
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006273 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006274
6275 if (did_add_space)
6276 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006277 cc = gchar_cursor();
6278 if (!WHITECHAR(cc))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006279 /* Somehow the space was removed already. */
6280 did_add_space = FALSE;
6281 else
6282 {
6283 if (!end_insert)
6284 {
6285 inc_cursor();
6286 c = gchar_cursor();
6287 dec_cursor();
6288 }
6289 if (c != NUL)
6290 {
6291 /* The space is no longer at the end of the line, delete it. */
6292 del_char(FALSE);
6293 did_add_space = FALSE;
6294 }
6295 }
6296 }
6297}
6298
6299/*
6300 * Find out textwidth to be used for formatting:
6301 * if 'textwidth' option is set, use it
6302 * else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin'
6303 * if invalid value, use 0.
6304 * Set default to window width (maximum 79) for "gq" operator.
6305 */
6306 int
6307comp_textwidth(ff)
Bram Moolenaar91170f82006-05-05 21:15:17 +00006308 int ff; /* force formatting (for "gq" command) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006309{
6310 int textwidth;
6311
6312 textwidth = curbuf->b_p_tw;
6313 if (textwidth == 0 && curbuf->b_p_wm)
6314 {
6315 /* The width is the window width minus 'wrapmargin' minus all the
6316 * things that add to the margin. */
6317 textwidth = W_WIDTH(curwin) - curbuf->b_p_wm;
6318#ifdef FEAT_CMDWIN
6319 if (cmdwin_type != 0)
6320 textwidth -= 1;
6321#endif
6322#ifdef FEAT_FOLDING
6323 textwidth -= curwin->w_p_fdc;
6324#endif
6325#ifdef FEAT_SIGNS
6326 if (curwin->w_buffer->b_signlist != NULL
6327# ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02006328 || netbeans_active()
Bram Moolenaar071d4272004-06-13 20:20:40 +00006329# endif
6330 )
6331 textwidth -= 1;
6332#endif
Bram Moolenaar64486672010-05-16 15:46:46 +02006333 if (curwin->w_p_nu || curwin->w_p_rnu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006334 textwidth -= 8;
6335 }
6336 if (textwidth < 0)
6337 textwidth = 0;
6338 if (ff && textwidth == 0)
6339 {
6340 textwidth = W_WIDTH(curwin) - 1;
6341 if (textwidth > 79)
6342 textwidth = 79;
6343 }
6344 return textwidth;
6345}
6346
6347/*
6348 * Put a character in the redo buffer, for when just after a CTRL-V.
6349 */
6350 static void
6351redo_literal(c)
6352 int c;
6353{
6354 char_u buf[10];
6355
6356 /* Only digits need special treatment. Translate them into a string of
6357 * three digits. */
6358 if (VIM_ISDIGIT(c))
6359 {
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00006360 vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006361 AppendToRedobuff(buf);
6362 }
6363 else
6364 AppendCharToRedobuff(c);
6365}
6366
6367/*
6368 * start_arrow() is called when an arrow key is used in insert mode.
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00006369 * For undo/redo it resembles hitting the <ESC> key.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006370 */
6371 static void
6372start_arrow(end_insert_pos)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006373 pos_T *end_insert_pos; /* can be NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006374{
6375 if (!arrow_used) /* something has been inserted */
6376 {
6377 AppendToRedobuff(ESC_STR);
6378 stop_insert(end_insert_pos, FALSE);
6379 arrow_used = TRUE; /* this means we stopped the current insert */
6380 }
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00006381#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00006382 check_spell_redraw();
6383#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006384}
6385
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00006386#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00006387/*
6388 * If we skipped highlighting word at cursor, do it now.
6389 * It may be skipped again, thus reset spell_redraw_lnum first.
6390 */
6391 static void
6392check_spell_redraw()
6393{
6394 if (spell_redraw_lnum != 0)
6395 {
6396 linenr_T lnum = spell_redraw_lnum;
6397
6398 spell_redraw_lnum = 0;
6399 redrawWinline(lnum, FALSE);
6400 }
6401}
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00006402
6403/*
6404 * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
6405 * spelled word, if there is one.
6406 */
6407 static void
6408spell_back_to_badword()
6409{
6410 pos_T tpos = curwin->w_cursor;
6411
Bram Moolenaar81f1ecb2005-08-25 21:27:31 +00006412 spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00006413 if (curwin->w_cursor.col != tpos.col)
6414 start_arrow(&tpos);
6415}
Bram Moolenaar217ad922005-03-20 22:37:15 +00006416#endif
6417
Bram Moolenaar071d4272004-06-13 20:20:40 +00006418/*
6419 * stop_arrow() is called before a change is made in insert mode.
6420 * If an arrow key has been used, start a new insertion.
6421 * Returns FAIL if undo is impossible, shouldn't insert then.
6422 */
6423 int
6424stop_arrow()
6425{
6426 if (arrow_used)
6427 {
6428 if (u_save_cursor() == OK)
6429 {
6430 arrow_used = FALSE;
6431 ins_need_undo = FALSE;
6432 }
6433 Insstart = curwin->w_cursor; /* new insertion starts here */
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00006434 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
Bram Moolenaar071d4272004-06-13 20:20:40 +00006435 ai_col = 0;
6436#ifdef FEAT_VREPLACE
6437 if (State & VREPLACE_FLAG)
6438 {
6439 orig_line_count = curbuf->b_ml.ml_line_count;
6440 vr_lines_changed = 1;
6441 }
6442#endif
6443 ResetRedobuff();
6444 AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
Bram Moolenaara9b1e742005-12-19 22:14:58 +00006445 new_insert_skip = 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006446 }
6447 else if (ins_need_undo)
6448 {
6449 if (u_save_cursor() == OK)
6450 ins_need_undo = FALSE;
6451 }
6452
6453#ifdef FEAT_FOLDING
6454 /* Always open fold at the cursor line when inserting something. */
6455 foldOpenCursor();
6456#endif
6457
6458 return (arrow_used || ins_need_undo ? FAIL : OK);
6459}
6460
6461/*
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006462 * Do a few things to stop inserting.
6463 * "end_insert_pos" is where insert ended. It is NULL when we already jumped
6464 * to another window/buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006465 */
6466 static void
6467stop_insert(end_insert_pos, esc)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006468 pos_T *end_insert_pos;
Bram Moolenaar83c465c2005-12-16 21:53:56 +00006469 int esc; /* called by ins_esc() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006470{
Bram Moolenaar83c465c2005-12-16 21:53:56 +00006471 int cc;
6472 char_u *ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006473
6474 stop_redo_ins();
6475 replace_flush(); /* abandon replace stack */
6476
6477 /*
Bram Moolenaar83c465c2005-12-16 21:53:56 +00006478 * Save the inserted text for later redo with ^@ and CTRL-A.
6479 * Don't do it when "restart_edit" was set and nothing was inserted,
6480 * otherwise CTRL-O w and then <Left> will clear "last_insert".
Bram Moolenaar071d4272004-06-13 20:20:40 +00006481 */
Bram Moolenaar83c465c2005-12-16 21:53:56 +00006482 ptr = get_inserted();
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00006483 if (did_restart_edit == 0 || (ptr != NULL
6484 && (int)STRLEN(ptr) > new_insert_skip))
Bram Moolenaar83c465c2005-12-16 21:53:56 +00006485 {
6486 vim_free(last_insert);
6487 last_insert = ptr;
6488 last_insert_skip = new_insert_skip;
6489 }
6490 else
6491 vim_free(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006492
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006493 if (!arrow_used && end_insert_pos != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006494 {
6495 /* Auto-format now. It may seem strange to do this when stopping an
6496 * insertion (or moving the cursor), but it's required when appending
6497 * a line and having it end in a space. But only do it when something
6498 * was actually inserted, otherwise undo won't work. */
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006499 if (!ins_need_undo && has_format_option(FO_AUTO))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006500 {
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006501 pos_T tpos = curwin->w_cursor;
6502
Bram Moolenaar071d4272004-06-13 20:20:40 +00006503 /* When the cursor is at the end of the line after a space the
6504 * formatting will move it to the following word. Avoid that by
6505 * moving the cursor onto the space. */
6506 cc = 'x';
6507 if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL)
6508 {
6509 dec_cursor();
6510 cc = gchar_cursor();
6511 if (!vim_iswhite(cc))
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006512 curwin->w_cursor = tpos;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006513 }
6514
6515 auto_format(TRUE, FALSE);
6516
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006517 if (vim_iswhite(cc))
6518 {
6519 if (gchar_cursor() != NUL)
6520 inc_cursor();
6521#ifdef FEAT_VIRTUALEDIT
6522 /* If the cursor is still at the same character, also keep
6523 * the "coladd". */
6524 if (gchar_cursor() == NUL
6525 && curwin->w_cursor.lnum == tpos.lnum
6526 && curwin->w_cursor.col == tpos.col)
6527 curwin->w_cursor.coladd = tpos.coladd;
6528#endif
6529 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006530 }
6531
6532 /* If a space was inserted for auto-formatting, remove it now. */
6533 check_auto_format(TRUE);
6534
6535 /* If we just did an auto-indent, remove the white space from the end
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006536 * of the line, and put the cursor back.
Bram Moolenaar4be50682009-05-26 09:02:10 +00006537 * Do this when ESC was used or moving the cursor up/down.
6538 * Check for the old position still being valid, just in case the text
6539 * got changed unexpectedly. */
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006540 if (did_ai && (esc || (vim_strchr(p_cpo, CPO_INDENT) == NULL
Bram Moolenaar4be50682009-05-26 09:02:10 +00006541 && curwin->w_cursor.lnum != end_insert_pos->lnum))
6542 && end_insert_pos->lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006543 {
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006544 pos_T tpos = curwin->w_cursor;
6545
6546 curwin->w_cursor = *end_insert_pos;
Bram Moolenaar4be50682009-05-26 09:02:10 +00006547 check_cursor_col(); /* make sure it is not past the line */
Bram Moolenaar39f05632006-03-19 22:15:26 +00006548 for (;;)
6549 {
6550 if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
6551 --curwin->w_cursor.col;
6552 cc = gchar_cursor();
6553 if (!vim_iswhite(cc))
6554 break;
Bram Moolenaar4be50682009-05-26 09:02:10 +00006555 if (del_char(TRUE) == FAIL)
6556 break; /* should not happen */
Bram Moolenaar39f05632006-03-19 22:15:26 +00006557 }
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00006558 if (curwin->w_cursor.lnum != tpos.lnum)
6559 curwin->w_cursor = tpos;
6560 else if (cc != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006561 ++curwin->w_cursor.col; /* put cursor back on the NUL */
6562
6563#ifdef FEAT_VISUAL
6564 /* <C-S-Right> may have started Visual mode, adjust the position for
6565 * deleted characters. */
6566 if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum)
6567 {
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00006568 int len = (int)STRLEN(ml_get_curline());
6569
6570 if (VIsual.col > len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006571 {
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00006572 VIsual.col = len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006573# ifdef FEAT_VIRTUALEDIT
6574 VIsual.coladd = 0;
6575# endif
6576 }
6577 }
6578#endif
6579 }
6580 }
6581 did_ai = FALSE;
6582#ifdef FEAT_SMARTINDENT
6583 did_si = FALSE;
6584 can_si = FALSE;
6585 can_si_back = FALSE;
6586#endif
6587
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006588 /* Set '[ and '] to the inserted text. When end_insert_pos is NULL we are
6589 * now in a different buffer. */
6590 if (end_insert_pos != NULL)
6591 {
6592 curbuf->b_op_start = Insstart;
6593 curbuf->b_op_end = *end_insert_pos;
6594 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006595}
6596
6597/*
6598 * Set the last inserted text to a single character.
6599 * Used for the replace command.
6600 */
6601 void
6602set_last_insert(c)
6603 int c;
6604{
6605 char_u *s;
6606
6607 vim_free(last_insert);
6608#ifdef FEAT_MBYTE
6609 last_insert = alloc(MB_MAXBYTES * 3 + 5);
6610#else
6611 last_insert = alloc(6);
6612#endif
6613 if (last_insert != NULL)
6614 {
6615 s = last_insert;
6616 /* Use the CTRL-V only when entering a special char */
6617 if (c < ' ' || c == DEL)
6618 *s++ = Ctrl_V;
6619 s = add_char2buf(c, s);
6620 *s++ = ESC;
6621 *s++ = NUL;
6622 last_insert_skip = 0;
6623 }
6624}
6625
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00006626#if defined(EXITFREE) || defined(PROTO)
6627 void
6628free_last_insert()
6629{
6630 vim_free(last_insert);
6631 last_insert = NULL;
Bram Moolenaare0ca7b22007-11-24 20:28:24 +00006632# ifdef FEAT_INS_EXPAND
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00006633 vim_free(compl_orig_text);
6634 compl_orig_text = NULL;
Bram Moolenaare0ca7b22007-11-24 20:28:24 +00006635# endif
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00006636}
6637#endif
6638
Bram Moolenaar071d4272004-06-13 20:20:40 +00006639/*
6640 * Add character "c" to buffer "s". Escape the special meaning of K_SPECIAL
6641 * and CSI. Handle multi-byte characters.
6642 * Returns a pointer to after the added bytes.
6643 */
6644 char_u *
6645add_char2buf(c, s)
6646 int c;
6647 char_u *s;
6648{
6649#ifdef FEAT_MBYTE
6650 char_u temp[MB_MAXBYTES];
6651 int i;
6652 int len;
6653
6654 len = (*mb_char2bytes)(c, temp);
6655 for (i = 0; i < len; ++i)
6656 {
6657 c = temp[i];
6658#endif
6659 /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */
6660 if (c == K_SPECIAL)
6661 {
6662 *s++ = K_SPECIAL;
6663 *s++ = KS_SPECIAL;
6664 *s++ = KE_FILLER;
6665 }
6666#ifdef FEAT_GUI
6667 else if (c == CSI)
6668 {
6669 *s++ = CSI;
6670 *s++ = KS_EXTRA;
6671 *s++ = (int)KE_CSI;
6672 }
6673#endif
6674 else
6675 *s++ = c;
6676#ifdef FEAT_MBYTE
6677 }
6678#endif
6679 return s;
6680}
6681
6682/*
6683 * move cursor to start of line
6684 * if flags & BL_WHITE move to first non-white
6685 * if flags & BL_SOL move to first non-white if startofline is set,
6686 * otherwise keep "curswant" column
6687 * if flags & BL_FIX don't leave the cursor on a NUL.
6688 */
6689 void
6690beginline(flags)
6691 int flags;
6692{
6693 if ((flags & BL_SOL) && !p_sol)
6694 coladvance(curwin->w_curswant);
6695 else
6696 {
6697 curwin->w_cursor.col = 0;
6698#ifdef FEAT_VIRTUALEDIT
6699 curwin->w_cursor.coladd = 0;
6700#endif
6701
6702 if (flags & (BL_WHITE | BL_SOL))
6703 {
6704 char_u *ptr;
6705
6706 for (ptr = ml_get_curline(); vim_iswhite(*ptr)
6707 && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
6708 ++curwin->w_cursor.col;
6709 }
6710 curwin->w_set_curswant = TRUE;
6711 }
6712}
6713
6714/*
6715 * oneright oneleft cursor_down cursor_up
6716 *
6717 * Move one char {right,left,down,up}.
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006718 * Doesn't move onto the NUL past the end of the line, unless it is allowed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006719 * Return OK when successful, FAIL when we hit a line of file boundary.
6720 */
6721
6722 int
6723oneright()
6724{
6725 char_u *ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006726 int l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006727
6728#ifdef FEAT_VIRTUALEDIT
6729 if (virtual_active())
6730 {
6731 pos_T prevpos = curwin->w_cursor;
6732
6733 /* Adjust for multi-wide char (excluding TAB) */
6734 ptr = ml_get_cursor();
6735 coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006736# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00006737 (*mb_ptr2char)(ptr)
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006738# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006739 *ptr
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006740# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006741 ))
6742 ? ptr2cells(ptr) : 1));
6743 curwin->w_set_curswant = TRUE;
6744 /* Return OK if the cursor moved, FAIL otherwise (at window edge). */
6745 return (prevpos.col != curwin->w_cursor.col
6746 || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL;
6747 }
6748#endif
6749
6750 ptr = ml_get_cursor();
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006751 if (*ptr == NUL)
6752 return FAIL; /* already at the very end */
6753
Bram Moolenaar071d4272004-06-13 20:20:40 +00006754#ifdef FEAT_MBYTE
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006755 if (has_mbyte)
6756 l = (*mb_ptr2len)(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006757 else
6758#endif
Bram Moolenaar2eb25da2006-03-16 21:43:34 +00006759 l = 1;
6760
6761 /* move "l" bytes right, but don't end up on the NUL, unless 'virtualedit'
6762 * contains "onemore". */
6763 if (ptr[l] == NUL
6764#ifdef FEAT_VIRTUALEDIT
6765 && (ve_flags & VE_ONEMORE) == 0
6766#endif
6767 )
6768 return FAIL;
6769 curwin->w_cursor.col += l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006770
6771 curwin->w_set_curswant = TRUE;
6772 return OK;
6773}
6774
6775 int
6776oneleft()
6777{
6778#ifdef FEAT_VIRTUALEDIT
6779 if (virtual_active())
6780 {
6781 int width;
6782 int v = getviscol();
6783
6784 if (v == 0)
6785 return FAIL;
6786
6787# ifdef FEAT_LINEBREAK
6788 /* We might get stuck on 'showbreak', skip over it. */
6789 width = 1;
6790 for (;;)
6791 {
6792 coladvance(v - width);
6793 /* getviscol() is slow, skip it when 'showbreak' is empty and
6794 * there are no multi-byte characters */
6795 if ((*p_sbr == NUL
6796# ifdef FEAT_MBYTE
6797 && !has_mbyte
6798# endif
6799 ) || getviscol() < v)
6800 break;
6801 ++width;
6802 }
6803# else
6804 coladvance(v - 1);
6805# endif
6806
6807 if (curwin->w_cursor.coladd == 1)
6808 {
6809 char_u *ptr;
6810
6811 /* Adjust for multi-wide char (not a TAB) */
6812 ptr = ml_get_cursor();
6813 if (*ptr != TAB && vim_isprintc(
6814# ifdef FEAT_MBYTE
6815 (*mb_ptr2char)(ptr)
6816# else
6817 *ptr
6818# endif
6819 ) && ptr2cells(ptr) > 1)
6820 curwin->w_cursor.coladd = 0;
6821 }
6822
6823 curwin->w_set_curswant = TRUE;
6824 return OK;
6825 }
6826#endif
6827
6828 if (curwin->w_cursor.col == 0)
6829 return FAIL;
6830
6831 curwin->w_set_curswant = TRUE;
6832 --curwin->w_cursor.col;
6833
6834#ifdef FEAT_MBYTE
6835 /* if the character on the left of the current cursor is a multi-byte
6836 * character, move to its first byte */
6837 if (has_mbyte)
6838 mb_adjust_cursor();
6839#endif
6840 return OK;
6841}
6842
6843 int
6844cursor_up(n, upd_topline)
6845 long n;
6846 int upd_topline; /* When TRUE: update topline */
6847{
6848 linenr_T lnum;
6849
6850 if (n > 0)
6851 {
6852 lnum = curwin->w_cursor.lnum;
Bram Moolenaar7c626922005-02-07 22:01:03 +00006853 /* This fails if the cursor is already in the first line or the count
6854 * is larger than the line number and '-' is in 'cpoptions' */
6855 if (lnum <= 1 || (n >= lnum && vim_strchr(p_cpo, CPO_MINUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006856 return FAIL;
6857 if (n >= lnum)
6858 lnum = 1;
6859 else
6860#ifdef FEAT_FOLDING
6861 if (hasAnyFolding(curwin))
6862 {
6863 /*
6864 * Count each sequence of folded lines as one logical line.
6865 */
6866 /* go to the the start of the current fold */
6867 (void)hasFolding(lnum, &lnum, NULL);
6868
6869 while (n--)
6870 {
6871 /* move up one line */
6872 --lnum;
6873 if (lnum <= 1)
6874 break;
6875 /* If we entered a fold, move to the beginning, unless in
6876 * Insert mode or when 'foldopen' contains "all": it will open
6877 * in a moment. */
6878 if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL)))
6879 (void)hasFolding(lnum, &lnum, NULL);
6880 }
6881 if (lnum < 1)
6882 lnum = 1;
6883 }
6884 else
6885#endif
6886 lnum -= n;
6887 curwin->w_cursor.lnum = lnum;
6888 }
6889
6890 /* try to advance to the column we want to be at */
6891 coladvance(curwin->w_curswant);
6892
6893 if (upd_topline)
6894 update_topline(); /* make sure curwin->w_topline is valid */
6895
6896 return OK;
6897}
6898
6899/*
6900 * Cursor down a number of logical lines.
6901 */
6902 int
6903cursor_down(n, upd_topline)
6904 long n;
6905 int upd_topline; /* When TRUE: update topline */
6906{
6907 linenr_T lnum;
6908
6909 if (n > 0)
6910 {
6911 lnum = curwin->w_cursor.lnum;
6912#ifdef FEAT_FOLDING
6913 /* Move to last line of fold, will fail if it's the end-of-file. */
6914 (void)hasFolding(lnum, NULL, &lnum);
6915#endif
Bram Moolenaar7c626922005-02-07 22:01:03 +00006916 /* This fails if the cursor is already in the last line or would move
6917 * beyound the last line and '-' is in 'cpoptions' */
6918 if (lnum >= curbuf->b_ml.ml_line_count
6919 || (lnum + n > curbuf->b_ml.ml_line_count
6920 && vim_strchr(p_cpo, CPO_MINUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006921 return FAIL;
6922 if (lnum + n >= curbuf->b_ml.ml_line_count)
6923 lnum = curbuf->b_ml.ml_line_count;
6924 else
6925#ifdef FEAT_FOLDING
6926 if (hasAnyFolding(curwin))
6927 {
6928 linenr_T last;
6929
6930 /* count each sequence of folded lines as one logical line */
6931 while (n--)
6932 {
6933 if (hasFolding(lnum, NULL, &last))
6934 lnum = last + 1;
6935 else
6936 ++lnum;
6937 if (lnum >= curbuf->b_ml.ml_line_count)
6938 break;
6939 }
6940 if (lnum > curbuf->b_ml.ml_line_count)
6941 lnum = curbuf->b_ml.ml_line_count;
6942 }
6943 else
6944#endif
6945 lnum += n;
6946 curwin->w_cursor.lnum = lnum;
6947 }
6948
6949 /* try to advance to the column we want to be at */
6950 coladvance(curwin->w_curswant);
6951
6952 if (upd_topline)
6953 update_topline(); /* make sure curwin->w_topline is valid */
6954
6955 return OK;
6956}
6957
6958/*
6959 * Stuff the last inserted text in the read buffer.
6960 * Last_insert actually is a copy of the redo buffer, so we
6961 * first have to remove the command.
6962 */
6963 int
6964stuff_inserted(c, count, no_esc)
6965 int c; /* Command character to be inserted */
6966 long count; /* Repeat this many times */
6967 int no_esc; /* Don't add an ESC at the end */
6968{
6969 char_u *esc_ptr;
6970 char_u *ptr;
6971 char_u *last_ptr;
6972 char_u last = NUL;
6973
6974 ptr = get_last_insert();
6975 if (ptr == NULL)
6976 {
6977 EMSG(_(e_noinstext));
6978 return FAIL;
6979 }
6980
6981 /* may want to stuff the command character, to start Insert mode */
6982 if (c != NUL)
6983 stuffcharReadbuff(c);
6984 if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
6985 *esc_ptr = NUL; /* remove the ESC */
6986
6987 /* when the last char is either "0" or "^" it will be quoted if no ESC
6988 * comes after it OR if it will inserted more than once and "ptr"
6989 * starts with ^D. -- Acevedo
6990 */
6991 last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
6992 if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
6993 && (no_esc || (*ptr == Ctrl_D && count > 1)))
6994 {
6995 last = *last_ptr;
6996 *last_ptr = NUL;
6997 }
6998
6999 do
7000 {
7001 stuffReadbuff(ptr);
7002 /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
7003 if (last)
7004 stuffReadbuff((char_u *)(last == '0'
7005 ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0")
7006 : IF_EB("\026^", CTRL_V_STR "^")));
7007 }
7008 while (--count > 0);
7009
7010 if (last)
7011 *last_ptr = last;
7012
7013 if (esc_ptr != NULL)
7014 *esc_ptr = ESC; /* put the ESC back */
7015
7016 /* may want to stuff a trailing ESC, to get out of Insert mode */
7017 if (!no_esc)
7018 stuffcharReadbuff(ESC);
7019
7020 return OK;
7021}
7022
7023 char_u *
7024get_last_insert()
7025{
7026 if (last_insert == NULL)
7027 return NULL;
7028 return last_insert + last_insert_skip;
7029}
7030
7031/*
7032 * Get last inserted string, and remove trailing <Esc>.
7033 * Returns pointer to allocated memory (must be freed) or NULL.
7034 */
7035 char_u *
7036get_last_insert_save()
7037{
7038 char_u *s;
7039 int len;
7040
7041 if (last_insert == NULL)
7042 return NULL;
7043 s = vim_strsave(last_insert + last_insert_skip);
7044 if (s != NULL)
7045 {
7046 len = (int)STRLEN(s);
7047 if (len > 0 && s[len - 1] == ESC) /* remove trailing ESC */
7048 s[len - 1] = NUL;
7049 }
7050 return s;
7051}
7052
7053/*
7054 * Check the word in front of the cursor for an abbreviation.
7055 * Called when the non-id character "c" has been entered.
7056 * When an abbreviation is recognized it is removed from the text and
7057 * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
7058 */
7059 static int
7060echeck_abbr(c)
7061 int c;
7062{
7063 /* Don't check for abbreviation in paste mode, when disabled and just
7064 * after moving around with cursor keys. */
7065 if (p_paste || no_abbr || arrow_used)
7066 return FALSE;
7067
7068 return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
7069 curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
7070}
7071
7072/*
7073 * replace-stack functions
7074 *
7075 * When replacing characters, the replaced characters are remembered for each
7076 * new character. This is used to re-insert the old text when backspacing.
7077 *
7078 * There is a NUL headed list of characters for each character that is
7079 * currently in the file after the insertion point. When BS is used, one NUL
7080 * headed list is put back for the deleted character.
7081 *
7082 * For a newline, there are two NUL headed lists. One contains the characters
7083 * that the NL replaced. The extra one stores the characters after the cursor
7084 * that were deleted (always white space).
7085 *
7086 * Replace_offset is normally 0, in which case replace_push will add a new
7087 * character at the end of the stack. If replace_offset is not 0, that many
7088 * characters will be left on the stack above the newly inserted character.
7089 */
7090
Bram Moolenaar6c0b44b2005-06-01 21:56:33 +00007091static char_u *replace_stack = NULL;
7092static long replace_stack_nr = 0; /* next entry in replace stack */
7093static long replace_stack_len = 0; /* max. number of entries */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007094
7095 void
7096replace_push(c)
7097 int c; /* character that is replaced (NUL is none) */
7098{
7099 char_u *p;
7100
7101 if (replace_stack_nr < replace_offset) /* nothing to do */
7102 return;
7103 if (replace_stack_len <= replace_stack_nr)
7104 {
7105 replace_stack_len += 50;
7106 p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
7107 if (p == NULL) /* out of memory */
7108 {
7109 replace_stack_len -= 50;
7110 return;
7111 }
7112 if (replace_stack != NULL)
7113 {
7114 mch_memmove(p, replace_stack,
7115 (size_t)(replace_stack_nr * sizeof(char_u)));
7116 vim_free(replace_stack);
7117 }
7118 replace_stack = p;
7119 }
7120 p = replace_stack + replace_stack_nr - replace_offset;
7121 if (replace_offset)
7122 mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
7123 *p = c;
7124 ++replace_stack_nr;
7125}
7126
Bram Moolenaar2c994e82008-01-02 16:49:36 +00007127#if defined(FEAT_MBYTE) || defined(PROTO)
7128/*
7129 * Push a character onto the replace stack. Handles a multi-byte character in
7130 * reverse byte order, so that the first byte is popped off first.
7131 * Return the number of bytes done (includes composing characters).
7132 */
7133 int
7134replace_push_mb(p)
7135 char_u *p;
7136{
7137 int l = (*mb_ptr2len)(p);
7138 int j;
7139
7140 for (j = l - 1; j >= 0; --j)
7141 replace_push(p[j]);
7142 return l;
7143}
7144#endif
7145
Bram Moolenaareb3593b2006-04-22 22:33:57 +00007146#if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00007147/*
7148 * call replace_push(c) with replace_offset set to the first NUL.
7149 */
7150 static void
7151replace_push_off(c)
7152 int c;
7153{
7154 char_u *p;
7155
7156 p = replace_stack + replace_stack_nr;
7157 for (replace_offset = 1; replace_offset < replace_stack_nr;
7158 ++replace_offset)
7159 if (*--p == NUL)
7160 break;
7161 replace_push(c);
7162 replace_offset = 0;
7163}
Bram Moolenaareb3593b2006-04-22 22:33:57 +00007164#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007165
7166/*
7167 * Pop one item from the replace stack.
7168 * return -1 if stack empty
7169 * return replaced character or NUL otherwise
7170 */
7171 static int
7172replace_pop()
7173{
7174 if (replace_stack_nr == 0)
7175 return -1;
7176 return (int)replace_stack[--replace_stack_nr];
7177}
7178
7179/*
7180 * Join the top two items on the replace stack. This removes to "off"'th NUL
7181 * encountered.
7182 */
7183 static void
7184replace_join(off)
7185 int off; /* offset for which NUL to remove */
7186{
7187 int i;
7188
7189 for (i = replace_stack_nr; --i >= 0; )
7190 if (replace_stack[i] == NUL && off-- <= 0)
7191 {
7192 --replace_stack_nr;
7193 mch_memmove(replace_stack + i, replace_stack + i + 1,
7194 (size_t)(replace_stack_nr - i));
7195 return;
7196 }
7197}
7198
7199/*
7200 * Pop bytes from the replace stack until a NUL is found, and insert them
7201 * before the cursor. Can only be used in REPLACE or VREPLACE mode.
7202 */
7203 static void
7204replace_pop_ins()
7205{
7206 int cc;
7207 int oldState = State;
7208
7209 State = NORMAL; /* don't want REPLACE here */
7210 while ((cc = replace_pop()) > 0)
7211 {
7212#ifdef FEAT_MBYTE
7213 mb_replace_pop_ins(cc);
7214#else
7215 ins_char(cc);
7216#endif
7217 dec_cursor();
7218 }
7219 State = oldState;
7220}
7221
7222#ifdef FEAT_MBYTE
7223/*
7224 * Insert bytes popped from the replace stack. "cc" is the first byte. If it
7225 * indicates a multi-byte char, pop the other bytes too.
7226 */
7227 static void
7228mb_replace_pop_ins(cc)
7229 int cc;
7230{
7231 int n;
7232 char_u buf[MB_MAXBYTES];
7233 int i;
7234 int c;
7235
7236 if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1)
7237 {
7238 buf[0] = cc;
7239 for (i = 1; i < n; ++i)
7240 buf[i] = replace_pop();
7241 ins_bytes_len(buf, n);
7242 }
7243 else
7244 ins_char(cc);
7245
7246 if (enc_utf8)
7247 /* Handle composing chars. */
7248 for (;;)
7249 {
7250 c = replace_pop();
7251 if (c == -1) /* stack empty */
7252 break;
7253 if ((n = MB_BYTE2LEN(c)) == 1)
7254 {
7255 /* Not a multi-byte char, put it back. */
7256 replace_push(c);
7257 break;
7258 }
7259 else
7260 {
7261 buf[0] = c;
7262 for (i = 1; i < n; ++i)
7263 buf[i] = replace_pop();
7264 if (utf_iscomposing(utf_ptr2char(buf)))
7265 ins_bytes_len(buf, n);
7266 else
7267 {
7268 /* Not a composing char, put it back. */
7269 for (i = n - 1; i >= 0; --i)
7270 replace_push(buf[i]);
7271 break;
7272 }
7273 }
7274 }
7275}
7276#endif
7277
7278/*
7279 * make the replace stack empty
7280 * (called when exiting replace mode)
7281 */
7282 static void
7283replace_flush()
7284{
7285 vim_free(replace_stack);
7286 replace_stack = NULL;
7287 replace_stack_len = 0;
7288 replace_stack_nr = 0;
7289}
7290
7291/*
7292 * Handle doing a BS for one character.
7293 * cc < 0: replace stack empty, just move cursor
7294 * cc == 0: character was inserted, delete it
7295 * cc > 0: character was replaced, put cc (first byte of original char) back
7296 * and check for more characters to be put back
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00007297 * When "limit_col" is >= 0, don't delete before this column. Matters when
7298 * using composing characters, use del_char_after_col() instead of del_char().
Bram Moolenaar071d4272004-06-13 20:20:40 +00007299 */
7300 static void
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00007301replace_do_bs(limit_col)
7302 int limit_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007303{
7304 int cc;
7305#ifdef FEAT_VREPLACE
7306 int orig_len = 0;
7307 int ins_len;
7308 int orig_vcols = 0;
7309 colnr_T start_vcol;
7310 char_u *p;
7311 int i;
7312 int vcol;
7313#endif
7314
7315 cc = replace_pop();
7316 if (cc > 0)
7317 {
7318#ifdef FEAT_VREPLACE
7319 if (State & VREPLACE_FLAG)
7320 {
7321 /* Get the number of screen cells used by the character we are
7322 * going to delete. */
7323 getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
7324 orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
7325 }
7326#endif
7327#ifdef FEAT_MBYTE
7328 if (has_mbyte)
7329 {
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00007330 (void)del_char_after_col(limit_col);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007331# ifdef FEAT_VREPLACE
7332 if (State & VREPLACE_FLAG)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007333 orig_len = (int)STRLEN(ml_get_cursor());
Bram Moolenaar071d4272004-06-13 20:20:40 +00007334# endif
7335 replace_push(cc);
7336 }
7337 else
7338#endif
7339 {
7340 pchar_cursor(cc);
7341#ifdef FEAT_VREPLACE
7342 if (State & VREPLACE_FLAG)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007343 orig_len = (int)STRLEN(ml_get_cursor()) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007344#endif
7345 }
7346 replace_pop_ins();
7347
7348#ifdef FEAT_VREPLACE
7349 if (State & VREPLACE_FLAG)
7350 {
7351 /* Get the number of screen cells used by the inserted characters */
7352 p = ml_get_cursor();
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007353 ins_len = (int)STRLEN(p) - orig_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007354 vcol = start_vcol;
7355 for (i = 0; i < ins_len; ++i)
7356 {
7357 vcol += chartabsize(p + i, vcol);
7358#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007359 i += (*mb_ptr2len)(p) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007360#endif
7361 }
7362 vcol -= start_vcol;
7363
7364 /* Delete spaces that were inserted after the cursor to keep the
7365 * text aligned. */
7366 curwin->w_cursor.col += ins_len;
7367 while (vcol > orig_vcols && gchar_cursor() == ' ')
7368 {
7369 del_char(FALSE);
7370 ++orig_vcols;
7371 }
7372 curwin->w_cursor.col -= ins_len;
7373 }
7374#endif
7375
7376 /* mark the buffer as changed and prepare for displaying */
7377 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
7378 }
7379 else if (cc == 0)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00007380 (void)del_char_after_col(limit_col);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007381}
7382
7383#ifdef FEAT_CINDENT
7384/*
7385 * Return TRUE if C-indenting is on.
7386 */
7387 static int
7388cindent_on()
7389{
7390 return (!p_paste && (curbuf->b_p_cin
7391# ifdef FEAT_EVAL
7392 || *curbuf->b_p_inde != NUL
7393# endif
7394 ));
7395}
7396#endif
7397
7398#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
7399/*
7400 * Re-indent the current line, based on the current contents of it and the
7401 * surrounding lines. Fixing the cursor position seems really easy -- I'm very
7402 * confused what all the part that handles Control-T is doing that I'm not.
7403 * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
7404 */
7405
7406 void
7407fixthisline(get_the_indent)
7408 int (*get_the_indent) __ARGS((void));
7409{
Bram Moolenaar21b17e72008-01-16 19:03:13 +00007410 change_indent(INDENT_SET, get_the_indent(), FALSE, 0, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007411 if (linewhite(curwin->w_cursor.lnum))
7412 did_ai = TRUE; /* delete the indent if the line stays empty */
7413}
7414
7415 void
7416fix_indent()
7417{
7418 if (p_paste)
7419 return;
7420# ifdef FEAT_LISP
7421 if (curbuf->b_p_lisp && curbuf->b_p_ai)
7422 fixthisline(get_lisp_indent);
7423# endif
7424# if defined(FEAT_LISP) && defined(FEAT_CINDENT)
7425 else
7426# endif
7427# ifdef FEAT_CINDENT
7428 if (cindent_on())
7429 do_c_expr_indent();
7430# endif
7431}
7432
7433#endif
7434
7435#ifdef FEAT_CINDENT
7436/*
7437 * return TRUE if 'cinkeys' contains the key "keytyped",
7438 * when == '*': Only if key is preceded with '*' (indent before insert)
7439 * when == '!': Only if key is prededed with '!' (don't insert)
7440 * when == ' ': Only if key is not preceded with '*'(indent afterwards)
7441 *
7442 * "keytyped" can have a few special values:
7443 * KEY_OPEN_FORW
7444 * KEY_OPEN_BACK
7445 * KEY_COMPLETE just finished completion.
7446 *
7447 * If line_is_empty is TRUE accept keys with '0' before them.
7448 */
7449 int
7450in_cinkeys(keytyped, when, line_is_empty)
7451 int keytyped;
7452 int when;
7453 int line_is_empty;
7454{
7455 char_u *look;
7456 int try_match;
7457 int try_match_word;
7458 char_u *p;
7459 char_u *line;
7460 int icase;
7461 int i;
7462
Bram Moolenaar30848942009-12-24 14:46:12 +00007463 if (keytyped == NUL)
7464 /* Can happen with CTRL-Y and CTRL-E on a short line. */
7465 return FALSE;
7466
Bram Moolenaar071d4272004-06-13 20:20:40 +00007467#ifdef FEAT_EVAL
7468 if (*curbuf->b_p_inde != NUL)
7469 look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */
7470 else
7471#endif
7472 look = curbuf->b_p_cink; /* 'indentexpr' empty: use 'cinkeys' */
7473 while (*look)
7474 {
7475 /*
7476 * Find out if we want to try a match with this key, depending on
7477 * 'when' and a '*' or '!' before the key.
7478 */
7479 switch (when)
7480 {
7481 case '*': try_match = (*look == '*'); break;
7482 case '!': try_match = (*look == '!'); break;
7483 default: try_match = (*look != '*'); break;
7484 }
7485 if (*look == '*' || *look == '!')
7486 ++look;
7487
7488 /*
7489 * If there is a '0', only accept a match if the line is empty.
7490 * But may still match when typing last char of a word.
7491 */
7492 if (*look == '0')
7493 {
7494 try_match_word = try_match;
7495 if (!line_is_empty)
7496 try_match = FALSE;
7497 ++look;
7498 }
7499 else
7500 try_match_word = FALSE;
7501
7502 /*
7503 * does it look like a control character?
7504 */
7505 if (*look == '^'
7506#ifdef EBCDIC
7507 && (Ctrl_chr(look[1]) != 0)
7508#else
7509 && look[1] >= '?' && look[1] <= '_'
7510#endif
7511 )
7512 {
7513 if (try_match && keytyped == Ctrl_chr(look[1]))
7514 return TRUE;
7515 look += 2;
7516 }
7517 /*
7518 * 'o' means "o" command, open forward.
7519 * 'O' means "O" command, open backward.
7520 */
7521 else if (*look == 'o')
7522 {
7523 if (try_match && keytyped == KEY_OPEN_FORW)
7524 return TRUE;
7525 ++look;
7526 }
7527 else if (*look == 'O')
7528 {
7529 if (try_match && keytyped == KEY_OPEN_BACK)
7530 return TRUE;
7531 ++look;
7532 }
7533
7534 /*
7535 * 'e' means to check for "else" at start of line and just before the
7536 * cursor.
7537 */
7538 else if (*look == 'e')
7539 {
7540 if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
7541 {
7542 p = ml_get_curline();
7543 if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
7544 STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
7545 return TRUE;
7546 }
7547 ++look;
7548 }
7549
7550 /*
7551 * ':' only causes an indent if it is at the end of a label or case
7552 * statement, or when it was before typing the ':' (to fix
7553 * class::method for C++).
7554 */
7555 else if (*look == ':')
7556 {
7557 if (try_match && keytyped == ':')
7558 {
7559 p = ml_get_curline();
Bram Moolenaar3acfc302010-07-11 17:23:02 +02007560 if (cin_iscase(p, FALSE) || cin_isscopedecl(p)
7561 || cin_islabel(30))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007562 return TRUE;
Bram Moolenaar30118152007-06-28 10:49:22 +00007563 /* Need to get the line again after cin_islabel(). */
7564 p = ml_get_curline();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007565 if (curwin->w_cursor.col > 2
7566 && p[curwin->w_cursor.col - 1] == ':'
7567 && p[curwin->w_cursor.col - 2] == ':')
7568 {
7569 p[curwin->w_cursor.col - 1] = ' ';
Bram Moolenaar3acfc302010-07-11 17:23:02 +02007570 i = (cin_iscase(p, FALSE) || cin_isscopedecl(p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007571 || cin_islabel(30));
7572 p = ml_get_curline();
7573 p[curwin->w_cursor.col - 1] = ':';
7574 if (i)
7575 return TRUE;
7576 }
7577 }
7578 ++look;
7579 }
7580
7581
7582 /*
7583 * Is it a key in <>, maybe?
7584 */
7585 else if (*look == '<')
7586 {
7587 if (try_match)
7588 {
7589 /*
7590 * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
7591 * <:> and <!> so that people can re-indent on o, O, e, 0, <,
7592 * >, *, : and ! keys if they really really want to.
7593 */
7594 if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
7595 && keytyped == look[1])
7596 return TRUE;
7597
7598 if (keytyped == get_special_key_code(look + 1))
7599 return TRUE;
7600 }
7601 while (*look && *look != '>')
7602 look++;
7603 while (*look == '>')
7604 look++;
7605 }
7606
7607 /*
7608 * Is it a word: "=word"?
7609 */
7610 else if (*look == '=' && look[1] != ',' && look[1] != NUL)
7611 {
7612 ++look;
7613 if (*look == '~')
7614 {
7615 icase = TRUE;
7616 ++look;
7617 }
7618 else
7619 icase = FALSE;
7620 p = vim_strchr(look, ',');
7621 if (p == NULL)
7622 p = look + STRLEN(look);
7623 if ((try_match || try_match_word)
7624 && curwin->w_cursor.col >= (colnr_T)(p - look))
7625 {
7626 int match = FALSE;
7627
7628#ifdef FEAT_INS_EXPAND
7629 if (keytyped == KEY_COMPLETE)
7630 {
7631 char_u *s;
7632
7633 /* Just completed a word, check if it starts with "look".
7634 * search back for the start of a word. */
7635 line = ml_get_curline();
7636# ifdef FEAT_MBYTE
7637 if (has_mbyte)
7638 {
7639 char_u *n;
7640
7641 for (s = line + curwin->w_cursor.col; s > line; s = n)
7642 {
7643 n = mb_prevptr(line, s);
7644 if (!vim_iswordp(n))
7645 break;
7646 }
7647 }
7648 else
7649# endif
7650 for (s = line + curwin->w_cursor.col; s > line; --s)
7651 if (!vim_iswordc(s[-1]))
7652 break;
7653 if (s + (p - look) <= line + curwin->w_cursor.col
7654 && (icase
7655 ? MB_STRNICMP(s, look, p - look)
7656 : STRNCMP(s, look, p - look)) == 0)
7657 match = TRUE;
7658 }
7659 else
7660#endif
7661 /* TODO: multi-byte */
7662 if (keytyped == (int)p[-1] || (icase && keytyped < 256
7663 && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
7664 {
7665 line = ml_get_cursor();
7666 if ((curwin->w_cursor.col == (colnr_T)(p - look)
7667 || !vim_iswordc(line[-(p - look) - 1]))
7668 && (icase
7669 ? MB_STRNICMP(line - (p - look), look, p - look)
7670 : STRNCMP(line - (p - look), look, p - look))
7671 == 0)
7672 match = TRUE;
7673 }
7674 if (match && try_match_word && !try_match)
7675 {
7676 /* "0=word": Check if there are only blanks before the
7677 * word. */
7678 line = ml_get_curline();
7679 if ((int)(skipwhite(line) - line) !=
7680 (int)(curwin->w_cursor.col - (p - look)))
7681 match = FALSE;
7682 }
7683 if (match)
7684 return TRUE;
7685 }
7686 look = p;
7687 }
7688
7689 /*
7690 * ok, it's a boring generic character.
7691 */
7692 else
7693 {
7694 if (try_match && *look == keytyped)
7695 return TRUE;
7696 ++look;
7697 }
7698
7699 /*
7700 * Skip over ", ".
7701 */
7702 look = skip_to_option_part(look);
7703 }
7704 return FALSE;
7705}
7706#endif /* FEAT_CINDENT */
7707
7708#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
7709/*
7710 * Map Hebrew keyboard when in hkmap mode.
7711 */
7712 int
7713hkmap(c)
7714 int c;
7715{
7716 if (p_hkmapp) /* phonetic mapping, by Ilya Dogolazky */
7717 {
7718 enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
7719 KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
7720 PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
7721 static char_u map[26] =
7722 {(char_u)hALEF/*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/,
7723 (char_u)DALET/*d*/, (char_u)-1 /*e*/, (char_u)PEIsofit/*f*/,
7724 (char_u)GIMEL/*g*/, (char_u)HEI /*h*/, (char_u)IUD /*i*/,
7725 (char_u)HET /*j*/, (char_u)KOF /*k*/, (char_u)LAMED /*l*/,
7726 (char_u)MEM /*m*/, (char_u)NUN /*n*/, (char_u)SAMEH /*o*/,
7727 (char_u)PEI /*p*/, (char_u)-1 /*q*/, (char_u)RESH /*r*/,
7728 (char_u)ZAIN /*s*/, (char_u)TAV /*t*/, (char_u)TET /*u*/,
7729 (char_u)VAV /*v*/, (char_u)hSHIN/*w*/, (char_u)-1 /*x*/,
7730 (char_u)AIN /*y*/, (char_u)ZADI /*z*/};
7731
7732 if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
7733 return (int)(map[CharOrd(c)] - 1 + p_aleph);
7734 /* '-1'='sofit' */
7735 else if (c == 'x')
7736 return 'X';
7737 else if (c == 'q')
7738 return '\''; /* {geresh}={'} */
7739 else if (c == 246)
7740 return ' '; /* \"o --> ' ' for a german keyboard */
7741 else if (c == 228)
7742 return ' '; /* \"a --> ' ' -- / -- */
7743 else if (c == 252)
7744 return ' '; /* \"u --> ' ' -- / -- */
7745#ifdef EBCDIC
7746 else if (islower(c))
7747#else
7748 /* NOTE: islower() does not do the right thing for us on Linux so we
7749 * do this the same was as 5.7 and previous, so it works correctly on
7750 * all systems. Specifically, the e.g. Delete and Arrow keys are
7751 * munged and won't work if e.g. searching for Hebrew text.
7752 */
7753 else if (c >= 'a' && c <= 'z')
7754#endif
7755 return (int)(map[CharOrdLow(c)] + p_aleph);
7756 else
7757 return c;
7758 }
7759 else
7760 {
7761 switch (c)
7762 {
7763 case '`': return ';';
7764 case '/': return '.';
7765 case '\'': return ',';
7766 case 'q': return '/';
7767 case 'w': return '\'';
7768
7769 /* Hebrew letters - set offset from 'a' */
7770 case ',': c = '{'; break;
7771 case '.': c = 'v'; break;
7772 case ';': c = 't'; break;
7773 default: {
7774 static char str[] = "zqbcxlsjphmkwonu ydafe rig";
7775
7776#ifdef EBCDIC
7777 /* see note about islower() above */
7778 if (!islower(c))
7779#else
7780 if (c < 'a' || c > 'z')
7781#endif
7782 return c;
7783 c = str[CharOrdLow(c)];
7784 break;
7785 }
7786 }
7787
7788 return (int)(CharOrdLow(c) + p_aleph);
7789 }
7790}
7791#endif
7792
7793 static void
7794ins_reg()
7795{
7796 int need_redraw = FALSE;
7797 int regname;
7798 int literally = 0;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007799#ifdef FEAT_VISUAL
7800 int vis_active = VIsual_active;
7801#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007802
7803 /*
7804 * If we are going to wait for a character, show a '"'.
7805 */
7806 pc_status = PC_STATUS_UNSET;
7807 if (redrawing() && !char_avail())
7808 {
7809 /* may need to redraw when no more chars available now */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007810 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007811
7812 edit_putchar('"', TRUE);
7813#ifdef FEAT_CMDL_INFO
7814 add_to_showcmd_c(Ctrl_R);
7815#endif
7816 }
7817
7818#ifdef USE_ON_FLY_SCROLL
7819 dont_scroll = TRUE; /* disallow scrolling here */
7820#endif
7821
7822 /*
7823 * Don't map the register name. This also prevents the mode message to be
7824 * deleted when ESC is hit.
7825 */
7826 ++no_mapping;
Bram Moolenaar61abfd12007-09-13 16:26:47 +00007827 regname = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007828 LANGMAP_ADJUST(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007829 if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P)
7830 {
7831 /* Get a third key for literal register insertion */
7832 literally = regname;
7833#ifdef FEAT_CMDL_INFO
7834 add_to_showcmd_c(literally);
7835#endif
Bram Moolenaar61abfd12007-09-13 16:26:47 +00007836 regname = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007837 LANGMAP_ADJUST(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007838 }
7839 --no_mapping;
7840
7841#ifdef FEAT_EVAL
7842 /*
7843 * Don't call u_sync() while getting the expression,
7844 * evaluating it or giving an error message for it!
7845 */
7846 ++no_u_sync;
7847 if (regname == '=')
7848 {
Bram Moolenaar8f999f12005-01-25 22:12:55 +00007849# ifdef USE_IM_CONTROL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007850 int im_on = im_get_status();
Bram Moolenaar8f999f12005-01-25 22:12:55 +00007851# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007852 regname = get_expr_register();
Bram Moolenaar8f999f12005-01-25 22:12:55 +00007853# ifdef USE_IM_CONTROL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007854 /* Restore the Input Method. */
7855 if (im_on)
7856 im_set_active(TRUE);
Bram Moolenaar8f999f12005-01-25 22:12:55 +00007857# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007858 }
Bram Moolenaar677ee682005-01-27 14:41:15 +00007859 if (regname == NUL || !valid_yank_reg(regname, FALSE))
7860 {
7861 vim_beep();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007862 need_redraw = TRUE; /* remove the '"' */
Bram Moolenaar677ee682005-01-27 14:41:15 +00007863 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007864 else
7865 {
7866#endif
7867 if (literally == Ctrl_O || literally == Ctrl_P)
7868 {
7869 /* Append the command to the redo buffer. */
7870 AppendCharToRedobuff(Ctrl_R);
7871 AppendCharToRedobuff(literally);
7872 AppendCharToRedobuff(regname);
7873
7874 do_put(regname, BACKWARD, 1L,
7875 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
7876 }
7877 else if (insert_reg(regname, literally) == FAIL)
7878 {
7879 vim_beep();
7880 need_redraw = TRUE; /* remove the '"' */
7881 }
Bram Moolenaar8f999f12005-01-25 22:12:55 +00007882 else if (stop_insert_mode)
7883 /* When the '=' register was used and a function was invoked that
7884 * did ":stopinsert" then stuff_empty() returns FALSE but we won't
7885 * insert anything, need to remove the '"' */
7886 need_redraw = TRUE;
7887
Bram Moolenaar071d4272004-06-13 20:20:40 +00007888#ifdef FEAT_EVAL
7889 }
7890 --no_u_sync;
7891#endif
7892#ifdef FEAT_CMDL_INFO
7893 clear_showcmd();
7894#endif
7895
7896 /* If the inserted register is empty, we need to remove the '"' */
7897 if (need_redraw || stuff_empty())
7898 edit_unputchar();
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007899
7900#ifdef FEAT_VISUAL
7901 /* Disallow starting Visual mode here, would get a weird mode. */
7902 if (!vis_active && VIsual_active)
7903 end_visual_mode();
7904#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007905}
7906
7907/*
7908 * CTRL-G commands in Insert mode.
7909 */
7910 static void
7911ins_ctrl_g()
7912{
7913 int c;
7914
7915#ifdef FEAT_INS_EXPAND
7916 /* Right after CTRL-X the cursor will be after the ruler. */
7917 setcursor();
7918#endif
7919
7920 /*
7921 * Don't map the second key. This also prevents the mode message to be
7922 * deleted when ESC is hit.
7923 */
7924 ++no_mapping;
Bram Moolenaar61abfd12007-09-13 16:26:47 +00007925 c = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007926 --no_mapping;
7927 switch (c)
7928 {
7929 /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
7930 case K_UP:
7931 case Ctrl_K:
7932 case 'k': ins_up(TRUE);
7933 break;
7934
7935 /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
7936 case K_DOWN:
7937 case Ctrl_J:
7938 case 'j': ins_down(TRUE);
7939 break;
7940
7941 /* CTRL-G u: start new undoable edit */
Bram Moolenaar779b74b2006-04-10 14:55:34 +00007942 case 'u': u_sync(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007943 ins_need_undo = TRUE;
Bram Moolenaara40ceaf2006-01-13 22:35:40 +00007944
7945 /* Need to reset Insstart, esp. because a BS that joins
Bram Moolenaar34e0bfa2007-05-10 18:44:18 +00007946 * a line to the previous one must save for undo. */
Bram Moolenaara40ceaf2006-01-13 22:35:40 +00007947 Insstart = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007948 break;
7949
7950 /* Unknown CTRL-G command, reserved for future expansion. */
7951 default: vim_beep();
7952 }
7953}
7954
7955/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007956 * CTRL-^ in Insert mode.
7957 */
7958 static void
7959ins_ctrl_hat()
7960{
Bram Moolenaar97b2ad32006-03-18 21:40:56 +00007961 if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE))
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007962 {
7963 /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
7964 if (State & LANGMAP)
7965 {
7966 curbuf->b_p_iminsert = B_IMODE_NONE;
7967 State &= ~LANGMAP;
7968 }
7969 else
7970 {
7971 curbuf->b_p_iminsert = B_IMODE_LMAP;
7972 State |= LANGMAP;
7973#ifdef USE_IM_CONTROL
7974 im_set_active(FALSE);
7975#endif
7976 }
7977 }
7978#ifdef USE_IM_CONTROL
7979 else
7980 {
7981 /* There are no ":lmap" mappings, toggle IM */
7982 if (im_get_status())
7983 {
7984 curbuf->b_p_iminsert = B_IMODE_NONE;
7985 im_set_active(FALSE);
7986 }
7987 else
7988 {
7989 curbuf->b_p_iminsert = B_IMODE_IM;
7990 State &= ~LANGMAP;
7991 im_set_active(TRUE);
7992 }
7993 }
7994#endif
7995 set_iminsert_global();
7996 showmode();
7997#ifdef FEAT_GUI
7998 /* may show different cursor shape or color */
7999 if (gui.in_use)
8000 gui_update_cursor(TRUE, FALSE);
8001#endif
8002#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
8003 /* Show/unshow value of 'keymap' in status lines. */
8004 status_redraw_curbuf();
8005#endif
8006}
8007
8008/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008009 * Handle ESC in insert mode.
8010 * Returns TRUE when leaving insert mode, FALSE when going to repeat the
8011 * insert.
8012 */
8013 static int
Bram Moolenaar488c6512005-08-11 20:09:58 +00008014ins_esc(count, cmdchar, nomove)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008015 long *count;
8016 int cmdchar;
Bram Moolenaar488c6512005-08-11 20:09:58 +00008017 int nomove; /* don't move cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008018{
8019 int temp;
8020 static int disabled_redraw = FALSE;
8021
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00008022#ifdef FEAT_SPELL
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008023 check_spell_redraw();
8024#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008025#if defined(FEAT_HANGULIN)
8026# if defined(ESC_CHG_TO_ENG_MODE)
8027 hangul_input_state_set(0);
8028# endif
8029 if (composing_hangul)
8030 {
8031 push_raw_key(composing_hangul_buffer, 2);
8032 composing_hangul = 0;
8033 }
8034#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008035
8036 temp = curwin->w_cursor.col;
8037 if (disabled_redraw)
8038 {
8039 --RedrawingDisabled;
8040 disabled_redraw = FALSE;
8041 }
8042 if (!arrow_used)
8043 {
8044 /*
8045 * Don't append the ESC for "r<CR>" and "grx".
Bram Moolenaar12805862005-01-05 22:16:17 +00008046 * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
8047 * when "count" is non-zero.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008048 */
8049 if (cmdchar != 'r' && cmdchar != 'v')
Bram Moolenaar12805862005-01-05 22:16:17 +00008050 AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008051
8052 /*
8053 * Repeating insert may take a long time. Check for
8054 * interrupt now and then.
8055 */
8056 if (*count > 0)
8057 {
8058 line_breakcheck();
8059 if (got_int)
8060 *count = 0;
8061 }
8062
8063 if (--*count > 0) /* repeat what was typed */
8064 {
Bram Moolenaar4399ef42005-02-12 14:29:27 +00008065 /* Vi repeats the insert without replacing characters. */
8066 if (vim_strchr(p_cpo, CPO_REPLCNT) != NULL)
8067 State &= ~REPLACE_FLAG;
8068
Bram Moolenaar071d4272004-06-13 20:20:40 +00008069 (void)start_redo_ins();
8070 if (cmdchar == 'r' || cmdchar == 'v')
8071 stuffReadbuff(ESC_STR); /* no ESC in redo buffer */
8072 ++RedrawingDisabled;
8073 disabled_redraw = TRUE;
8074 return FALSE; /* repeat the insert */
8075 }
8076 stop_insert(&curwin->w_cursor, TRUE);
8077 undisplay_dollar();
8078 }
8079
8080 /* When an autoindent was removed, curswant stays after the
8081 * indent */
8082 if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col)
8083 curwin->w_set_curswant = TRUE;
8084
8085 /* Remember the last Insert position in the '^ mark. */
8086 if (!cmdmod.keepjumps)
8087 curbuf->b_last_insert = curwin->w_cursor;
8088
8089 /*
8090 * The cursor should end up on the last inserted character.
Bram Moolenaar488c6512005-08-11 20:09:58 +00008091 * Don't do it for CTRL-O, unless past the end of the line.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008092 */
Bram Moolenaar488c6512005-08-11 20:09:58 +00008093 if (!nomove
8094 && (curwin->w_cursor.col != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00008095#ifdef FEAT_VIRTUALEDIT
8096 || curwin->w_cursor.coladd > 0
8097#endif
Bram Moolenaar488c6512005-08-11 20:09:58 +00008098 )
8099 && (restart_edit == NUL
8100 || (gchar_cursor() == NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008101#ifdef FEAT_VISUAL
Bram Moolenaar488c6512005-08-11 20:09:58 +00008102 && !VIsual_active
Bram Moolenaar071d4272004-06-13 20:20:40 +00008103#endif
Bram Moolenaar488c6512005-08-11 20:09:58 +00008104 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008105#ifdef FEAT_RIGHTLEFT
8106 && !revins_on
8107#endif
8108 )
8109 {
8110#ifdef FEAT_VIRTUALEDIT
8111 if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL)
8112 {
8113 oneleft();
8114 if (restart_edit != NUL)
8115 ++curwin->w_cursor.coladd;
8116 }
8117 else
8118#endif
8119 {
8120 --curwin->w_cursor.col;
8121#ifdef FEAT_MBYTE
8122 /* Correct cursor for multi-byte character. */
8123 if (has_mbyte)
8124 mb_adjust_cursor();
8125#endif
8126 }
8127 }
8128
8129#ifdef USE_IM_CONTROL
8130 /* Disable IM to allow typing English directly for Normal mode commands.
8131 * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
8132 * well). */
8133 if (!(State & LANGMAP))
8134 im_save_status(&curbuf->b_p_iminsert);
8135 im_set_active(FALSE);
8136#endif
8137
8138 State = NORMAL;
8139 /* need to position cursor again (e.g. when on a TAB ) */
8140 changed_cline_bef_curs();
8141
8142#ifdef FEAT_MOUSE
8143 setmouse();
8144#endif
8145#ifdef CURSOR_SHAPE
8146 ui_cursor_shape(); /* may show different cursor shape */
8147#endif
8148
8149 /*
8150 * When recording or for CTRL-O, need to display the new mode.
8151 * Otherwise remove the mode message.
8152 */
8153 if (Recording || restart_edit != NUL)
8154 showmode();
8155 else if (p_smd)
8156 MSG("");
8157
8158 return TRUE; /* exit Insert mode */
8159}
8160
8161#ifdef FEAT_RIGHTLEFT
8162/*
8163 * Toggle language: hkmap and revins_on.
8164 * Move to end of reverse inserted text.
8165 */
8166 static void
8167ins_ctrl_()
8168{
8169 if (revins_on && revins_chars && revins_scol >= 0)
8170 {
8171 while (gchar_cursor() != NUL && revins_chars--)
8172 ++curwin->w_cursor.col;
8173 }
8174 p_ri = !p_ri;
8175 revins_on = (State == INSERT && p_ri);
8176 if (revins_on)
8177 {
8178 revins_scol = curwin->w_cursor.col;
8179 revins_legal++;
8180 revins_chars = 0;
8181 undisplay_dollar();
8182 }
8183 else
8184 revins_scol = -1;
8185#ifdef FEAT_FKMAP
8186 if (p_altkeymap)
8187 {
8188 /*
8189 * to be consistent also for redo command, using '.'
8190 * set arrow_used to true and stop it - causing to redo
8191 * characters entered in one mode (normal/reverse insert).
8192 */
8193 arrow_used = TRUE;
8194 (void)stop_arrow();
8195 p_fkmap = curwin->w_p_rl ^ p_ri;
8196 if (p_fkmap && p_ri)
8197 State = INSERT;
8198 }
8199 else
8200#endif
8201 p_hkmap = curwin->w_p_rl ^ p_ri; /* be consistent! */
8202 showmode();
8203}
8204#endif
8205
8206#ifdef FEAT_VISUAL
8207/*
8208 * If 'keymodel' contains "startsel", may start selection.
8209 * Returns TRUE when a CTRL-O and other keys stuffed.
8210 */
8211 static int
8212ins_start_select(c)
8213 int c;
8214{
8215 if (km_startsel)
8216 switch (c)
8217 {
8218 case K_KHOME:
Bram Moolenaar071d4272004-06-13 20:20:40 +00008219 case K_KEND:
Bram Moolenaar071d4272004-06-13 20:20:40 +00008220 case K_PAGEUP:
8221 case K_KPAGEUP:
8222 case K_PAGEDOWN:
8223 case K_KPAGEDOWN:
8224# ifdef MACOS
8225 case K_LEFT:
8226 case K_RIGHT:
8227 case K_UP:
8228 case K_DOWN:
8229 case K_END:
8230 case K_HOME:
8231# endif
8232 if (!(mod_mask & MOD_MASK_SHIFT))
8233 break;
8234 /* FALLTHROUGH */
8235 case K_S_LEFT:
8236 case K_S_RIGHT:
8237 case K_S_UP:
8238 case K_S_DOWN:
8239 case K_S_END:
8240 case K_S_HOME:
8241 /* Start selection right away, the cursor can move with
8242 * CTRL-O when beyond the end of the line. */
8243 start_selection();
8244
8245 /* Execute the key in (insert) Select mode. */
8246 stuffcharReadbuff(Ctrl_O);
8247 if (mod_mask)
8248 {
8249 char_u buf[4];
8250
8251 buf[0] = K_SPECIAL;
8252 buf[1] = KS_MODIFIER;
8253 buf[2] = mod_mask;
8254 buf[3] = NUL;
8255 stuffReadbuff(buf);
8256 }
8257 stuffcharReadbuff(c);
8258 return TRUE;
8259 }
8260 return FALSE;
8261}
8262#endif
8263
8264/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008265 * <Insert> key in Insert mode: toggle insert/remplace mode.
8266 */
8267 static void
8268ins_insert(replaceState)
8269 int replaceState;
8270{
8271#ifdef FEAT_FKMAP
8272 if (p_fkmap && p_ri)
8273 {
8274 beep_flush();
8275 EMSG(farsi_text_3); /* encoded in Farsi */
8276 return;
8277 }
8278#endif
8279
8280#ifdef FEAT_AUTOCMD
Bram Moolenaar1e015462005-09-25 22:16:38 +00008281# ifdef FEAT_EVAL
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008282 set_vim_var_string(VV_INSERTMODE,
8283 (char_u *)((State & REPLACE_FLAG) ? "i" :
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00008284# ifdef FEAT_VREPLACE
8285 replaceState == VREPLACE ? "v" :
8286# endif
8287 "r"), 1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008288# endif
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008289 apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf);
8290#endif
8291 if (State & REPLACE_FLAG)
8292 State = INSERT | (State & LANGMAP);
8293 else
8294 State = replaceState | (State & LANGMAP);
8295 AppendCharToRedobuff(K_INS);
8296 showmode();
8297#ifdef CURSOR_SHAPE
8298 ui_cursor_shape(); /* may show different cursor shape */
8299#endif
8300}
8301
8302/*
8303 * Pressed CTRL-O in Insert mode.
8304 */
8305 static void
8306ins_ctrl_o()
8307{
8308#ifdef FEAT_VREPLACE
8309 if (State & VREPLACE_FLAG)
8310 restart_edit = 'V';
8311 else
8312#endif
8313 if (State & REPLACE_FLAG)
8314 restart_edit = 'R';
8315 else
8316 restart_edit = 'I';
8317#ifdef FEAT_VIRTUALEDIT
8318 if (virtual_active())
8319 ins_at_eol = FALSE; /* cursor always keeps its column */
8320 else
8321#endif
8322 ins_at_eol = (gchar_cursor() == NUL);
8323}
8324
8325/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008326 * If the cursor is on an indent, ^T/^D insert/delete one
8327 * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>".
Bram Moolenaar5b3e4602009-02-04 10:20:58 +00008328 * Always round the indent to 'shiftwidth', this is compatible
Bram Moolenaar071d4272004-06-13 20:20:40 +00008329 * with vi. But vi only supports ^T and ^D after an
8330 * autoindent, we support it everywhere.
8331 */
8332 static void
8333ins_shift(c, lastc)
8334 int c;
8335 int lastc;
8336{
8337 if (stop_arrow() == FAIL)
8338 return;
8339 AppendCharToRedobuff(c);
8340
8341 /*
8342 * 0^D and ^^D: remove all indent.
8343 */
Bram Moolenaar0cbac5b2007-07-29 13:03:35 +00008344 if (c == Ctrl_D && (lastc == '0' || lastc == '^')
8345 && curwin->w_cursor.col > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008346 {
8347 --curwin->w_cursor.col;
8348 (void)del_char(FALSE); /* delete the '^' or '0' */
8349 /* In Replace mode, restore the characters that '^' or '0' replaced. */
8350 if (State & REPLACE_FLAG)
8351 replace_pop_ins();
8352 if (lastc == '^')
8353 old_indent = get_indent(); /* remember curr. indent */
Bram Moolenaar21b17e72008-01-16 19:03:13 +00008354 change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008355 }
8356 else
Bram Moolenaar21b17e72008-01-16 19:03:13 +00008357 change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008358
8359 if (did_ai && *skipwhite(ml_get_curline()) != NUL)
8360 did_ai = FALSE;
8361#ifdef FEAT_SMARTINDENT
8362 did_si = FALSE;
8363 can_si = FALSE;
8364 can_si_back = FALSE;
8365#endif
8366#ifdef FEAT_CINDENT
8367 can_cindent = FALSE; /* no cindenting after ^D or ^T */
8368#endif
8369}
8370
8371 static void
8372ins_del()
8373{
8374 int temp;
8375
8376 if (stop_arrow() == FAIL)
8377 return;
8378 if (gchar_cursor() == NUL) /* delete newline */
8379 {
8380 temp = curwin->w_cursor.col;
8381 if (!can_bs(BS_EOL) /* only if "eol" included */
Bram Moolenaar893eaab2010-07-10 17:51:46 +02008382 || do_join(2, FALSE, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008383 vim_beep();
8384 else
8385 curwin->w_cursor.col = temp;
8386 }
8387 else if (del_char(FALSE) == FAIL) /* delete char under cursor */
8388 vim_beep();
8389 did_ai = FALSE;
8390#ifdef FEAT_SMARTINDENT
8391 did_si = FALSE;
8392 can_si = FALSE;
8393 can_si_back = FALSE;
8394#endif
8395 AppendCharToRedobuff(K_DEL);
8396}
8397
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008398static void ins_bs_one __ARGS((colnr_T *vcolp));
8399
8400/*
8401 * Delete one character for ins_bs().
8402 */
8403 static void
8404ins_bs_one(vcolp)
8405 colnr_T *vcolp;
8406{
8407 dec_cursor();
8408 getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
8409 if (State & REPLACE_FLAG)
8410 {
8411 /* Don't delete characters before the insert point when in
8412 * Replace mode */
8413 if (curwin->w_cursor.lnum != Insstart.lnum
8414 || curwin->w_cursor.col >= Insstart.col)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00008415 replace_do_bs(-1);
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008416 }
8417 else
8418 (void)del_char(FALSE);
8419}
8420
Bram Moolenaar071d4272004-06-13 20:20:40 +00008421/*
8422 * Handle Backspace, delete-word and delete-line in Insert mode.
8423 * Return TRUE when backspace was actually used.
8424 */
8425 static int
8426ins_bs(c, mode, inserted_space_p)
8427 int c;
8428 int mode;
8429 int *inserted_space_p;
8430{
8431 linenr_T lnum;
8432 int cc;
8433 int temp = 0; /* init for GCC */
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00008434 colnr_T save_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008435 colnr_T mincol;
8436 int did_backspace = FALSE;
8437 int in_indent;
8438 int oldState;
8439#ifdef FEAT_MBYTE
Bram Moolenaar362e1a32006-03-06 23:29:24 +00008440 int cpc[MAX_MCO]; /* composing characters */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008441#endif
8442
8443 /*
8444 * can't delete anything in an empty file
8445 * can't backup past first character in buffer
8446 * can't backup past starting point unless 'backspace' > 1
8447 * can backup to a previous line if 'backspace' == 0
8448 */
8449 if ( bufempty()
8450 || (
8451#ifdef FEAT_RIGHTLEFT
8452 !revins_on &&
8453#endif
8454 ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
8455 || (!can_bs(BS_START)
8456 && (arrow_used
8457 || (curwin->w_cursor.lnum == Insstart.lnum
8458 && curwin->w_cursor.col <= Insstart.col)))
8459 || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
8460 && curwin->w_cursor.col <= ai_col)
8461 || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0))))
8462 {
8463 vim_beep();
8464 return FALSE;
8465 }
8466
8467 if (stop_arrow() == FAIL)
8468 return FALSE;
8469 in_indent = inindent(0);
8470#ifdef FEAT_CINDENT
8471 if (in_indent)
8472 can_cindent = FALSE;
8473#endif
8474#ifdef FEAT_COMMENTS
8475 end_comment_pending = NUL; /* After BS, don't auto-end comment */
8476#endif
8477#ifdef FEAT_RIGHTLEFT
8478 if (revins_on) /* put cursor after last inserted char */
8479 inc_cursor();
8480#endif
8481
8482#ifdef FEAT_VIRTUALEDIT
8483 /* Virtualedit:
8484 * BACKSPACE_CHAR eats a virtual space
8485 * BACKSPACE_WORD eats all coladd
8486 * BACKSPACE_LINE eats all coladd and keeps going
8487 */
8488 if (curwin->w_cursor.coladd > 0)
8489 {
8490 if (mode == BACKSPACE_CHAR)
8491 {
8492 --curwin->w_cursor.coladd;
8493 return TRUE;
8494 }
8495 if (mode == BACKSPACE_WORD)
8496 {
8497 curwin->w_cursor.coladd = 0;
8498 return TRUE;
8499 }
8500 curwin->w_cursor.coladd = 0;
8501 }
8502#endif
8503
8504 /*
8505 * delete newline!
8506 */
8507 if (curwin->w_cursor.col == 0)
8508 {
8509 lnum = Insstart.lnum;
8510 if (curwin->w_cursor.lnum == Insstart.lnum
8511#ifdef FEAT_RIGHTLEFT
8512 || revins_on
8513#endif
8514 )
8515 {
8516 if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
8517 (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
8518 return FALSE;
8519 --Insstart.lnum;
8520 Insstart.col = MAXCOL;
8521 }
8522 /*
8523 * In replace mode:
8524 * cc < 0: NL was inserted, delete it
8525 * cc >= 0: NL was replaced, put original characters back
8526 */
8527 cc = -1;
8528 if (State & REPLACE_FLAG)
8529 cc = replace_pop(); /* returns -1 if NL was inserted */
8530 /*
8531 * In replace mode, in the line we started replacing, we only move the
8532 * cursor.
8533 */
8534 if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum)
8535 {
8536 dec_cursor();
8537 }
8538 else
8539 {
8540#ifdef FEAT_VREPLACE
8541 if (!(State & VREPLACE_FLAG)
8542 || curwin->w_cursor.lnum > orig_line_count)
8543#endif
8544 {
8545 temp = gchar_cursor(); /* remember current char */
8546 --curwin->w_cursor.lnum;
Bram Moolenaarc930a3c2005-05-20 21:27:20 +00008547
8548 /* When "aw" is in 'formatoptions' we must delete the space at
8549 * the end of the line, otherwise the line will be broken
8550 * again when auto-formatting. */
8551 if (has_format_option(FO_AUTO)
8552 && has_format_option(FO_WHITE_PAR))
8553 {
8554 char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum,
8555 TRUE);
8556 int len;
8557
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008558 len = (int)STRLEN(ptr);
Bram Moolenaarc930a3c2005-05-20 21:27:20 +00008559 if (len > 0 && ptr[len - 1] == ' ')
8560 ptr[len - 1] = NUL;
8561 }
8562
Bram Moolenaar893eaab2010-07-10 17:51:46 +02008563 (void)do_join(2, FALSE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008564 if (temp == NUL && gchar_cursor() != NUL)
8565 inc_cursor();
8566 }
8567#ifdef FEAT_VREPLACE
8568 else
8569 dec_cursor();
8570#endif
8571
8572 /*
8573 * In REPLACE mode we have to put back the text that was replaced
8574 * by the NL. On the replace stack is first a NUL-terminated
8575 * sequence of characters that were deleted and then the
8576 * characters that NL replaced.
8577 */
8578 if (State & REPLACE_FLAG)
8579 {
8580 /*
8581 * Do the next ins_char() in NORMAL state, to
8582 * prevent ins_char() from replacing characters and
8583 * avoiding showmatch().
8584 */
8585 oldState = State;
8586 State = NORMAL;
8587 /*
8588 * restore characters (blanks) deleted after cursor
8589 */
8590 while (cc > 0)
8591 {
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00008592 save_col = curwin->w_cursor.col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008593#ifdef FEAT_MBYTE
8594 mb_replace_pop_ins(cc);
8595#else
8596 ins_char(cc);
8597#endif
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00008598 curwin->w_cursor.col = save_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008599 cc = replace_pop();
8600 }
8601 /* restore the characters that NL replaced */
8602 replace_pop_ins();
8603 State = oldState;
8604 }
8605 }
8606 did_ai = FALSE;
8607 }
8608 else
8609 {
8610 /*
8611 * Delete character(s) before the cursor.
8612 */
8613#ifdef FEAT_RIGHTLEFT
8614 if (revins_on) /* put cursor on last inserted char */
8615 dec_cursor();
8616#endif
8617 mincol = 0;
8618 /* keep indent */
Bram Moolenaar9248e6e2007-03-08 12:10:13 +00008619 if (mode == BACKSPACE_LINE
8620 && (curbuf->b_p_ai
8621#ifdef FEAT_CINDENT
Bram Moolenaar97b98102009-11-17 16:41:01 +00008622 || cindent_on()
Bram Moolenaar9248e6e2007-03-08 12:10:13 +00008623#endif
8624 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008625#ifdef FEAT_RIGHTLEFT
8626 && !revins_on
8627#endif
8628 )
8629 {
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00008630 save_col = curwin->w_cursor.col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008631 beginline(BL_WHITE);
Bram Moolenaar76675562009-11-11 12:22:32 +00008632 if (curwin->w_cursor.col < save_col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008633 mincol = curwin->w_cursor.col;
Bram Moolenaar5fd0ca72009-05-13 16:56:33 +00008634 curwin->w_cursor.col = save_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008635 }
8636
8637 /*
8638 * Handle deleting one 'shiftwidth' or 'softtabstop'.
8639 */
8640 if ( mode == BACKSPACE_CHAR
8641 && ((p_sta && in_indent)
Bram Moolenaar280f1262006-01-30 00:14:18 +00008642 || (curbuf->b_p_sts != 0
Bram Moolenaar7b88a0e2008-01-09 09:14:13 +00008643 && curwin->w_cursor.col > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00008644 && (*(ml_get_cursor() - 1) == TAB
8645 || (*(ml_get_cursor() - 1) == ' '
8646 && (!*inserted_space_p
8647 || arrow_used))))))
8648 {
8649 int ts;
8650 colnr_T vcol;
8651 colnr_T want_vcol;
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008652 colnr_T start_vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008653
8654 *inserted_space_p = FALSE;
Bram Moolenaar280f1262006-01-30 00:14:18 +00008655 if (p_sta && in_indent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008656 ts = curbuf->b_p_sw;
8657 else
8658 ts = curbuf->b_p_sts;
8659 /* Compute the virtual column where we want to be. Since
8660 * 'showbreak' may get in the way, need to get the last column of
8661 * the previous character. */
8662 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008663 start_vcol = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008664 dec_cursor();
8665 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
8666 inc_cursor();
8667 want_vcol = (want_vcol / ts) * ts;
8668
8669 /* delete characters until we are at or before want_vcol */
8670 while (vcol > want_vcol
8671 && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008672 ins_bs_one(&vcol);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008673
8674 /* insert extra spaces until we are at want_vcol */
8675 while (vcol < want_vcol)
8676 {
8677 /* Remember the first char we inserted */
8678 if (curwin->w_cursor.lnum == Insstart.lnum
8679 && curwin->w_cursor.col < Insstart.col)
8680 Insstart.col = curwin->w_cursor.col;
8681
8682#ifdef FEAT_VREPLACE
8683 if (State & VREPLACE_FLAG)
8684 ins_char(' ');
8685 else
8686#endif
8687 {
8688 ins_str((char_u *)" ");
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008689 if ((State & REPLACE_FLAG))
8690 replace_push(NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008691 }
8692 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
8693 }
Bram Moolenaarf5dcf7c2007-12-09 19:26:44 +00008694
8695 /* If we are now back where we started delete one character. Can
8696 * happen when using 'sts' and 'linebreak'. */
8697 if (vcol >= start_vcol)
8698 ins_bs_one(&vcol);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008699 }
8700
8701 /*
8702 * Delete upto starting point, start of line or previous word.
8703 */
8704 else do
8705 {
8706#ifdef FEAT_RIGHTLEFT
8707 if (!revins_on) /* put cursor on char to be deleted */
8708#endif
8709 dec_cursor();
8710
8711 /* start of word? */
8712 if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor()))
8713 {
8714 mode = BACKSPACE_WORD_NOT_SPACE;
8715 temp = vim_iswordc(gchar_cursor());
8716 }
8717 /* end of word? */
8718 else if (mode == BACKSPACE_WORD_NOT_SPACE
8719 && (vim_isspace(cc = gchar_cursor())
8720 || vim_iswordc(cc) != temp))
8721 {
8722#ifdef FEAT_RIGHTLEFT
8723 if (!revins_on)
8724#endif
8725 inc_cursor();
8726#ifdef FEAT_RIGHTLEFT
8727 else if (State & REPLACE_FLAG)
8728 dec_cursor();
8729#endif
8730 break;
8731 }
8732 if (State & REPLACE_FLAG)
Bram Moolenaar0f6c9482009-01-13 11:29:48 +00008733 replace_do_bs(-1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008734 else
8735 {
8736#ifdef FEAT_MBYTE
8737 if (enc_utf8 && p_deco)
Bram Moolenaar362e1a32006-03-06 23:29:24 +00008738 (void)utfc_ptr2char(ml_get_cursor(), cpc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008739#endif
8740 (void)del_char(FALSE);
8741#ifdef FEAT_MBYTE
8742 /*
Bram Moolenaar362e1a32006-03-06 23:29:24 +00008743 * If there are combining characters and 'delcombine' is set
8744 * move the cursor back. Don't back up before the base
Bram Moolenaar071d4272004-06-13 20:20:40 +00008745 * character.
8746 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +00008747 if (enc_utf8 && p_deco && cpc[0] != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008748 inc_cursor();
8749#endif
8750#ifdef FEAT_RIGHTLEFT
8751 if (revins_chars)
8752 {
8753 revins_chars--;
8754 revins_legal++;
8755 }
8756 if (revins_on && gchar_cursor() == NUL)
8757 break;
8758#endif
8759 }
8760 /* Just a single backspace?: */
8761 if (mode == BACKSPACE_CHAR)
8762 break;
8763 } while (
8764#ifdef FEAT_RIGHTLEFT
8765 revins_on ||
8766#endif
8767 (curwin->w_cursor.col > mincol
8768 && (curwin->w_cursor.lnum != Insstart.lnum
8769 || curwin->w_cursor.col != Insstart.col)));
8770 did_backspace = TRUE;
8771 }
8772#ifdef FEAT_SMARTINDENT
8773 did_si = FALSE;
8774 can_si = FALSE;
8775 can_si_back = FALSE;
8776#endif
8777 if (curwin->w_cursor.col <= 1)
8778 did_ai = FALSE;
8779 /*
8780 * It's a little strange to put backspaces into the redo
8781 * buffer, but it makes auto-indent a lot easier to deal
8782 * with.
8783 */
8784 AppendCharToRedobuff(c);
8785
8786 /* If deleted before the insertion point, adjust it */
8787 if (curwin->w_cursor.lnum == Insstart.lnum
8788 && curwin->w_cursor.col < Insstart.col)
8789 Insstart.col = curwin->w_cursor.col;
8790
8791 /* vi behaviour: the cursor moves backward but the character that
8792 * was there remains visible
8793 * Vim behaviour: the cursor moves backward and the character that
8794 * was there is erased from the screen.
8795 * We can emulate the vi behaviour by pretending there is a dollar
8796 * displayed even when there isn't.
8797 * --pkv Sun Jan 19 01:56:40 EST 2003 */
8798 if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0)
8799 dollar_vcol = curwin->w_virtcol;
8800
Bram Moolenaarce3be472008-01-14 19:12:28 +00008801#ifdef FEAT_FOLDING
8802 /* When deleting a char the cursor line must never be in a closed fold.
8803 * E.g., when 'foldmethod' is indent and deleting the first non-white
8804 * char before a Tab. */
8805 if (did_backspace)
8806 foldOpenCursor();
8807#endif
8808
Bram Moolenaar071d4272004-06-13 20:20:40 +00008809 return did_backspace;
8810}
8811
8812#ifdef FEAT_MOUSE
8813 static void
8814ins_mouse(c)
8815 int c;
8816{
8817 pos_T tpos;
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008818 win_T *old_curwin = curwin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008819
8820# ifdef FEAT_GUI
8821 /* When GUI is active, also move/paste when 'mouse' is empty */
8822 if (!gui.in_use)
8823# endif
8824 if (!mouse_has(MOUSE_INSERT))
8825 return;
8826
8827 undisplay_dollar();
8828 tpos = curwin->w_cursor;
8829 if (do_mouse(NULL, c, BACKWARD, 1L, 0))
8830 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008831#ifdef FEAT_WINDOWS
8832 win_T *new_curwin = curwin;
8833
8834 if (curwin != old_curwin && win_valid(old_curwin))
8835 {
8836 /* Mouse took us to another window. We need to go back to the
8837 * previous one to stop insert there properly. */
8838 curwin = old_curwin;
8839 curbuf = curwin->w_buffer;
8840 }
8841#endif
8842 start_arrow(curwin == old_curwin ? &tpos : NULL);
8843#ifdef FEAT_WINDOWS
8844 if (curwin != new_curwin && win_valid(new_curwin))
8845 {
8846 curwin = new_curwin;
8847 curbuf = curwin->w_buffer;
8848 }
8849#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008850# ifdef FEAT_CINDENT
8851 can_cindent = TRUE;
8852# endif
8853 }
8854
8855#ifdef FEAT_WINDOWS
8856 /* redraw status lines (in case another window became active) */
8857 redraw_statuslines();
8858#endif
8859}
8860
8861 static void
8862ins_mousescroll(up)
8863 int up;
8864{
8865 pos_T tpos;
Bram Moolenaar9b25ffb2007-11-06 21:27:31 +00008866# if defined(FEAT_WINDOWS)
8867 win_T *old_curwin = curwin;
8868# endif
8869# ifdef FEAT_INS_EXPAND
8870 int did_scroll = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008871# endif
8872
8873 tpos = curwin->w_cursor;
8874
8875# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008876 /* Currently the mouse coordinates are only known in the GUI. */
8877 if (gui.in_use && mouse_row >= 0 && mouse_col >= 0)
8878 {
8879 int row, col;
8880
8881 row = mouse_row;
8882 col = mouse_col;
8883
8884 /* find the window at the pointer coordinates */
8885 curwin = mouse_find_win(&row, &col);
8886 curbuf = curwin->w_buffer;
8887 }
8888 if (curwin == old_curwin)
8889# endif
8890 undisplay_dollar();
8891
Bram Moolenaar9b25ffb2007-11-06 21:27:31 +00008892# ifdef FEAT_INS_EXPAND
8893 /* Don't scroll the window in which completion is being done. */
8894 if (!pum_visible()
8895# if defined(FEAT_WINDOWS)
8896 || curwin != old_curwin
8897# endif
8898 )
8899# endif
8900 {
8901 if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
8902 scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
8903 else
8904 scroll_redraw(up, 3L);
8905# ifdef FEAT_INS_EXPAND
8906 did_scroll = TRUE;
8907# endif
8908 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008909
8910# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
8911 curwin->w_redr_status = TRUE;
8912
8913 curwin = old_curwin;
8914 curbuf = curwin->w_buffer;
8915# endif
8916
Bram Moolenaar9b25ffb2007-11-06 21:27:31 +00008917# ifdef FEAT_INS_EXPAND
8918 /* The popup menu may overlay the window, need to redraw it.
8919 * TODO: Would be more efficient to only redraw the windows that are
8920 * overlapped by the popup menu. */
8921 if (pum_visible() && did_scroll)
8922 {
8923 redraw_all_later(NOT_VALID);
8924 ins_compl_show_pum();
8925 }
8926# endif
8927
Bram Moolenaar071d4272004-06-13 20:20:40 +00008928 if (!equalpos(curwin->w_cursor, tpos))
8929 {
8930 start_arrow(&tpos);
8931# ifdef FEAT_CINDENT
8932 can_cindent = TRUE;
8933# endif
8934 }
8935}
8936#endif
8937
Bram Moolenaara23ccb82006-02-27 00:08:02 +00008938#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
Bram Moolenaara94bc432006-03-10 21:42:59 +00008939 static void
Bram Moolenaara23ccb82006-02-27 00:08:02 +00008940ins_tabline(c)
8941 int c;
8942{
8943 /* We will be leaving the current window, unless closing another tab. */
8944 if (c != K_TABMENU || current_tabmenu != TABLINE_MENU_CLOSE
8945 || (current_tab != 0 && current_tab != tabpage_index(curtab)))
8946 {
8947 undisplay_dollar();
8948 start_arrow(&curwin->w_cursor);
8949# ifdef FEAT_CINDENT
8950 can_cindent = TRUE;
8951# endif
8952 }
8953
8954 if (c == K_TABLINE)
8955 goto_tabpage(current_tab);
8956 else
Bram Moolenaar437df8f2006-04-27 21:47:44 +00008957 {
Bram Moolenaara23ccb82006-02-27 00:08:02 +00008958 handle_tabmenu();
Bram Moolenaar437df8f2006-04-27 21:47:44 +00008959 redraw_statuslines(); /* will redraw the tabline when needed */
8960 }
Bram Moolenaara23ccb82006-02-27 00:08:02 +00008961}
8962#endif
8963
8964#if defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008965 void
8966ins_scroll()
8967{
8968 pos_T tpos;
8969
8970 undisplay_dollar();
8971 tpos = curwin->w_cursor;
8972 if (gui_do_scroll())
8973 {
8974 start_arrow(&tpos);
8975# ifdef FEAT_CINDENT
8976 can_cindent = TRUE;
8977# endif
8978 }
8979}
8980
8981 void
8982ins_horscroll()
8983{
8984 pos_T tpos;
8985
8986 undisplay_dollar();
8987 tpos = curwin->w_cursor;
8988 if (gui_do_horiz_scroll())
8989 {
8990 start_arrow(&tpos);
8991# ifdef FEAT_CINDENT
8992 can_cindent = TRUE;
8993# endif
8994 }
8995}
8996#endif
8997
8998 static void
8999ins_left()
9000{
9001 pos_T tpos;
9002
9003#ifdef FEAT_FOLDING
9004 if ((fdo_flags & FDO_HOR) && KeyTyped)
9005 foldOpenCursor();
9006#endif
9007 undisplay_dollar();
9008 tpos = curwin->w_cursor;
9009 if (oneleft() == OK)
9010 {
Bram Moolenaar39fecab2006-08-29 14:07:36 +00009011#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
9012 /* Only call start_arrow() when not busy with preediting, it will
9013 * break undo. K_LEFT is inserted in im_correct_cursor(). */
9014 if (!im_is_preediting())
9015#endif
9016 start_arrow(&tpos);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009017#ifdef FEAT_RIGHTLEFT
9018 /* If exit reversed string, position is fixed */
9019 if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
9020 revins_legal++;
9021 revins_chars++;
9022#endif
9023 }
9024
9025 /*
9026 * if 'whichwrap' set for cursor in insert mode may go to
9027 * previous line
9028 */
9029 else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
9030 {
9031 start_arrow(&tpos);
9032 --(curwin->w_cursor.lnum);
9033 coladvance((colnr_T)MAXCOL);
9034 curwin->w_set_curswant = TRUE; /* so we stay at the end */
9035 }
9036 else
9037 vim_beep();
9038}
9039
9040 static void
9041ins_home(c)
9042 int c;
9043{
9044 pos_T tpos;
9045
9046#ifdef FEAT_FOLDING
9047 if ((fdo_flags & FDO_HOR) && KeyTyped)
9048 foldOpenCursor();
9049#endif
9050 undisplay_dollar();
9051 tpos = curwin->w_cursor;
9052 if (c == K_C_HOME)
9053 curwin->w_cursor.lnum = 1;
9054 curwin->w_cursor.col = 0;
9055#ifdef FEAT_VIRTUALEDIT
9056 curwin->w_cursor.coladd = 0;
9057#endif
9058 curwin->w_curswant = 0;
9059 start_arrow(&tpos);
9060}
9061
9062 static void
9063ins_end(c)
9064 int c;
9065{
9066 pos_T tpos;
9067
9068#ifdef FEAT_FOLDING
9069 if ((fdo_flags & FDO_HOR) && KeyTyped)
9070 foldOpenCursor();
9071#endif
9072 undisplay_dollar();
9073 tpos = curwin->w_cursor;
9074 if (c == K_C_END)
9075 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
9076 coladvance((colnr_T)MAXCOL);
9077 curwin->w_curswant = MAXCOL;
9078
9079 start_arrow(&tpos);
9080}
9081
9082 static void
9083ins_s_left()
9084{
9085#ifdef FEAT_FOLDING
9086 if ((fdo_flags & FDO_HOR) && KeyTyped)
9087 foldOpenCursor();
9088#endif
9089 undisplay_dollar();
9090 if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
9091 {
9092 start_arrow(&curwin->w_cursor);
9093 (void)bck_word(1L, FALSE, FALSE);
9094 curwin->w_set_curswant = TRUE;
9095 }
9096 else
9097 vim_beep();
9098}
9099
9100 static void
9101ins_right()
9102{
9103#ifdef FEAT_FOLDING
9104 if ((fdo_flags & FDO_HOR) && KeyTyped)
9105 foldOpenCursor();
9106#endif
9107 undisplay_dollar();
Bram Moolenaar78a15312009-05-15 19:33:18 +00009108 if (gchar_cursor() != NUL
9109#ifdef FEAT_VIRTUALEDIT
9110 || virtual_active()
9111#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009112 )
9113 {
9114 start_arrow(&curwin->w_cursor);
9115 curwin->w_set_curswant = TRUE;
9116#ifdef FEAT_VIRTUALEDIT
9117 if (virtual_active())
9118 oneright();
9119 else
9120#endif
9121 {
9122#ifdef FEAT_MBYTE
9123 if (has_mbyte)
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009124 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor());
Bram Moolenaar071d4272004-06-13 20:20:40 +00009125 else
9126#endif
9127 ++curwin->w_cursor.col;
9128 }
9129
9130#ifdef FEAT_RIGHTLEFT
9131 revins_legal++;
9132 if (revins_chars)
9133 revins_chars--;
9134#endif
9135 }
9136 /* if 'whichwrap' set for cursor in insert mode, may move the
9137 * cursor to the next line */
9138 else if (vim_strchr(p_ww, ']') != NULL
9139 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
9140 {
9141 start_arrow(&curwin->w_cursor);
9142 curwin->w_set_curswant = TRUE;
9143 ++curwin->w_cursor.lnum;
9144 curwin->w_cursor.col = 0;
9145 }
9146 else
9147 vim_beep();
9148}
9149
9150 static void
9151ins_s_right()
9152{
9153#ifdef FEAT_FOLDING
9154 if ((fdo_flags & FDO_HOR) && KeyTyped)
9155 foldOpenCursor();
9156#endif
9157 undisplay_dollar();
9158 if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
9159 || gchar_cursor() != NUL)
9160 {
9161 start_arrow(&curwin->w_cursor);
9162 (void)fwd_word(1L, FALSE, 0);
9163 curwin->w_set_curswant = TRUE;
9164 }
9165 else
9166 vim_beep();
9167}
9168
9169 static void
9170ins_up(startcol)
9171 int startcol; /* when TRUE move to Insstart.col */
9172{
9173 pos_T tpos;
9174 linenr_T old_topline = curwin->w_topline;
9175#ifdef FEAT_DIFF
9176 int old_topfill = curwin->w_topfill;
9177#endif
9178
9179 undisplay_dollar();
9180 tpos = curwin->w_cursor;
9181 if (cursor_up(1L, TRUE) == OK)
9182 {
9183 if (startcol)
9184 coladvance(getvcol_nolist(&Insstart));
9185 if (old_topline != curwin->w_topline
9186#ifdef FEAT_DIFF
9187 || old_topfill != curwin->w_topfill
9188#endif
9189 )
9190 redraw_later(VALID);
9191 start_arrow(&tpos);
9192#ifdef FEAT_CINDENT
9193 can_cindent = TRUE;
9194#endif
9195 }
9196 else
9197 vim_beep();
9198}
9199
9200 static void
9201ins_pageup()
9202{
9203 pos_T tpos;
9204
9205 undisplay_dollar();
Bram Moolenaar7fc904b2006-04-13 20:37:35 +00009206
9207#ifdef FEAT_WINDOWS
9208 if (mod_mask & MOD_MASK_CTRL)
9209 {
9210 /* <C-PageUp>: tab page back */
Bram Moolenaarbc444822006-10-17 11:37:50 +00009211 if (first_tabpage->tp_next != NULL)
9212 {
9213 start_arrow(&curwin->w_cursor);
9214 goto_tabpage(-1);
9215 }
Bram Moolenaar7fc904b2006-04-13 20:37:35 +00009216 return;
9217 }
9218#endif
9219
Bram Moolenaar071d4272004-06-13 20:20:40 +00009220 tpos = curwin->w_cursor;
9221 if (onepage(BACKWARD, 1L) == OK)
9222 {
9223 start_arrow(&tpos);
9224#ifdef FEAT_CINDENT
9225 can_cindent = TRUE;
9226#endif
9227 }
9228 else
9229 vim_beep();
9230}
9231
9232 static void
9233ins_down(startcol)
9234 int startcol; /* when TRUE move to Insstart.col */
9235{
9236 pos_T tpos;
9237 linenr_T old_topline = curwin->w_topline;
9238#ifdef FEAT_DIFF
9239 int old_topfill = curwin->w_topfill;
9240#endif
9241
9242 undisplay_dollar();
9243 tpos = curwin->w_cursor;
9244 if (cursor_down(1L, TRUE) == OK)
9245 {
9246 if (startcol)
9247 coladvance(getvcol_nolist(&Insstart));
9248 if (old_topline != curwin->w_topline
9249#ifdef FEAT_DIFF
9250 || old_topfill != curwin->w_topfill
9251#endif
9252 )
9253 redraw_later(VALID);
9254 start_arrow(&tpos);
9255#ifdef FEAT_CINDENT
9256 can_cindent = TRUE;
9257#endif
9258 }
9259 else
9260 vim_beep();
9261}
9262
9263 static void
9264ins_pagedown()
9265{
9266 pos_T tpos;
9267
9268 undisplay_dollar();
Bram Moolenaar7fc904b2006-04-13 20:37:35 +00009269
9270#ifdef FEAT_WINDOWS
9271 if (mod_mask & MOD_MASK_CTRL)
9272 {
9273 /* <C-PageDown>: tab page forward */
Bram Moolenaarbc444822006-10-17 11:37:50 +00009274 if (first_tabpage->tp_next != NULL)
9275 {
9276 start_arrow(&curwin->w_cursor);
9277 goto_tabpage(0);
9278 }
Bram Moolenaar7fc904b2006-04-13 20:37:35 +00009279 return;
9280 }
9281#endif
9282
Bram Moolenaar071d4272004-06-13 20:20:40 +00009283 tpos = curwin->w_cursor;
9284 if (onepage(FORWARD, 1L) == OK)
9285 {
9286 start_arrow(&tpos);
9287#ifdef FEAT_CINDENT
9288 can_cindent = TRUE;
9289#endif
9290 }
9291 else
9292 vim_beep();
9293}
9294
9295#ifdef FEAT_DND
9296 static void
9297ins_drop()
9298{
9299 do_put('~', BACKWARD, 1L, PUT_CURSEND);
9300}
9301#endif
9302
9303/*
9304 * Handle TAB in Insert or Replace mode.
9305 * Return TRUE when the TAB needs to be inserted like a normal character.
9306 */
9307 static int
9308ins_tab()
9309{
9310 int ind;
9311 int i;
9312 int temp;
9313
9314 if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
9315 Insstart_blank_vcol = get_nolist_virtcol();
9316 if (echeck_abbr(TAB + ABBR_OFF))
9317 return FALSE;
9318
9319 ind = inindent(0);
9320#ifdef FEAT_CINDENT
9321 if (ind)
9322 can_cindent = FALSE;
9323#endif
9324
9325 /*
9326 * When nothing special, insert TAB like a normal character
9327 */
9328 if (!curbuf->b_p_et
9329 && !(p_sta && ind && curbuf->b_p_ts != curbuf->b_p_sw)
9330 && curbuf->b_p_sts == 0)
9331 return TRUE;
9332
9333 if (stop_arrow() == FAIL)
9334 return TRUE;
9335
9336 did_ai = FALSE;
9337#ifdef FEAT_SMARTINDENT
9338 did_si = FALSE;
9339 can_si = FALSE;
9340 can_si_back = FALSE;
9341#endif
9342 AppendToRedobuff((char_u *)"\t");
9343
9344 if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */
9345 temp = (int)curbuf->b_p_sw;
9346 else if (curbuf->b_p_sts > 0) /* use 'softtabstop' when set */
9347 temp = (int)curbuf->b_p_sts;
9348 else /* otherwise use 'tabstop' */
9349 temp = (int)curbuf->b_p_ts;
9350 temp -= get_nolist_virtcol() % temp;
9351
9352 /*
9353 * Insert the first space with ins_char(). It will delete one char in
9354 * replace mode. Insert the rest with ins_str(); it will not delete any
9355 * chars. For VREPLACE mode, we use ins_char() for all characters.
9356 */
9357 ins_char(' ');
9358 while (--temp > 0)
9359 {
9360#ifdef FEAT_VREPLACE
9361 if (State & VREPLACE_FLAG)
9362 ins_char(' ');
9363 else
9364#endif
9365 {
9366 ins_str((char_u *)" ");
9367 if (State & REPLACE_FLAG) /* no char replaced */
9368 replace_push(NUL);
9369 }
9370 }
9371
9372 /*
9373 * When 'expandtab' not set: Replace spaces by TABs where possible.
9374 */
9375 if (!curbuf->b_p_et && (curbuf->b_p_sts || (p_sta && ind)))
9376 {
9377 char_u *ptr;
9378#ifdef FEAT_VREPLACE
9379 char_u *saved_line = NULL; /* init for GCC */
9380 pos_T pos;
9381#endif
9382 pos_T fpos;
9383 pos_T *cursor;
9384 colnr_T want_vcol, vcol;
9385 int change_col = -1;
9386 int save_list = curwin->w_p_list;
9387
9388 /*
9389 * Get the current line. For VREPLACE mode, don't make real changes
9390 * yet, just work on a copy of the line.
9391 */
9392#ifdef FEAT_VREPLACE
9393 if (State & VREPLACE_FLAG)
9394 {
9395 pos = curwin->w_cursor;
9396 cursor = &pos;
9397 saved_line = vim_strsave(ml_get_curline());
9398 if (saved_line == NULL)
9399 return FALSE;
9400 ptr = saved_line + pos.col;
9401 }
9402 else
9403#endif
9404 {
9405 ptr = ml_get_cursor();
9406 cursor = &curwin->w_cursor;
9407 }
9408
9409 /* When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. */
9410 if (vim_strchr(p_cpo, CPO_LISTWM) == NULL)
9411 curwin->w_p_list = FALSE;
9412
9413 /* Find first white before the cursor */
9414 fpos = curwin->w_cursor;
9415 while (fpos.col > 0 && vim_iswhite(ptr[-1]))
9416 {
9417 --fpos.col;
9418 --ptr;
9419 }
9420
9421 /* In Replace mode, don't change characters before the insert point. */
9422 if ((State & REPLACE_FLAG)
9423 && fpos.lnum == Insstart.lnum
9424 && fpos.col < Insstart.col)
9425 {
9426 ptr += Insstart.col - fpos.col;
9427 fpos.col = Insstart.col;
9428 }
9429
9430 /* compute virtual column numbers of first white and cursor */
9431 getvcol(curwin, &fpos, &vcol, NULL, NULL);
9432 getvcol(curwin, cursor, &want_vcol, NULL, NULL);
9433
9434 /* Use as many TABs as possible. Beware of 'showbreak' and
9435 * 'linebreak' adding extra virtual columns. */
9436 while (vim_iswhite(*ptr))
9437 {
9438 i = lbr_chartabsize((char_u *)"\t", vcol);
9439 if (vcol + i > want_vcol)
9440 break;
9441 if (*ptr != TAB)
9442 {
9443 *ptr = TAB;
9444 if (change_col < 0)
9445 {
9446 change_col = fpos.col; /* Column of first change */
9447 /* May have to adjust Insstart */
9448 if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col)
9449 Insstart.col = fpos.col;
9450 }
9451 }
9452 ++fpos.col;
9453 ++ptr;
9454 vcol += i;
9455 }
9456
9457 if (change_col >= 0)
9458 {
9459 int repl_off = 0;
9460
9461 /* Skip over the spaces we need. */
9462 while (vcol < want_vcol && *ptr == ' ')
9463 {
9464 vcol += lbr_chartabsize(ptr, vcol);
9465 ++ptr;
9466 ++repl_off;
9467 }
9468 if (vcol > want_vcol)
9469 {
9470 /* Must have a char with 'showbreak' just before it. */
9471 --ptr;
9472 --repl_off;
9473 }
9474 fpos.col += repl_off;
9475
9476 /* Delete following spaces. */
9477 i = cursor->col - fpos.col;
9478 if (i > 0)
9479 {
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00009480 STRMOVE(ptr, ptr + i);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009481 /* correct replace stack. */
9482 if ((State & REPLACE_FLAG)
9483#ifdef FEAT_VREPLACE
9484 && !(State & VREPLACE_FLAG)
9485#endif
9486 )
9487 for (temp = i; --temp >= 0; )
9488 replace_join(repl_off);
9489 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00009490#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02009491 if (netbeans_active())
Bram Moolenaar009b2592004-10-24 19:18:58 +00009492 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02009493 netbeans_removed(curbuf, fpos.lnum, cursor->col, (long)(i + 1));
Bram Moolenaar009b2592004-10-24 19:18:58 +00009494 netbeans_inserted(curbuf, fpos.lnum, cursor->col,
9495 (char_u *)"\t", 1);
9496 }
9497#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009498 cursor->col -= i;
9499
9500#ifdef FEAT_VREPLACE
9501 /*
9502 * In VREPLACE mode, we haven't changed anything yet. Do it now by
9503 * backspacing over the changed spacing and then inserting the new
9504 * spacing.
9505 */
9506 if (State & VREPLACE_FLAG)
9507 {
9508 /* Backspace from real cursor to change_col */
9509 backspace_until_column(change_col);
9510
9511 /* Insert each char in saved_line from changed_col to
9512 * ptr-cursor */
9513 ins_bytes_len(saved_line + change_col,
9514 cursor->col - change_col);
9515 }
9516#endif
9517 }
9518
9519#ifdef FEAT_VREPLACE
9520 if (State & VREPLACE_FLAG)
9521 vim_free(saved_line);
9522#endif
9523 curwin->w_p_list = save_list;
9524 }
9525
9526 return FALSE;
9527}
9528
9529/*
9530 * Handle CR or NL in insert mode.
9531 * Return TRUE when out of memory or can't undo.
9532 */
9533 static int
9534ins_eol(c)
9535 int c;
9536{
9537 int i;
9538
9539 if (echeck_abbr(c + ABBR_OFF))
9540 return FALSE;
9541 if (stop_arrow() == FAIL)
9542 return TRUE;
9543 undisplay_dollar();
9544
9545 /*
9546 * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
9547 * character under the cursor. Only push a NUL on the replace stack,
9548 * nothing to put back when the NL is deleted.
9549 */
9550 if ((State & REPLACE_FLAG)
9551#ifdef FEAT_VREPLACE
9552 && !(State & VREPLACE_FLAG)
9553#endif
9554 )
9555 replace_push(NUL);
9556
9557 /*
9558 * In VREPLACE mode, a NL replaces the rest of the line, and starts
9559 * replacing the next line, so we push all of the characters left on the
9560 * line onto the replace stack. This is not done here though, it is done
9561 * in open_line().
9562 */
9563
Bram Moolenaarf193fff2006-04-27 00:02:13 +00009564#ifdef FEAT_VIRTUALEDIT
9565 /* Put cursor on NUL if on the last char and coladd is 1 (happens after
9566 * CTRL-O). */
9567 if (virtual_active() && curwin->w_cursor.coladd > 0)
9568 coladvance(getviscol());
9569#endif
9570
Bram Moolenaar071d4272004-06-13 20:20:40 +00009571#ifdef FEAT_RIGHTLEFT
9572# ifdef FEAT_FKMAP
9573 if (p_altkeymap && p_fkmap)
9574 fkmap(NL);
9575# endif
9576 /* NL in reverse insert will always start in the end of
9577 * current line. */
9578 if (revins_on)
9579 curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
9580#endif
9581
9582 AppendToRedobuff(NL_STR);
9583 i = open_line(FORWARD,
9584#ifdef FEAT_COMMENTS
9585 has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
9586#endif
9587 0, old_indent);
9588 old_indent = 0;
9589#ifdef FEAT_CINDENT
9590 can_cindent = TRUE;
9591#endif
Bram Moolenaar6ae133b2006-11-01 20:25:45 +00009592#ifdef FEAT_FOLDING
9593 /* When inserting a line the cursor line must never be in a closed fold. */
9594 foldOpenCursor();
9595#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009596
9597 return (!i);
9598}
9599
9600#ifdef FEAT_DIGRAPHS
9601/*
9602 * Handle digraph in insert mode.
9603 * Returns character still to be inserted, or NUL when nothing remaining to be
9604 * done.
9605 */
9606 static int
9607ins_digraph()
9608{
9609 int c;
9610 int cc;
9611
9612 pc_status = PC_STATUS_UNSET;
9613 if (redrawing() && !char_avail())
9614 {
9615 /* may need to redraw when no more chars available now */
Bram Moolenaar754b5602006-02-09 23:53:20 +00009616 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009617
9618 edit_putchar('?', TRUE);
9619#ifdef FEAT_CMDL_INFO
9620 add_to_showcmd_c(Ctrl_K);
9621#endif
9622 }
9623
9624#ifdef USE_ON_FLY_SCROLL
9625 dont_scroll = TRUE; /* disallow scrolling here */
9626#endif
9627
9628 /* don't map the digraph chars. This also prevents the
9629 * mode message to be deleted when ESC is hit */
9630 ++no_mapping;
9631 ++allow_keys;
Bram Moolenaar61abfd12007-09-13 16:26:47 +00009632 c = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009633 --no_mapping;
9634 --allow_keys;
Bram Moolenaar26dcc7e2010-07-14 22:35:55 +02009635 edit_unputchar(); /* when line fits in 'columns' the '?' is at the start
9636 of the next line and will not be redrawn */
9637
Bram Moolenaar071d4272004-06-13 20:20:40 +00009638 if (IS_SPECIAL(c) || mod_mask) /* special key */
9639 {
9640#ifdef FEAT_CMDL_INFO
9641 clear_showcmd();
9642#endif
9643 insert_special(c, TRUE, FALSE);
9644 return NUL;
9645 }
9646 if (c != ESC)
9647 {
9648 if (redrawing() && !char_avail())
9649 {
9650 /* may need to redraw when no more chars available now */
Bram Moolenaar754b5602006-02-09 23:53:20 +00009651 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009652
9653 if (char2cells(c) == 1)
9654 {
9655 /* first remove the '?', otherwise it's restored when typing
9656 * an ESC next */
9657 edit_unputchar();
Bram Moolenaar754b5602006-02-09 23:53:20 +00009658 ins_redraw(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009659 edit_putchar(c, TRUE);
9660 }
9661#ifdef FEAT_CMDL_INFO
9662 add_to_showcmd_c(c);
9663#endif
9664 }
9665 ++no_mapping;
9666 ++allow_keys;
Bram Moolenaar61abfd12007-09-13 16:26:47 +00009667 cc = plain_vgetc();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009668 --no_mapping;
9669 --allow_keys;
Bram Moolenaar26dcc7e2010-07-14 22:35:55 +02009670 edit_unputchar(); /* when line fits in 'columns' the '?' is at the
9671 start of the next line and will not be redrawn */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009672 if (cc != ESC)
9673 {
9674 AppendToRedobuff((char_u *)CTRL_V_STR);
9675 c = getdigraph(c, cc, TRUE);
9676#ifdef FEAT_CMDL_INFO
9677 clear_showcmd();
9678#endif
9679 return c;
9680 }
9681 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009682#ifdef FEAT_CMDL_INFO
9683 clear_showcmd();
9684#endif
9685 return NUL;
9686}
9687#endif
9688
9689/*
9690 * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
9691 * Returns the char to be inserted, or NUL if none found.
9692 */
9693 static int
9694ins_copychar(lnum)
9695 linenr_T lnum;
9696{
9697 int c;
9698 int temp;
9699 char_u *ptr, *prev_ptr;
9700
9701 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
9702 {
9703 vim_beep();
9704 return NUL;
9705 }
9706
9707 /* try to advance to the cursor column */
9708 temp = 0;
9709 ptr = ml_get(lnum);
9710 prev_ptr = ptr;
9711 validate_virtcol();
9712 while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
9713 {
9714 prev_ptr = ptr;
9715 temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp);
9716 }
9717 if ((colnr_T)temp > curwin->w_virtcol)
9718 ptr = prev_ptr;
9719
9720#ifdef FEAT_MBYTE
9721 c = (*mb_ptr2char)(ptr);
9722#else
9723 c = *ptr;
9724#endif
9725 if (c == NUL)
9726 vim_beep();
9727 return c;
9728}
9729
Bram Moolenaar4be06f92005-07-29 22:36:03 +00009730/*
9731 * CTRL-Y or CTRL-E typed in Insert mode.
9732 */
9733 static int
9734ins_ctrl_ey(tc)
9735 int tc;
9736{
9737 int c = tc;
9738
9739#ifdef FEAT_INS_EXPAND
9740 if (ctrl_x_mode == CTRL_X_SCROLL)
9741 {
9742 if (c == Ctrl_Y)
9743 scrolldown_clamp();
9744 else
9745 scrollup_clamp();
9746 redraw_later(VALID);
9747 }
9748 else
9749#endif
9750 {
9751 c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1));
9752 if (c != NUL)
9753 {
9754 long tw_save;
9755
9756 /* The character must be taken literally, insert like it
9757 * was typed after a CTRL-V, and pretend 'textwidth'
9758 * wasn't set. Digits, 'o' and 'x' are special after a
9759 * CTRL-V, don't use it for these. */
9760 if (c < 256 && !isalnum(c))
9761 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
9762 tw_save = curbuf->b_p_tw;
9763 curbuf->b_p_tw = -1;
9764 insert_special(c, TRUE, FALSE);
9765 curbuf->b_p_tw = tw_save;
9766#ifdef FEAT_RIGHTLEFT
9767 revins_chars++;
9768 revins_legal++;
9769#endif
9770 c = Ctrl_V; /* pretend CTRL-V is last character */
9771 auto_format(FALSE, TRUE);
9772 }
9773 }
9774 return c;
9775}
9776
Bram Moolenaar071d4272004-06-13 20:20:40 +00009777#ifdef FEAT_SMARTINDENT
9778/*
9779 * Try to do some very smart auto-indenting.
9780 * Used when inserting a "normal" character.
9781 */
9782 static void
9783ins_try_si(c)
9784 int c;
9785{
9786 pos_T *pos, old_pos;
9787 char_u *ptr;
9788 int i;
9789 int temp;
9790
9791 /*
9792 * do some very smart indenting when entering '{' or '}'
9793 */
9794 if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
9795 {
9796 /*
9797 * for '}' set indent equal to indent of line containing matching '{'
9798 */
9799 if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
9800 {
9801 old_pos = curwin->w_cursor;
9802 /*
9803 * If the matching '{' has a ')' immediately before it (ignoring
9804 * white-space), then line up with the start of the line
9805 * containing the matching '(' if there is one. This handles the
9806 * case where an "if (..\n..) {" statement continues over multiple
9807 * lines -- webb
9808 */
9809 ptr = ml_get(pos->lnum);
9810 i = pos->col;
9811 if (i > 0) /* skip blanks before '{' */
9812 while (--i > 0 && vim_iswhite(ptr[i]))
9813 ;
9814 curwin->w_cursor.lnum = pos->lnum;
9815 curwin->w_cursor.col = i;
9816 if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
9817 curwin->w_cursor = *pos;
9818 i = get_indent();
9819 curwin->w_cursor = old_pos;
9820#ifdef FEAT_VREPLACE
9821 if (State & VREPLACE_FLAG)
Bram Moolenaar21b17e72008-01-16 19:03:13 +00009822 change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009823 else
9824#endif
9825 (void)set_indent(i, SIN_CHANGED);
9826 }
9827 else if (curwin->w_cursor.col > 0)
9828 {
9829 /*
9830 * when inserting '{' after "O" reduce indent, but not
9831 * more than indent of previous line
9832 */
9833 temp = TRUE;
9834 if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
9835 {
9836 old_pos = curwin->w_cursor;
9837 i = get_indent();
9838 while (curwin->w_cursor.lnum > 1)
9839 {
9840 ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
9841
9842 /* ignore empty lines and lines starting with '#'. */
9843 if (*ptr != '#' && *ptr != NUL)
9844 break;
9845 }
9846 if (get_indent() >= i)
9847 temp = FALSE;
9848 curwin->w_cursor = old_pos;
9849 }
9850 if (temp)
Bram Moolenaar21b17e72008-01-16 19:03:13 +00009851 shift_line(TRUE, FALSE, 1, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009852 }
9853 }
9854
9855 /*
9856 * set indent of '#' always to 0
9857 */
9858 if (curwin->w_cursor.col > 0 && can_si && c == '#')
9859 {
9860 /* remember current indent for next line */
9861 old_indent = get_indent();
9862 (void)set_indent(0, SIN_CHANGED);
9863 }
9864
9865 /* Adjust ai_col, the char at this position can be deleted. */
9866 if (ai_col > curwin->w_cursor.col)
9867 ai_col = curwin->w_cursor.col;
9868}
9869#endif
9870
9871/*
9872 * Get the value that w_virtcol would have when 'list' is off.
9873 * Unless 'cpo' contains the 'L' flag.
9874 */
9875 static colnr_T
9876get_nolist_virtcol()
9877{
9878 if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
9879 return getvcol_nolist(&curwin->w_cursor);
9880 validate_virtcol();
9881 return curwin->w_virtcol;
9882}