diff options
Diffstat (limited to 'src/edit.c')
-rw-r--r-- | src/edit.c | 1386 |
1 files changed, 755 insertions, 631 deletions
diff --git a/src/edit.c b/src/edit.c index 48883fde6..01a6591f7 100644 --- a/src/edit.c +++ b/src/edit.c @@ -31,6 +31,8 @@ #define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT) #define CTRL_X_CMDLINE 11 #define CTRL_X_FUNCTION 12 +#define CTRL_X_OCCULT 13 +#define CTRL_X_LOCAL_MSG 14 /* only used in "ctrl_x_msgs" */ #define CHECK_KEYS_TIME 30 @@ -40,9 +42,7 @@ static char *ctrl_x_msgs[] = { N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */ N_(" ^X mode (^E^Y^L^]^F^I^K^D^U^V^N^P)"), - /* Scroll has it's own msgs, in it's place there is the msg for local - * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo */ - N_(" Keyword Local completion (^N^P)"), + NULL, N_(" Whole line completion (^L^N^P)"), N_(" File name completion (^F^N^P)"), N_(" Tag completion (^]^N^P)"), @@ -53,6 +53,8 @@ static char *ctrl_x_msgs[] = N_(" Thesaurus completion (^T^N^P)"), N_(" Command-line completion (^V^N^P)"), N_(" User defined completion (^U^N^P)"), + N_(" Occult completion (^O^N^P)"), + N_(" Keyword Local completion (^N^P)"), }; static char_u e_hitend[] = N_("Hit end of paragraph"); @@ -76,28 +78,35 @@ struct Completion /* * All the current matches are stored in a list. - * "first_match" points to the start of the list. - * "curr_match" points to the currently selected entry. - * "shown_match" is different from curr_match during ins_compl_get_exp(). + * "compl_first_match" points to the start of the list. + * "compl_curr_match" points to the currently selected entry. + * "compl_shown_match" is different from compl_curr_match during + * ins_compl_get_exp(). */ -static struct Completion *first_match = NULL; -static struct Completion *curr_match = NULL; -static struct Completion *shown_match = NULL; - -static int started_completion = FALSE; -static int completion_matches = 0; -static char_u *complete_pat = NULL; -static int complete_direction = FORWARD; -static int shown_direction = FORWARD; -static int completion_pending = FALSE; -static pos_T initial_pos; -static colnr_T complete_col = 0; /* column where the text starts +static struct Completion *compl_first_match = NULL; +static struct Completion *compl_curr_match = NULL; +static struct Completion *compl_shown_match = NULL; + +/* When the first completion is done "compl_started" is set. When it's + * FALSE the word to be completed must be located. */ +static int compl_started = FALSE; + +static int compl_matches = 0; +static char_u *compl_pattern = NULL; +static int compl_direction = FORWARD; +static int compl_shows_dir = FORWARD; +static int compl_pending = FALSE; +static pos_T compl_startpos; +static colnr_T compl_col = 0; /* column where the text starts that is being completed */ -static int save_sm; -static char_u *original_text = NULL; /* text before completion */ -static int continue_mode = 0; -static expand_T complete_xp; - +static int save_sm = -1; +static char_u *compl_orig_text = NULL; /* text as it was before + completion started */ +static int compl_cont_mode = 0; +static expand_T compl_xp; + +static void ins_ctrl_x __ARGS((void)); +static int has_compl_option __ARGS((int dict_opt)); static int ins_compl_add __ARGS((char_u *str, int len, char_u *, int dir, int reuse)); static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir)); static int ins_compl_make_cyclic __ARGS((void)); @@ -145,6 +154,7 @@ static int cindent_on __ARGS((void)); #endif static void ins_reg __ARGS((void)); static void ins_ctrl_g __ARGS((void)); +static void ins_ctrl_hat __ARGS((void)); static int ins_esc __ARGS((long *count, int cmdchar)); #ifdef FEAT_RIGHTLEFT static void ins_ctrl_ __ARGS((void)); @@ -152,6 +162,8 @@ static void ins_ctrl_ __ARGS((void)); #ifdef FEAT_VISUAL static int ins_start_select __ARGS((int c)); #endif +static void ins_insert __ARGS((int replaceState)); +static void ins_ctrl_o __ARGS((void)); static void ins_shift __ARGS((int c, int lastc)); static void ins_del __ARGS((void)); static int ins_bs __ARGS((int c, int mode, int *inserted_space_p)); @@ -178,6 +190,7 @@ static int ins_eol __ARGS((int c)); static int ins_digraph __ARGS((void)); #endif static int ins_copychar __ARGS((linenr_T lnum)); +static int ins_ctrl_ey __ARGS((int tc)); #ifdef FEAT_SMARTINDENT static void ins_try_si __ARGS((int c)); #endif @@ -735,121 +748,12 @@ edit(cmdchar, startln, count) */ switch (c) { - /* toggle insert/replace mode */ - case K_INS: - case K_KINS: -#ifdef FEAT_FKMAP - if (p_fkmap && p_ri) - { - beep_flush(); - EMSG(farsi_text_3); /* encoded in Farsi */ - break; - } -#endif -#ifdef FEAT_AUTOCMD - set_vim_var_string(VV_INSERTMODE, - (char_u *)((State & REPLACE_FLAG) ? "i" : - replaceState == VREPLACE ? "v" : "r"), 1); - apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf); -#endif - if (State & REPLACE_FLAG) - State = INSERT | (State & LANGMAP); - else - State = replaceState | (State & LANGMAP); - AppendCharToRedobuff(K_INS); - showmode(); -#ifdef CURSOR_SHAPE - ui_cursor_shape(); /* may show different cursor shape */ -#endif - break; - -#ifdef FEAT_INS_EXPAND - /* Enter CTRL-X mode */ - case Ctrl_X: - /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X - * CTRL-V works like CTRL-N */ - if (ctrl_x_mode != CTRL_X_CMDLINE) - { - /* if the next ^X<> won't ADD nothing, then reset - * continue_status */ - if (continue_status & CONT_N_ADDS) - continue_status = (continue_status | CONT_INTRPT); - else - continue_status = 0; - /* We're not sure which CTRL-X mode it will be yet */ - ctrl_x_mode = CTRL_X_NOT_DEFINED_YET; - edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); - edit_submode_pre = NULL; - showmode(); - } - break; -#endif - - /* end of Select mode mapping - ignore */ - case K_SELECT: - break; - - /* suspend when 'insertmode' set */ - case Ctrl_Z: - if (!p_im) - goto normalchar; /* insert CTRL-Z as normal char */ - stuffReadbuff((char_u *)":st\r"); - c = Ctrl_O; - /*FALLTHROUGH*/ - - /* execute one command */ - case Ctrl_O: - if (echeck_abbr(Ctrl_O + ABBR_OFF)) - break; - count = 0; -#ifdef FEAT_VREPLACE - if (State & VREPLACE_FLAG) - restart_edit = 'V'; - else -#endif - if (State & REPLACE_FLAG) - restart_edit = 'R'; - else - restart_edit = 'I'; -#ifdef FEAT_VIRTUALEDIT - if (virtual_active()) - ins_at_eol = FALSE; /* cursor always keeps its column */ - else -#endif - ins_at_eol = (gchar_cursor() == NUL); - goto doESCkey; - -#ifdef FEAT_SNIFF - case K_SNIFF: - stuffcharReadbuff(K_SNIFF); - goto doESCkey; -#endif - - /* Hitting the help key in insert mode is like <ESC> <Help> */ - case K_HELP: - case K_F1: - case K_XF1: - stuffcharReadbuff(K_HELP); - if (p_im) - need_start_insertmode = TRUE; - goto doESCkey; - -#ifdef FEAT_NETBEANS_INTG - case K_F21: - ++no_mapping; /* don't map the next key hits */ - i = safe_vgetc(); - --no_mapping; - netbeans_keycommand(i); - break; -#endif - - /* an escape ends input mode */ - case ESC: + case ESC: /* End input mode */ if (echeck_abbr(ESC + ABBR_OFF)) break; /*FALLTHROUGH*/ - case Ctrl_C: + case Ctrl_C: /* End input mode */ #ifdef FEAT_CMDWIN if (c == Ctrl_C && cmdwin_type != 0) { @@ -880,9 +784,6 @@ doESCkey: /* * This is the ONLY return from edit()! */ -#ifdef FEAT_SYN_HL - check_spell_redraw(); -#endif /* Always update o_lnum, so that a "CTRL-O ." that adds a line * still puts the cursor back after the inserted text. */ if (ins_at_eol && gchar_cursor() == NUL) @@ -899,116 +800,108 @@ doESCkey: } continue; - /* - * Insert the previously inserted text. - * For ^@ the trailing ESC will end the insert, unless there is an - * error. - */ - case K_ZERO: + case K_INS: /* toggle insert/replace mode */ + case K_KINS: + ins_insert(replaceState); + break; + +#ifdef FEAT_INS_EXPAND + case Ctrl_X: /* Enter CTRL-X mode */ + ins_ctrl_x(); + break; +#endif + + case K_SELECT: /* end of Select mode mapping - ignore */ + break; + + case Ctrl_Z: /* suspend when 'insertmode' set */ + if (!p_im) + goto normalchar; /* insert CTRL-Z as normal char */ + stuffReadbuff((char_u *)":st\r"); + c = Ctrl_O; + /*FALLTHROUGH*/ + + case Ctrl_O: /* execute one command */ +#ifdef FEAT_INS_EXPAND + if (ctrl_x_mode == CTRL_X_OCCULT) + goto docomplete; +#endif + if (echeck_abbr(Ctrl_O + ABBR_OFF)) + break; + ins_ctrl_o(); + count = 0; + goto doESCkey; + +#ifdef FEAT_SNIFF + case K_SNIFF: /* Sniff command received */ + stuffcharReadbuff(K_SNIFF); + goto doESCkey; +#endif + + case K_HELP: /* Help key works like <ESC> <Help> */ + case K_F1: + case K_XF1: + stuffcharReadbuff(K_HELP); + if (p_im) + need_start_insertmode = TRUE; + goto doESCkey; + +#ifdef FEAT_NETBEANS_INTG + case K_F21: /* NetBeans command */ + ++no_mapping; /* don't map the next key hits */ + i = safe_vgetc(); + --no_mapping; + netbeans_keycommand(i); + break; +#endif + + case K_ZERO: /* Insert the previously inserted text. */ case NUL: case Ctrl_A: + /* For ^@ the trailing ESC will end the insert, unless there is an + * error. */ if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL && c != Ctrl_A && !p_im) goto doESCkey; /* quit insert mode */ inserted_space = FALSE; break; - /* insert the contents of a register */ - case Ctrl_R: + case Ctrl_R: /* insert the contents of a register */ ins_reg(); auto_format(FALSE, TRUE); inserted_space = FALSE; break; - case Ctrl_G: + case Ctrl_G: /* commands starting with CTRL-G */ ins_ctrl_g(); break; - case Ctrl_HAT: - if (map_to_exists_mode((char_u *)"", LANGMAP)) - { - /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ - if (State & LANGMAP) - { - curbuf->b_p_iminsert = B_IMODE_NONE; - State &= ~LANGMAP; - } - else - { - curbuf->b_p_iminsert = B_IMODE_LMAP; - State |= LANGMAP; -#ifdef USE_IM_CONTROL - im_set_active(FALSE); -#endif - } - } -#ifdef USE_IM_CONTROL - else - { - /* There are no ":lmap" mappings, toggle IM */ - if (im_get_status()) - { - curbuf->b_p_iminsert = B_IMODE_NONE; - im_set_active(FALSE); - } - else - { - curbuf->b_p_iminsert = B_IMODE_IM; - State &= ~LANGMAP; - im_set_active(TRUE); - } - } -#endif - set_iminsert_global(); - showmode(); -#ifdef FEAT_GUI - /* may show different cursor shape or color */ - if (gui.in_use) - gui_update_cursor(TRUE, FALSE); -#endif -#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP) - /* Show/unshow value of 'keymap' in status lines. */ - status_redraw_curbuf(); -#endif + case Ctrl_HAT: /* switch input mode and/or langmap */ + ins_ctrl_hat(); break; #ifdef FEAT_RIGHTLEFT - case Ctrl__: + case Ctrl__: /* switch between languages */ if (!p_ari) goto normalchar; ins_ctrl_(); break; #endif - /* Make indent one shiftwidth smaller. */ - case Ctrl_D: + case Ctrl_D: /* Make indent one shiftwidth smaller. */ #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) if (ctrl_x_mode == CTRL_X_PATH_DEFINES) goto docomplete; #endif /* FALLTHROUGH */ - /* Make indent one shiftwidth greater. */ - case Ctrl_T: + case Ctrl_T: /* Make indent one shiftwidth greater. */ # ifdef FEAT_INS_EXPAND if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS) { - if (*curbuf->b_p_tsr == NUL && *p_tsr == NUL) - { - ctrl_x_mode = 0; - edit_submode = NULL; - msg_attr((char_u *)_("'thesaurus' option is empty"), - hl_attr(HLF_E)); - if (emsg_silent == 0) - { - vim_beep(); - setcursor(); - out_flush(); - ui_delay(2000L, FALSE); - } - break; - } - goto docomplete; + if (has_compl_option(FALSE)) + goto docomplete; + break; } # endif ins_shift(c, lastc); @@ -1016,32 +909,27 @@ doESCkey: inserted_space = FALSE; break; - /* delete character under the cursor */ - case K_DEL: + case K_DEL: /* delete character under the cursor */ case K_KDEL: ins_del(); auto_format(FALSE, TRUE); break; - /* delete character before the cursor */ - case K_BS: + case K_BS: /* delete character before the cursor */ case Ctrl_H: did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); auto_format(FALSE, TRUE); break; - /* delete word before the cursor */ - case Ctrl_W: + case Ctrl_W: /* delete word before the cursor */ did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); auto_format(FALSE, TRUE); break; - /* delete all inserted text in current line */ - case Ctrl_U: + case Ctrl_U: /* delete all inserted text in current line */ # ifdef FEAT_COMPL_FUNC /* CTRL-X CTRL-U completes with 'completefunc'. */ - if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET - || ctrl_x_mode == CTRL_X_FUNCTION) + if (ctrl_x_mode == CTRL_X_FUNCTION) goto docomplete; # endif did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); @@ -1050,7 +938,7 @@ doESCkey: break; #ifdef FEAT_MOUSE - case K_LEFTMOUSE: + case K_LEFTMOUSE: /* mouse keys */ case K_LEFTMOUSE_NM: case K_LEFTDRAG: case K_LEFTRELEASE: @@ -1070,18 +958,16 @@ doESCkey: ins_mouse(c); break; - /* Default action for scroll wheel up: scroll up */ - case K_MOUSEDOWN: + case K_MOUSEDOWN: /* Default action for scroll wheel up: scroll up */ ins_mousescroll(FALSE); break; - /* Default action for scroll wheel down: scroll down */ - case K_MOUSEUP: + case K_MOUSEUP: /* Default action for scroll wheel down: scroll down */ ins_mousescroll(TRUE); break; #endif - case K_IGNORE: + case K_IGNORE: /* Something mapped to nothing */ break; #ifdef FEAT_GUI @@ -1094,83 +980,81 @@ doESCkey: break; #endif - case K_HOME: + case K_HOME: /* <Home> */ case K_KHOME: case K_S_HOME: case K_C_HOME: ins_home(c); break; - case K_END: + case K_END: /* <End> */ case K_KEND: case K_S_END: case K_C_END: ins_end(c); break; - case K_LEFT: + case K_LEFT: /* <Left> */ if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) ins_s_left(); else ins_left(); break; - case K_S_LEFT: + case K_S_LEFT: /* <S-Left> */ case K_C_LEFT: ins_s_left(); break; - case K_RIGHT: + case K_RIGHT: /* <Right> */ if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) ins_s_right(); else ins_right(); break; - case K_S_RIGHT: + case K_S_RIGHT: /* <S-Right> */ case K_C_RIGHT: ins_s_right(); break; - case K_UP: + case K_UP: /* <Up> */ if (mod_mask & MOD_MASK_SHIFT) ins_pageup(); else ins_up(FALSE); break; - case K_S_UP: + case K_S_UP: /* <S-Up> */ case K_PAGEUP: case K_KPAGEUP: ins_pageup(); break; - case K_DOWN: + case K_DOWN: /* <Down> */ if (mod_mask & MOD_MASK_SHIFT) ins_pagedown(); else ins_down(FALSE); break; - case K_S_DOWN: + case K_S_DOWN: /* <S-Down> */ case K_PAGEDOWN: case K_KPAGEDOWN: ins_pagedown(); break; #ifdef FEAT_DND - case K_DROP: + case K_DROP: /* drag-n-drop event */ ins_drop(); break; #endif - /* When <S-Tab> isn't mapped, use it like a normal TAB */ - case K_S_TAB: + case K_S_TAB: /* When not mapped, use like a normal TAB */ c = TAB; /* FALLTHROUGH */ - /* TAB or Complete patterns along path */ - case TAB: + case TAB: /* TAB or Complete patterns along path */ #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) if (ctrl_x_mode == CTRL_X_PATH_PATTERNS) goto docomplete; @@ -1181,7 +1065,7 @@ doESCkey: auto_format(FALSE, TRUE); break; - case K_KENTER: + case K_KENTER: /* <Enter> */ c = CAR; /* FALLTHROUGH */ case CAR: @@ -1210,26 +1094,13 @@ doESCkey: break; #if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND) - case Ctrl_K: + case Ctrl_K: /* digraph or keyword completion */ # ifdef FEAT_INS_EXPAND if (ctrl_x_mode == CTRL_X_DICTIONARY) { - if (*curbuf->b_p_dict == NUL && *p_dict == NUL) - { - ctrl_x_mode = 0; - edit_submode = NULL; - msg_attr((char_u *)_("'dictionary' option is empty"), - hl_attr(HLF_E)); - if (emsg_silent == 0) - { - vim_beep(); - setcursor(); - out_flush(); - ui_delay(2000L, FALSE); - } - break; - } - goto docomplete; + if (has_compl_option(TRUE)) + goto docomplete; + break; } # endif # ifdef FEAT_DIGRAPHS @@ -1238,21 +1109,21 @@ doESCkey: break; # endif goto normalchar; -#endif /* FEAT_DIGRAPHS || FEAT_INS_EXPAND */ +#endif #ifdef FEAT_INS_EXPAND - case Ctrl_RSB: /* Tag name completion after ^X */ + case Ctrl_RSB: /* Tag name completion after ^X */ if (ctrl_x_mode != CTRL_X_TAGS) goto normalchar; goto docomplete; - case Ctrl_F: /* File name completion after ^X */ + case Ctrl_F: /* File name completion after ^X */ if (ctrl_x_mode != CTRL_X_FILES) goto normalchar; goto docomplete; #endif - case Ctrl_L: /* Whole line completion after ^X */ + case Ctrl_L: /* Whole line completion after ^X */ #ifdef FEAT_INS_EXPAND if (ctrl_x_mode != CTRL_X_WHOLE_LINE) #endif @@ -1269,60 +1140,24 @@ doESCkey: #ifdef FEAT_INS_EXPAND /* FALLTHROUGH */ - /* Do previous/next pattern completion */ - case Ctrl_P: + case Ctrl_P: /* Do previous/next pattern completion */ case Ctrl_N: /* if 'complete' is empty then plain ^P is no longer special, * but it is under other ^X modes */ if (*curbuf->b_p_cpt == NUL && ctrl_x_mode != 0 - && !(continue_status & CONT_LOCAL)) + && !(compl_cont_status & CONT_LOCAL)) goto normalchar; docomplete: if (ins_complete(c) == FAIL) - continue_status = 0; + compl_cont_status = 0; break; #endif /* FEAT_INS_EXPAND */ - case Ctrl_Y: /* copy from previous line or scroll down */ - case Ctrl_E: /* copy from next line or scroll up */ -#ifdef FEAT_INS_EXPAND - if (ctrl_x_mode == CTRL_X_SCROLL) - { - if (c == Ctrl_Y) - scrolldown_clamp(); - else - scrollup_clamp(); - redraw_later(VALID); - } - else -#endif - { - c = ins_copychar(curwin->w_cursor.lnum - + (c == Ctrl_Y ? -1 : 1)); - if (c != NUL) - { - long tw_save; - - /* The character must be taken literally, insert like it - * was typed after a CTRL-V, and pretend 'textwidth' - * wasn't set. Digits, 'o' and 'x' are special after a - * CTRL-V, don't use it for these. */ - if (c < 256 && !isalnum(c)) - AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ - tw_save = curbuf->b_p_tw; - curbuf->b_p_tw = -1; - insert_special(c, TRUE, FALSE); - curbuf->b_p_tw = tw_save; -#ifdef FEAT_RIGHTLEFT - revins_chars++; - revins_legal++; -#endif - c = Ctrl_V; /* pretend CTRL-V is last character */ - auto_format(FALSE, TRUE); - } - } + case Ctrl_Y: /* copy from previous line or scroll down */ + case Ctrl_E: /* copy from next line or scroll up */ + c = ins_ctrl_ey(c); break; default: @@ -1897,6 +1732,57 @@ backspace_until_column(col) #if defined(FEAT_INS_EXPAND) || defined(PROTO) /* + * CTRL-X pressed in Insert mode. + */ + static void +ins_ctrl_x() +{ + /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X + * CTRL-V works like CTRL-N */ + if (ctrl_x_mode != CTRL_X_CMDLINE) + { + /* if the next ^X<> won't ADD nothing, then reset + * compl_cont_status */ + if (compl_cont_status & CONT_N_ADDS) + compl_cont_status = (compl_cont_status | CONT_INTRPT); + else + compl_cont_status = 0; + /* We're not sure which CTRL-X mode it will be yet */ + ctrl_x_mode = CTRL_X_NOT_DEFINED_YET; + edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); + edit_submode_pre = NULL; + showmode(); + } +} + +/* + * Return TRUE if the 'dict' or 'tsr' option can be used. + */ + static int +has_compl_option(dict_opt) + int dict_opt; +{ + if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL) + : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) + { + ctrl_x_mode = 0; + edit_submode = NULL; + msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty") + : (char_u *)_("'thesaurus' option is empty"), + hl_attr(HLF_E)); + if (emsg_silent == 0) + { + vim_beep(); + setcursor(); + out_flush(); + ui_delay(2000L, FALSE); + } + return FALSE; + } + return TRUE; +} + +/* * Is the character 'c' a valid key to go to or keep us in CTRL-X mode? * This depends on the current mode. */ @@ -1913,7 +1799,7 @@ vim_is_ctrl_x_key(c) case 0: /* Not in any CTRL-X mode */ return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X); case CTRL_X_NOT_DEFINED_YET: - return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E + return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V @@ -1941,8 +1827,10 @@ vim_is_ctrl_x_key(c) || c == Ctrl_X); #ifdef FEAT_COMPL_FUNC case CTRL_X_FUNCTION: - return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N || c == Ctrl_X); + return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N); #endif + case CTRL_X_OCCULT: + return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N); } EMSG(_(e_internal)); return FALSE; @@ -1953,6 +1841,7 @@ vim_is_ctrl_x_key(c) * case of the originally typed text is used, and the case of the completed * text is infered, ie this tries to work out what case you probably wanted * the rest of the word to be in -- webb + * TODO: make this work for multi-byte characters. */ int ins_compl_add_infercase(str, len, fname, dir, reuse) @@ -1973,15 +1862,15 @@ ins_compl_add_infercase(str, len, fname, dir, reuse) vim_strncpy(IObuff, str, len); /* Rule 1: Were any chars converted to lower? */ - for (idx = 0; idx < completion_length; ++idx) + for (idx = 0; idx < compl_length; ++idx) { - if (islower(original_text[idx])) + if (islower(compl_orig_text[idx])) { has_lower = TRUE; if (isupper(IObuff[idx])) { /* Rule 1 is satisfied */ - for (idx = completion_length; idx < len; ++idx) + for (idx = compl_length; idx < len; ++idx) IObuff[idx] = TOLOWER_LOC(IObuff[idx]); break; } @@ -1994,22 +1883,22 @@ ins_compl_add_infercase(str, len, fname, dir, reuse) */ if (!has_lower) { - for (idx = 0; idx < completion_length; ++idx) + for (idx = 0; idx < compl_length; ++idx) { - if (was_letter && isupper(original_text[idx]) + if (was_letter && isupper(compl_orig_text[idx]) && islower(IObuff[idx])) { /* Rule 2 is satisfied */ - for (idx = completion_length; idx < len; ++idx) + for (idx = compl_length; idx < len; ++idx) IObuff[idx] = TOUPPER_LOC(IObuff[idx]); break; } - was_letter = isalpha(original_text[idx]); + was_letter = isalpha(compl_orig_text[idx]); } } /* Copy the original case of the part we typed */ - STRNCPY(IObuff, original_text, completion_length); + STRNCPY(IObuff, compl_orig_text, compl_length); return ins_compl_add(IObuff, len, fname, dir, reuse); } @@ -2041,9 +1930,9 @@ ins_compl_add(str, len, fname, dir, reuse) /* * If the same match is already present, don't add it. */ - if (first_match != NULL) + if (compl_first_match != NULL) { - match = first_match; + match = compl_first_match; do { if ( !(match->original & ORIGINAL_TEXT) @@ -2051,7 +1940,7 @@ ins_compl_add(str, len, fname, dir, reuse) && match->str[len] == NUL) return FAIL; match = match->next; - } while (match != NULL && match != first_match); + } while (match != NULL && match != compl_first_match); } /* @@ -2065,7 +1954,7 @@ ins_compl_add(str, len, fname, dir, reuse) if (reuse & ORIGINAL_TEXT) { match->number = 0; - match->str = original_text; + match->str = compl_orig_text; } else if ((match->str = vim_strnsave(str, len)) == NULL) { @@ -2073,12 +1962,12 @@ ins_compl_add(str, len, fname, dir, reuse) return RET_ERROR; } /* match-fname is: - * - curr_match->fname if it is a string equal to fname. + * - compl_curr_match->fname if it is a string equal to fname. * - a copy of fname, FREE_FNAME is set to free later THE allocated mem. * - NULL otherwise. --Acevedo */ - if (fname && curr_match && curr_match->fname - && STRCMP(fname, curr_match->fname) == 0) - match->fname = curr_match->fname; + if (fname && compl_curr_match && compl_curr_match->fname + && STRCMP(fname, compl_curr_match->fname) == 0) + match->fname = compl_curr_match->fname; else if (fname && (match->fname = vim_strsave(fname)) != NULL) reuse |= FREE_FNAME; else @@ -2088,25 +1977,25 @@ ins_compl_add(str, len, fname, dir, reuse) /* * Link the new match structure in the list of matches. */ - if (first_match == NULL) + if (compl_first_match == NULL) match->next = match->prev = NULL; else if (dir == FORWARD) { - match->next = curr_match->next; - match->prev = curr_match; + match->next = compl_curr_match->next; + match->prev = compl_curr_match; } else /* BACKWARD */ { - match->next = curr_match; - match->prev = curr_match->prev; + match->next = compl_curr_match; + match->prev = compl_curr_match->prev; } if (match->next) match->next->prev = match; if (match->prev) match->prev->next = match; else /* if there's nothing before, it is the first match */ - first_match = match; - curr_match = match; + compl_first_match = match; + compl_curr_match = match; return OK; } @@ -2141,20 +2030,20 @@ ins_compl_make_cyclic() struct Completion *match; int count = 0; - if (first_match != NULL) + if (compl_first_match != NULL) { /* * Find the end of the list. */ - match = first_match; - /* there's always an entry for the original_text, it doesn't count. */ - while (match->next != NULL && match->next != first_match) + match = compl_first_match; + /* there's always an entry for the compl_orig_text, it doesn't count. */ + while (match->next != NULL && match->next != compl_first_match) { match = match->next; ++count; } - match->next = first_match; - first_match->prev = match; + match->next = compl_first_match; + compl_first_match->prev = match; } return count; } @@ -2192,7 +2081,7 @@ ins_compl_dictionaries(dict, pat, dir, flags, thesaurus) /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */ regmatch.rm_ic = ignorecase(pat); while (buf != NULL && regmatch.regprog != NULL && *dict != NUL - && !got_int && !completion_interrupted) + && !got_int && !compl_interrupted) { /* copy one dictionary file name into buf */ if (flags == DICT_EXACT) @@ -2212,7 +2101,7 @@ ins_compl_dictionaries(dict, pat, dir, flags, thesaurus) count = 0; } - for (i = 0; i < count && !got_int && !completion_interrupted; i++) + for (i = 0; i < count && !got_int && !compl_interrupted; i++) { fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */ if (flags != DICT_EXACT) @@ -2228,8 +2117,8 @@ ins_compl_dictionaries(dict, pat, dir, flags, thesaurus) * Read dictionary file line by line. * Check each line for a match. */ - while (!got_int && !completion_interrupted - && !vim_fgets(buf, LSIZE, fp)) + while (!got_int && !compl_interrupted + && !vim_fgets(buf, LSIZE, fp)) { ptr = buf; while (vim_regexec(®match, buf, (colnr_T)(ptr - buf))) @@ -2358,33 +2247,33 @@ ins_compl_free() { struct Completion *match; - vim_free(complete_pat); - complete_pat = NULL; + vim_free(compl_pattern); + compl_pattern = NULL; - if (first_match == NULL) + if (compl_first_match == NULL) return; - curr_match = first_match; + compl_curr_match = compl_first_match; do { - match = curr_match; - curr_match = curr_match->next; + match = compl_curr_match; + compl_curr_match = compl_curr_match->next; vim_free(match->str); /* several entries may use the same fname, free it just once. */ if (match->original & FREE_FNAME) vim_free(match->fname); vim_free(match); - } while (curr_match != NULL && curr_match != first_match); - first_match = curr_match = NULL; + } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); + compl_first_match = compl_curr_match = NULL; } static void ins_compl_clear() { - continue_status = 0; - started_completion = FALSE; - completion_matches = 0; - vim_free(complete_pat); - complete_pat = NULL; + compl_cont_status = 0; + compl_started = FALSE; + compl_matches = 0; + vim_free(compl_pattern); + compl_pattern = NULL; save_sm = -1; edit_submode_extra = NULL; } @@ -2397,7 +2286,6 @@ ins_compl_prep(c) int c; { char_u *ptr; - char_u *tmp_ptr; int temp; int want_cindent; @@ -2449,6 +2337,9 @@ ins_compl_prep(c) ctrl_x_mode = CTRL_X_FUNCTION; break; #endif + case Ctrl_O: + ctrl_x_mode = CTRL_X_OCCULT; + break; case Ctrl_RSB: ctrl_x_mode = CTRL_X_TAGS; break; @@ -2474,26 +2365,28 @@ ins_compl_prep(c) * ^X^F^X^P or ^P^X^X^P, see below) * nothing changes if interrupting mode 0, (eg, the flag * doesn't change when going to ADDING mode -- Acevedo */ - if (!(continue_status & CONT_INTRPT)) - continue_status |= CONT_LOCAL; - else if (continue_mode != 0) - continue_status &= ~CONT_LOCAL; + if (!(compl_cont_status & CONT_INTRPT)) + compl_cont_status |= CONT_LOCAL; + else if (compl_cont_mode != 0) + compl_cont_status &= ~CONT_LOCAL; /* FALLTHROUGH */ default: - /* if we have typed at least 2 ^X's... for modes != 0, we set - * continue_status = 0 (eg, as if we had just started ^X mode) - * for mode 0, we set continue_mode to an impossible value, in - * both cases ^X^X can be used to restart the same mode - * (avoiding ADDING mode). Undocumented feature: - * In a mode != 0 ^X^P and ^X^X^P start 'complete' and local - * ^P expansions respectively. In mode 0 an extra ^X is - * needed since ^X^P goes to ADDING mode -- Acevedo */ + /* If we have typed at least 2 ^X's... for modes != 0, we set + * compl_cont_status = 0 (eg, as if we had just started ^X + * mode). + * For mode 0, we set "compl_cont_mode" to an impossible + * value, in both cases ^X^X can be used to restart the same + * mode (avoiding ADDING mode). + * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start + * 'complete' and local ^P expansions respectively. + * In mode 0 an extra ^X is needed since ^X^P goes to ADDING + * mode -- Acevedo */ if (c == Ctrl_X) { - if (continue_mode != 0) - continue_status = 0; + if (compl_cont_mode != 0) + compl_cont_status = 0; else - continue_mode = CTRL_X_NOT_DEFINED_YET; + compl_cont_mode = CTRL_X_NOT_DEFINED_YET; } ctrl_x_mode = 0; edit_submode = NULL; @@ -2515,36 +2408,36 @@ ins_compl_prep(c) showmode(); } - if (started_completion || ctrl_x_mode == CTRL_X_FINISHED) + if (compl_started || ctrl_x_mode == CTRL_X_FINISHED) { /* Show error message from attempted keyword completion (probably * 'Pattern not found') until another key is hit, then go back to - * showing what mode we are in. - */ + * showing what mode we are in. */ showmode(); if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R) || ctrl_x_mode == CTRL_X_FINISHED) { /* Get here when we have finished typing a sequence of ^N and * ^P or other completion characters in CTRL-X mode. Free up - * memory that was used, and make sure we can redo the insert. - */ - if (curr_match != NULL) + * memory that was used, and make sure we can redo the insert. */ + if (compl_curr_match != NULL) { + char_u *p; + /* * If any of the original typed text has been changed, * eg when ignorecase is set, we must add back-spaces to * the redo buffer. We add as few as necessary to delete * just the part of the original text that has changed. */ - ptr = curr_match->str; - tmp_ptr = original_text; - while (*tmp_ptr && *tmp_ptr == *ptr) + ptr = compl_curr_match->str; + p = compl_orig_text; + while (*p && *p == *ptr) { - ++tmp_ptr; + ++p; ++ptr; } - for (temp = 0; tmp_ptr[temp]; ++temp) + for (temp = 0; p[temp]; ++temp) AppendCharToRedobuff(K_BS); AppendToRedobuffLit(ptr); } @@ -2556,7 +2449,7 @@ ins_compl_prep(c) * When completing whole lines: fix indent for 'cindent'. * Otherwise, break line if it's too long. */ - if (continue_mode == CTRL_X_WHOLE_LINE) + if (compl_cont_mode == CTRL_X_WHOLE_LINE) { #ifdef FEAT_CINDENT /* re-indent the current line */ @@ -2579,11 +2472,12 @@ ins_compl_prep(c) auto_format(FALSE, TRUE); ins_compl_free(); - started_completion = FALSE; - completion_matches = 0; + compl_started = FALSE; + compl_matches = 0; msg_clr_cmdline(); /* necessary for "noshowmode" */ ctrl_x_mode = 0; - p_sm = save_sm; + if (save_sm >= 0) + p_sm = save_sm; if (edit_submode != NULL) { edit_submode = NULL; @@ -2604,8 +2498,8 @@ ins_compl_prep(c) * (re)set properly in ins_complete() */ if (!vim_is_ctrl_x_key(c)) { - continue_status = 0; - continue_mode = 0; + compl_cont_status = 0; + compl_cont_mode = 0; } } @@ -2698,9 +2592,11 @@ expand_by_function(lnum, col, base, matches) char_u ***matches; { char_u *matchstr = NULL; + char_u *line_copy = vim_strsave(ml_get(lnum)); /* Execute 'completefunc' and get the result */ - matchstr = call_completefunc(ml_get_buf(curbuf, lnum, FALSE), base, col, 0); + matchstr = call_completefunc(line_copy, base, col, 0); + vim_free(line_copy); /* Parse returned string */ if (matchstr != NULL) @@ -2736,10 +2632,37 @@ expand_by_function(lnum, col, base, matches) } #endif /* FEAT_COMPL_FUNC */ +static int expand_occult __ARGS((linenr_T lnum, int col, char_u *base, char_u ***matches)); + +/* + * Perform occult completion' + * Return value is number of candidates and array of candidates as "matchp". + */ + static int +expand_occult(lnum, col, pat, matchp) + linenr_T lnum; + int col; + char_u *pat; + char_u ***matchp; +{ + int num_matches; + + /* Use tag completion for now. */ + if (find_tags(pat, &num_matches, matchp, + TAG_REGEXP | TAG_NAMES | TAG_NOIC | + TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), + TAG_MANY, curbuf->b_ffname) == FAIL) + return 0; + return num_matches; +} + /* - * Get the next expansion(s) for the text starting at the initial curbuf - * position "ini" and in the direction dir. - * Return the total of matches or -1 if still unknown -- Acevedo + * Get the next expansion(s), using "compl_pattern". + * The search starts at position "ini" in curbuf and in the direction dir. + * When "compl_started" is FALSE start at that position, otherwise + * continue where we stopped searching before. + * This may return before finding all the matches. + * Return the total number of matches or -1 if still unknown -- Acevedo */ static int ins_compl_get_exp(ini, dir) @@ -2749,8 +2672,9 @@ ins_compl_get_exp(ini, dir) static pos_T first_match_pos; static pos_T last_match_pos; static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */ - static int found_all = FALSE; /* Found all matches. */ - static buf_T *ins_buf = NULL; + static int found_all = FALSE; /* Found all matches of a + certain type. */ + static buf_T *ins_buf = NULL; /* buffer being scanned */ pos_T *pos; char_u **matches; @@ -2763,34 +2687,33 @@ ins_compl_get_exp(ini, dir) int found_new_match; int type = ctrl_x_mode; char_u *ptr; - char_u *tmp_ptr; char_u *dict = NULL; int dict_f = 0; struct Completion *old_match; - if (!started_completion) + if (!compl_started) { for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next) ins_buf->b_scanned = 0; found_all = FALSE; ins_buf = curbuf; - e_cpt = (continue_status & CONT_LOCAL) + e_cpt = (compl_cont_status & CONT_LOCAL) ? (char_u *)"." : curbuf->b_p_cpt; last_match_pos = first_match_pos = *ini; } - old_match = curr_match; /* remember the last current match */ + old_match = compl_curr_match; /* remember the last current match */ pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos; /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */ for (;;) { found_new_match = FAIL; - /* For ^N/^P pick a new entry from e_cpt if started_completion is off, + /* For ^N/^P pick a new entry from e_cpt if compl_started is off, * or if found_all says this entry is done. For ^X^L only use the * entries from 'complete' that look in loaded buffers. */ if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE) - && (!started_completion || found_all)) + && (!compl_started || found_all)) { found_all = FALSE; while (*e_cpt == ',' || *e_cpt == ' ') @@ -2811,7 +2734,7 @@ ins_compl_get_exp(ini, dir) /* Scan a buffer, but not the current one. */ if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */ { - started_completion = TRUE; + compl_started = TRUE; first_match_pos.col = last_match_pos.col = 0; first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1; last_match_pos.lnum = 0; @@ -2883,10 +2806,10 @@ ins_compl_get_exp(ini, dir) #ifdef FEAT_FIND_ID case CTRL_X_PATH_PATTERNS: case CTRL_X_PATH_DEFINES: - find_pattern_in_path(complete_pat, dir, - (int)STRLEN(complete_pat), FALSE, FALSE, + find_pattern_in_path(compl_pattern, dir, + (int)STRLEN(compl_pattern), FALSE, FALSE, (type == CTRL_X_PATH_DEFINES - && !(continue_status & CONT_SOL)) + && !(compl_cont_status & CONT_SOL)) ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND, (linenr_T)1, (linenr_T)MAXLNUM); break; @@ -2903,7 +2826,7 @@ ins_compl_get_exp(ini, dir) : (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)), - complete_pat, dir, + compl_pattern, dir, dict ? dict_f : 0, type == CTRL_X_THESAURUS); dict = NULL; break; @@ -2911,11 +2834,11 @@ ins_compl_get_exp(ini, dir) case CTRL_X_TAGS: /* set p_ic according to p_ic, p_scs and pat for find_tags(). */ save_p_ic = p_ic; - p_ic = ignorecase(complete_pat); + p_ic = ignorecase(compl_pattern); /* Find up to TAG_MANY matches. Avoids that an enourmous number - * of matches is found when complete_pat is empty */ - if (find_tags(complete_pat, &num_matches, &matches, + * of matches is found when compl_pattern is empty */ + if (find_tags(compl_pattern, &num_matches, &matches, TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) @@ -2926,19 +2849,19 @@ ins_compl_get_exp(ini, dir) break; case CTRL_X_FILES: - if (expand_wildcards(1, &complete_pat, &num_matches, &matches, + if (expand_wildcards(1, &compl_pattern, &num_matches, &matches, EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) { /* May change home directory back to "~". */ - tilde_replace(complete_pat, num_matches, matches); + tilde_replace(compl_pattern, num_matches, matches); ins_compl_add_matches(num_matches, matches, dir); } break; case CTRL_X_CMDLINE: - if (expand_cmdline(&complete_xp, complete_pat, - (int)STRLEN(complete_pat), + if (expand_cmdline(&compl_xp, compl_pattern, + (int)STRLEN(compl_pattern), &num_matches, &matches) == EXPAND_OK) ins_compl_add_matches(num_matches, matches, dir); break; @@ -2946,12 +2869,19 @@ ins_compl_get_exp(ini, dir) #ifdef FEAT_COMPL_FUNC case CTRL_X_FUNCTION: num_matches = expand_by_function(first_match_pos.lnum, - first_match_pos.col, complete_pat, &matches); + first_match_pos.col, compl_pattern, &matches); if (num_matches > 0) ins_compl_add_matches(num_matches, matches, dir); break; #endif + case CTRL_X_OCCULT: + num_matches = expand_occult(first_match_pos.lnum, + first_match_pos.col, compl_pattern, &matches); + if (num_matches > 0) + ins_compl_add_matches(num_matches, matches, dir); + break; + default: /* normal ^P/^N and ^X^L */ /* * If 'infercase' is set, don't use 'smartcase' here @@ -2959,6 +2889,7 @@ ins_compl_get_exp(ini, dir) save_p_scs = p_scs; if (ins_buf->b_p_inf) p_scs = FALSE; + /* buffers other than curbuf are scanned from the beginning or the * end but never from the middle, thus setting nowrapscan in this * buffers is a good idea, on the other hand, we always set @@ -2975,17 +2906,17 @@ ins_compl_get_exp(ini, dir) /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has * added a word that was at the beginning of the line */ if ( ctrl_x_mode == CTRL_X_WHOLE_LINE - || (continue_status & CONT_SOL)) + || (compl_cont_status & CONT_SOL)) found_new_match = search_for_exact_line(ins_buf, pos, - dir, complete_pat); + dir, compl_pattern); else found_new_match = searchit(NULL, ins_buf, pos, dir, - complete_pat, 1L, SEARCH_KEEP + SEARCH_NFMSG, + compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST); - if (!started_completion) + if (!compl_started) { - /* set started_completion even on fail */ - started_completion = TRUE; + /* set compl_started even on fail */ + compl_started = TRUE; first_match_pos = *pos; last_match_pos = *pos; } @@ -3000,14 +2931,14 @@ ins_compl_get_exp(ini, dir) } /* when ADDING, the text before the cursor matches, skip it */ - if ( (continue_status & CONT_ADDING) && ins_buf == curbuf + if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf && ini->lnum == pos->lnum && ini->col == pos->col) continue; ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col; if (ctrl_x_mode == CTRL_X_WHOLE_LINE) { - if (continue_status & CONT_ADDING) + if (compl_cont_status & CONT_ADDING) { if (pos->lnum >= ins_buf->b_ml.ml_line_count) continue; @@ -3019,10 +2950,11 @@ ins_compl_get_exp(ini, dir) } else { - tmp_ptr = ptr; - if (continue_status & CONT_ADDING) + char_u *tmp_ptr = ptr; + + if (compl_cont_status & CONT_ADDING) { - tmp_ptr += completion_length; + tmp_ptr += compl_length; /* Skip if already inside a word. */ if (vim_iswordp(tmp_ptr)) continue; @@ -3033,15 +2965,15 @@ ins_compl_get_exp(ini, dir) tmp_ptr = find_word_end(tmp_ptr); len = (int)(tmp_ptr - ptr); - if ((continue_status & CONT_ADDING) - && len == completion_length) + if ((compl_cont_status & CONT_ADDING) + && len == compl_length) { if (pos->lnum < ins_buf->b_ml.ml_line_count) { /* Try next line, if any. the new word will be * "join" as if the normal command "J" was used. * IOSIZE is always greater than - * completion_length, so the next STRNCPY always + * compl_length, so the next STRNCPY always * works -- Acevedo */ STRNCPY(IObuff, ptr, len); ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); @@ -3075,7 +3007,7 @@ ins_compl_get_exp(ini, dir) IObuff[len] = NUL; ptr = IObuff; } - if (len == completion_length) + if (len == compl_length) continue; } } @@ -3090,24 +3022,24 @@ ins_compl_get_exp(ini, dir) p_scs = save_p_scs; p_ws = save_p_ws; } - /* check if curr_match has changed, (e.g. other type of expansion - * added somenthing) */ - if (curr_match != old_match) + /* check if compl_curr_match has changed, (e.g. other type of + * expansion added somenthing) */ + if (compl_curr_match != old_match) found_new_match = OK; /* break the loop for specialized modes (use 'complete' just for the * generic ctrl_x_mode == 0) or when we've found a new match */ if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE) - || found_new_match != FAIL) + || found_new_match != FAIL) break; /* Mark a buffer scanned when it has been scanned completely */ if (type == 0 || type == CTRL_X_PATH_PATTERNS) ins_buf->b_scanned = TRUE; - started_completion = FALSE; + compl_started = FALSE; } - started_completion = TRUE; + compl_started = TRUE; if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE) && *e_cpt == NUL) /* Got to end of 'complete' */ @@ -3119,11 +3051,11 @@ ins_compl_get_exp(ini, dir) i = ins_compl_make_cyclic(); /* If several matches were added (FORWARD) or the search failed and has - * just been made cyclic then we have to move curr_match to the next or - * previous entry (if any) -- Acevedo */ - curr_match = dir == FORWARD ? old_match->next : old_match->prev; - if (curr_match == NULL) - curr_match = old_match; + * just been made cyclic then we have to move compl_curr_match to the next + * or previous entry (if any) -- Acevedo */ + compl_curr_match = dir == FORWARD ? old_match->next : old_match->prev; + if (compl_curr_match == NULL) + compl_curr_match = old_match; return i; } @@ -3137,7 +3069,7 @@ ins_compl_delete() * In insert mode: Delete the typed part. * In replace mode: Put the old characters back, if any. */ - i = complete_col + (continue_status & CONT_ADDING ? completion_length : 0); + i = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); backspace_until_column(i); changed_cline_bef_curs(); } @@ -3146,7 +3078,7 @@ ins_compl_delete() static void ins_compl_insert() { - ins_bytes(shown_match->str + curwin->w_cursor.col - complete_col); + ins_bytes(compl_shown_match->str + curwin->w_cursor.col - compl_col); } /* @@ -3158,8 +3090,8 @@ ins_compl_insert() * the ones found so far. * Return the total number of matches, or -1 if still unknown -- webb. * - * curr_match is currently being used by ins_compl_get_exp(), so we use - * shown_match here. + * compl_curr_match is currently being used by ins_compl_get_exp(), so we use + * compl_shown_match here. * * Note that this function may be called recursively once only. First with * allow_get_expansion TRUE, which calls ins_compl_get_exp(), which in turn @@ -3177,21 +3109,22 @@ ins_compl_next(allow_get_expansion) /* Delete old text to be replaced */ ins_compl_delete(); } - completion_pending = FALSE; - if (shown_direction == FORWARD && shown_match->next != NULL) - shown_match = shown_match->next; - else if (shown_direction == BACKWARD && shown_match->prev != NULL) - shown_match = shown_match->prev; + compl_pending = FALSE; + if (compl_shows_dir == FORWARD && compl_shown_match->next != NULL) + compl_shown_match = compl_shown_match->next; + else if (compl_shows_dir == BACKWARD && compl_shown_match->prev != NULL) + compl_shown_match = compl_shown_match->prev; else { - completion_pending = TRUE; + compl_pending = TRUE; if (allow_get_expansion) { - num_matches = ins_compl_get_exp(&initial_pos, complete_direction); - if (completion_pending) + num_matches = ins_compl_get_exp(&compl_startpos, + compl_direction); + if (compl_pending) { - if (complete_direction == shown_direction) - shown_match = curr_match; + if (compl_direction == compl_shows_dir) + compl_shown_match = compl_curr_match; } } else @@ -3215,15 +3148,15 @@ ins_compl_next(allow_get_expansion) * Show the file name for the match (if any) * Truncate the file name to avoid a wait for return. */ - if (shown_match->fname != NULL) + if (compl_shown_match->fname != NULL) { STRCPY(IObuff, "match in file "); - i = (vim_strsize(shown_match->fname) + 16) - sc_col; + i = (vim_strsize(compl_shown_match->fname) + 16) - sc_col; if (i <= 0) i = 0; else STRCAT(IObuff, "<"); - STRCAT(IObuff, shown_match->fname + i); + STRCAT(IObuff, compl_shown_match->fname + i); msg(IObuff); redraw_cmdline = FALSE; /* don't overwrite! */ } @@ -3234,7 +3167,7 @@ ins_compl_next(allow_get_expansion) /* * Call this while finding completions, to check whether the user has hit a key * that should change the currently displayed completion, or exit completion - * mode. Also, when completion_pending is TRUE, show a completion as soon as + * mode. Also, when compl_pending is TRUE, show a completion as soon as * possible. -- webb */ void @@ -3263,15 +3196,15 @@ ins_compl_check_keys() { c = safe_vgetc(); /* Eat the character */ if (c == Ctrl_P || c == Ctrl_L) - shown_direction = BACKWARD; + compl_shows_dir = BACKWARD; else - shown_direction = FORWARD; + compl_shows_dir = FORWARD; (void)ins_compl_next(FALSE); } else if (c != Ctrl_R) - completion_interrupted = TRUE; + compl_interrupted = TRUE; } - if (completion_pending && !got_int) + if (compl_pending && !got_int) (void)ins_compl_next(FALSE); } @@ -3282,17 +3215,18 @@ ins_compl_check_keys() */ static int ins_complete(c) - int c; + int c; { - char_u *line; - char_u *tmp_ptr = NULL; /* init for gcc */ - int temp = 0; + char_u *line; + int startcol = 0; /* column where searched text starts */ + colnr_T curs_col; /* cursor column */ + int n; if (c == Ctrl_P || c == Ctrl_L) - complete_direction = BACKWARD; + compl_direction = BACKWARD; else - complete_direction = FORWARD; - if (!started_completion) + compl_direction = FORWARD; + if (!compl_started) { /* First time we hit ^N or ^P (in a row, I mean) */ @@ -3310,138 +3244,143 @@ ins_complete(c) return FAIL; line = ml_get(curwin->w_cursor.lnum); - complete_col = curwin->w_cursor.col; + curs_col = curwin->w_cursor.col; /* if this same ctrl_x_mode has been interrupted use the text from - * "initial_pos" to the cursor as a pattern to add a new word instead - * of expand the one before the cursor, in word-wise if "initial_pos" + * "compl_startpos" to the cursor as a pattern to add a new word + * instead of expand the one before the cursor, in word-wise if + * "compl_startpos" * is not in the same line as the cursor then fix it (the line has * been split because it was longer than 'tw'). if SOL is set then * skip the previous pattern, a word at the beginning of the line has * been inserted, we'll look for that -- Acevedo. */ - if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode) + if ((compl_cont_status & CONT_INTRPT) && compl_cont_mode == ctrl_x_mode) { /* * it is a continued search */ - continue_status &= ~CONT_INTRPT; /* remove INTRPT */ + compl_cont_status &= ~CONT_INTRPT; /* remove INTRPT */ if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS || ctrl_x_mode == CTRL_X_PATH_DEFINES) { - if (initial_pos.lnum != curwin->w_cursor.lnum) + if (compl_startpos.lnum != curwin->w_cursor.lnum) { - /* line (probably) wrapped, set initial_pos to the first - * non_blank in the line, if it is not a wordchar include - * it to get a better pattern, but then we don't want the - * "\\<" prefix, check it bellow */ - tmp_ptr = skipwhite(line); - initial_pos.col = (colnr_T) (tmp_ptr - line); - initial_pos.lnum = curwin->w_cursor.lnum; - continue_status &= ~CONT_SOL; /* clear SOL if present */ + /* line (probably) wrapped, set compl_startpos to the + * first non_blank in the line, if it is not a wordchar + * include it to get a better pattern, but then we don't + * want the "\\<" prefix, check it bellow */ + compl_col = (colnr_T)(skipwhite(line) - line); + compl_startpos.col = compl_col; + compl_startpos.lnum = curwin->w_cursor.lnum; + compl_cont_status &= ~CONT_SOL; /* clear SOL if present */ } else { /* S_IPOS was set when we inserted a word that was at the * beginning of the line, which means that we'll go to SOL - * mode but first we need to redefine initial_pos */ - if (continue_status & CONT_S_IPOS) + * mode but first we need to redefine compl_startpos */ + if (compl_cont_status & CONT_S_IPOS) { - continue_status |= CONT_SOL; - initial_pos.col = (colnr_T) (skipwhite(line + completion_length + - initial_pos.col) - line); + compl_cont_status |= CONT_SOL; + compl_startpos.col = (colnr_T)(skipwhite( + line + compl_length + + compl_startpos.col) - line); } - tmp_ptr = line + initial_pos.col; + compl_col = compl_startpos.col; } - temp = curwin->w_cursor.col - (int)(tmp_ptr - line); + compl_length = curwin->w_cursor.col - (int)compl_col; /* IObuf is used to add a "word from the next line" would we * have enough space? just being paranoic */ #define MIN_SPACE 75 - if (temp > (IOSIZE - MIN_SPACE)) + if (compl_length > (IOSIZE - MIN_SPACE)) { - continue_status &= ~CONT_SOL; - temp = (IOSIZE - MIN_SPACE); - tmp_ptr = line + curwin->w_cursor.col - temp; + compl_cont_status &= ~CONT_SOL; + compl_length = (IOSIZE - MIN_SPACE); + compl_col = curwin->w_cursor.col - compl_length; } - continue_status |= CONT_ADDING | CONT_N_ADDS; - if (temp < 1) - continue_status &= CONT_LOCAL; + compl_cont_status |= CONT_ADDING | CONT_N_ADDS; + if (compl_length < 1) + compl_cont_status &= CONT_LOCAL; } else if (ctrl_x_mode == CTRL_X_WHOLE_LINE) - continue_status = CONT_ADDING | CONT_N_ADDS; + compl_cont_status = CONT_ADDING | CONT_N_ADDS; else - continue_status = 0; + compl_cont_status = 0; } else - continue_status &= CONT_LOCAL; + compl_cont_status &= CONT_LOCAL; - if (!(continue_status & CONT_ADDING)) /* normal expansion */ + if (!(compl_cont_status & CONT_ADDING)) /* normal expansion */ { - continue_mode = ctrl_x_mode; + compl_cont_mode = ctrl_x_mode; if (ctrl_x_mode != 0) /* Remove LOCAL if ctrl_x_mode != 0 */ - continue_status = 0; - continue_status |= CONT_N_ADDS; - initial_pos = curwin->w_cursor; - temp = (int)complete_col; - tmp_ptr = line; + compl_cont_status = 0; + compl_cont_status |= CONT_N_ADDS; + compl_startpos = curwin->w_cursor; + startcol = (int)curs_col; + compl_col = 0; } /* Work out completion pattern and original text -- webb */ if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT)) { - if ( (continue_status & CONT_SOL) + if ((compl_cont_status & CONT_SOL) || ctrl_x_mode == CTRL_X_PATH_DEFINES) { - if (!(continue_status & CONT_ADDING)) + if (!(compl_cont_status & CONT_ADDING)) { - while (--temp >= 0 && vim_isIDc(line[temp])) + while (--startcol >= 0 && vim_isIDc(line[startcol])) ; - tmp_ptr += ++temp; - temp = complete_col - temp; + compl_col += ++startcol; + compl_length = curs_col - startcol; } if (p_ic) - complete_pat = str_foldcase(tmp_ptr, temp, NULL, 0); + compl_pattern = str_foldcase(line + compl_col, + compl_length, NULL, 0); else - complete_pat = vim_strnsave(tmp_ptr, temp); - if (complete_pat == NULL) + compl_pattern = vim_strnsave(line + compl_col, + compl_length); + if (compl_pattern == NULL) return FAIL; } - else if (continue_status & CONT_ADDING) + else if (compl_cont_status & CONT_ADDING) { char_u *prefix = (char_u *)"\\<"; /* we need 3 extra chars, 1 for the NUL and * 2 >= strlen(prefix) -- Acevedo */ - complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3); - if (complete_pat == NULL) + compl_pattern = alloc(quote_meta(NULL, line + compl_col, + compl_length) + 3); + if (compl_pattern == NULL) return FAIL; - if (!vim_iswordp(tmp_ptr) - || (tmp_ptr > line + if (!vim_iswordp(line + compl_col) + || (compl_col > 0 && ( #ifdef FEAT_MBYTE - vim_iswordp(mb_prevptr(line, tmp_ptr)) + vim_iswordp(mb_prevptr(line, line + compl_col)) #else - vim_iswordc(*(tmp_ptr - 1)) + vim_iswordc(line[compl_col - 1]) #endif ))) prefix = (char_u *)""; - STRCPY((char *)complete_pat, prefix); - (void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp); + STRCPY((char *)compl_pattern, prefix); + (void)quote_meta(compl_pattern + STRLEN(prefix), + line + compl_col, compl_length); } - else if ( + else if (--startcol < 0 || #ifdef FEAT_MBYTE - --temp < 0 || !vim_iswordp(mb_prevptr(line, - line + temp + 1)) + !vim_iswordp(mb_prevptr(line, line + startcol + 1)) #else - --temp < 0 || !vim_iswordc(line[temp]) + !vim_iswordc(line[startcol]) #endif ) { /* Match any word of at least two chars */ - complete_pat = vim_strsave((char_u *)"\\<\\k\\k"); - if (complete_pat == NULL) + compl_pattern = vim_strsave((char_u *)"\\<\\k\\k"); + if (compl_pattern == NULL) return FAIL; - tmp_ptr += complete_col; - temp = 0; + compl_col += curs_col; + compl_length = 0; } else { @@ -3453,80 +3392,86 @@ ins_complete(c) int base_class; int head_off; - temp -= (*mb_head_off)(line, line + temp); - base_class = mb_get_class(line + temp); - while (--temp >= 0) + startcol -= (*mb_head_off)(line, line + startcol); + base_class = mb_get_class(line + startcol); + while (--startcol >= 0) { - head_off = (*mb_head_off)(line, line + temp); - if (base_class != mb_get_class(line + temp - head_off)) + head_off = (*mb_head_off)(line, line + startcol); + if (base_class != mb_get_class(line + startcol + - head_off)) break; - temp -= head_off; + startcol -= head_off; } } else #endif - while (--temp >= 0 && vim_iswordc(line[temp])) + while (--startcol >= 0 && vim_iswordc(line[startcol])) ; - tmp_ptr += ++temp; - if ((temp = (int)complete_col - temp) == 1) + compl_col += ++startcol; + compl_length = (int)curs_col - startcol; + if (compl_length == 1) { /* Only match word with at least two chars -- webb * there's no need to call quote_meta, * alloc(7) is enough -- Acevedo */ - complete_pat = alloc(7); - if (complete_pat == NULL) + compl_pattern = alloc(7); + if (compl_pattern == NULL) return FAIL; - STRCPY((char *)complete_pat, "\\<"); - (void)quote_meta(complete_pat + 2, tmp_ptr, 1); - STRCAT((char *)complete_pat, "\\k"); + STRCPY((char *)compl_pattern, "\\<"); + (void)quote_meta(compl_pattern + 2, line + compl_col, 1); + STRCAT((char *)compl_pattern, "\\k"); } else { - complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3); - if (complete_pat == NULL) + compl_pattern = alloc(quote_meta(NULL, line + compl_col, + compl_length) + 3); + if (compl_pattern == NULL) return FAIL; - STRCPY((char *)complete_pat, "\\<"); - (void)quote_meta(complete_pat + 2, tmp_ptr, temp); + STRCPY((char *)compl_pattern, "\\<"); + (void)quote_meta(compl_pattern + 2, line + compl_col, + compl_length); } } } else if (ctrl_x_mode == CTRL_X_WHOLE_LINE) { - tmp_ptr = skipwhite(line); - temp = (int)complete_col - (int)(tmp_ptr - line); - if (temp < 0) /* cursor in indent: empty pattern */ - temp = 0; + compl_col = skipwhite(line) - line; + compl_length = (int)curs_col - (int)compl_col; + if (compl_length < 0) /* cursor in indent: empty pattern */ + compl_length = 0; if (p_ic) - complete_pat = str_foldcase(tmp_ptr, temp, NULL, 0); + compl_pattern = str_foldcase(line + compl_col, compl_length, + NULL, 0); else - complete_pat = vim_strnsave(tmp_ptr, temp); - if (complete_pat == NULL) + compl_pattern = vim_strnsave(line + compl_col, compl_length); + if (compl_pattern == NULL) return FAIL; } else if (ctrl_x_mode == CTRL_X_FILES) { - while (--temp >= 0 && vim_isfilec(line[temp])) + while (--startcol >= 0 && vim_isfilec(line[startcol])) ; - tmp_ptr += ++temp; - temp = (int)complete_col - temp; - complete_pat = addstar(tmp_ptr, temp, EXPAND_FILES); - if (complete_pat == NULL) + compl_col += ++startcol; + compl_length = (int)curs_col - startcol; + compl_pattern = addstar(line + compl_col, compl_length, + EXPAND_FILES); + if (compl_pattern == NULL) return FAIL; } else if (ctrl_x_mode == CTRL_X_CMDLINE) { - complete_pat = vim_strnsave(line, complete_col); - if (complete_pat == NULL) + compl_pattern = vim_strnsave(line, curs_col); + if (compl_pattern == NULL) return FAIL; - set_cmd_context(&complete_xp, complete_pat, - (int)STRLEN(complete_pat), complete_col); - if (complete_xp.xp_context == EXPAND_UNSUCCESSFUL - || complete_xp.xp_context == EXPAND_NOTHING) + set_cmd_context(&compl_xp, compl_pattern, + (int)STRLEN(compl_pattern), curs_col); + if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL + || compl_xp.xp_context == EXPAND_NOTHING) return FAIL; - temp = (int)(complete_xp.xp_pattern - complete_pat); - tmp_ptr = line + temp; - temp = complete_col - temp; + startcol = (int)(compl_xp.xp_pattern - compl_pattern); + compl_col = startcol; + compl_length = curs_col - startcol; } #ifdef FEAT_COMPL_FUNC else if (ctrl_x_mode == CTRL_X_FUNCTION) @@ -3538,29 +3483,49 @@ ins_complete(c) */ char_u *lenstr; int keeplen = 0; + char_u *line_copy = vim_strsave(line); /* Call 'completefunc' and get pattern length as a string */ - lenstr = call_completefunc(line, NULL, complete_col, 1); + lenstr = call_completefunc(line_copy, NULL, curs_col, 1); + vim_free(line_copy); if (lenstr == NULL) return FAIL; keeplen = atoi((char *)lenstr); vim_free(lenstr); if (keeplen < 0) return FAIL; - if ((colnr_T)keeplen > complete_col) - keeplen = complete_col; - - /* Setup variables for completion */ - tmp_ptr = line + keeplen; - temp = complete_col - keeplen; - complete_pat = vim_strnsave(tmp_ptr, temp); - if (complete_pat == NULL) + if ((colnr_T)keeplen > curs_col) + keeplen = curs_col; + + /* Setup variables for completion. Need to obtain "line" again, + * it may have become invalid. */ + line = ml_get(curwin->w_cursor.lnum); + compl_col = keeplen; + compl_length = curs_col - keeplen; + compl_pattern = vim_strnsave(line + compl_col, compl_length); + if (compl_pattern == NULL) return FAIL; } #endif - complete_col = (colnr_T) (tmp_ptr - line); + else if (ctrl_x_mode == CTRL_X_OCCULT) + { + /* TODO: let language-specific function handle locating the text + * to be completed or use 'coupler' option. */ + while (--startcol >= 0 && vim_isIDc(line[startcol])) + ; + compl_col += ++startcol; + compl_length = (int)curs_col - startcol; + compl_pattern = vim_strnsave(line + compl_col, compl_length); + if (compl_pattern == NULL) + return FAIL; + } + else + { + EMSG2(_(e_intern2), "ins_complete()"); + return FAIL; + } - if (continue_status & CONT_ADDING) + if (compl_cont_status & CONT_ADDING) { edit_submode_pre = (char_u *)_(" Adding"); if (ctrl_x_mode == CTRL_X_WHOLE_LINE) @@ -3571,39 +3536,38 @@ ins_complete(c) curbuf->b_p_com = (char_u *)""; #endif - initial_pos.lnum = curwin->w_cursor.lnum; - initial_pos.col = complete_col; + compl_startpos.lnum = curwin->w_cursor.lnum; + compl_startpos.col = compl_col; ins_eol('\r'); #ifdef FEAT_COMMENTS curbuf->b_p_com = old; #endif - tmp_ptr = (char_u *)""; - temp = 0; - complete_col = curwin->w_cursor.col; + compl_length = 0; + compl_col = curwin->w_cursor.col; } } else { edit_submode_pre = NULL; - initial_pos.col = complete_col; + compl_startpos.col = compl_col; } - if (continue_status & CONT_LOCAL) - edit_submode = (char_u *)_(ctrl_x_msgs[2]); + if (compl_cont_status & CONT_LOCAL) + edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]); else edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); - completion_length = temp; - /* Always add completion for the original text. Note that - * "original_text" itself (not a copy) is added, it will be freed when - * the list of matches is freed. */ - if ((original_text = vim_strnsave(tmp_ptr, temp)) == NULL - || ins_compl_add(original_text, -1, NULL, 0, ORIGINAL_TEXT) != OK) - { - vim_free(complete_pat); - complete_pat = NULL; - vim_free(original_text); + * "compl_orig_text" itself (not a copy) is added, it will be freed + * when the list of matches is freed. */ + compl_orig_text = vim_strnsave(line + compl_col, compl_length); + if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, + -1, NULL, 0, ORIGINAL_TEXT) != OK) + { + vim_free(compl_pattern); + compl_pattern = NULL; + vim_free(compl_orig_text); + compl_orig_text = NULL; return FAIL; } @@ -3618,19 +3582,19 @@ ins_complete(c) out_flush(); } - shown_match = curr_match; - shown_direction = complete_direction; + compl_shown_match = compl_curr_match; + compl_shows_dir = compl_direction; /* * Find next match. */ - temp = ins_compl_next(TRUE); + n = ins_compl_next(TRUE); - if (temp > 1) /* all matches have been found */ - completion_matches = temp; - curr_match = shown_match; - complete_direction = shown_direction; - completion_interrupted = FALSE; + if (n > 1) /* all matches have been found */ + compl_matches = n; + compl_curr_match = compl_shown_match; + compl_direction = compl_shows_dir; + compl_interrupted = FALSE; /* eat the ESC to avoid leaving insert mode */ if (got_int && !global_busy) @@ -3639,43 +3603,43 @@ ins_complete(c) got_int = FALSE; } - /* we found no match if the list has only the original_text-entry */ - if (first_match == first_match->next) + /* we found no match if the list has only the "compl_orig_text"-entry */ + if (compl_first_match == compl_first_match->next) { - edit_submode_extra = (continue_status & CONT_ADDING) - && completion_length > 1 + edit_submode_extra = (compl_cont_status & CONT_ADDING) + && compl_length > 1 ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf); edit_submode_highl = HLF_E; /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode, * because we couldn't expand anything at first place, but if we used * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word * (such as M in M'exico) if not tried already. -- Acevedo */ - if ( completion_length > 1 - || (continue_status & CONT_ADDING) + if ( compl_length > 1 + || (compl_cont_status & CONT_ADDING) || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_PATH_PATTERNS && ctrl_x_mode != CTRL_X_PATH_DEFINES)) - continue_status &= ~CONT_N_ADDS; + compl_cont_status &= ~CONT_N_ADDS; } - if (curr_match->original & CONT_S_IPOS) - continue_status |= CONT_S_IPOS; + if (compl_curr_match->original & CONT_S_IPOS) + compl_cont_status |= CONT_S_IPOS; else - continue_status &= ~CONT_S_IPOS; + compl_cont_status &= ~CONT_S_IPOS; if (edit_submode_extra == NULL) { - if (curr_match->original & ORIGINAL_TEXT) + if (compl_curr_match->original & ORIGINAL_TEXT) { edit_submode_extra = (char_u *)_("Back at original"); edit_submode_highl = HLF_W; } - else if (continue_status & CONT_S_IPOS) + else if (compl_cont_status & CONT_S_IPOS) { edit_submode_extra = (char_u *)_("Word from other line"); edit_submode_highl = HLF_COUNT; } - else if (curr_match->next == curr_match->prev) + else if (compl_curr_match->next == compl_curr_match->prev) { edit_submode_extra = (char_u *)_("The only match"); edit_submode_highl = HLF_COUNT; @@ -3683,18 +3647,18 @@ ins_complete(c) else { /* Update completion sequence number when needed. */ - if (curr_match->number == -1) + if (compl_curr_match->number == -1) { int number = 0; struct Completion *match; - if (complete_direction == FORWARD) + if (compl_direction == FORWARD) { /* search backwards for the first valid (!= -1) number. * This should normally succeed already at the first loop * cycle, so it's fast! */ - for (match = curr_match->prev; match != NULL - && match != first_match; match = match->prev) + for (match = compl_curr_match->prev; match != NULL + && match != compl_first_match; match = match->prev) if (match->number != -1) { number = match->number; @@ -3712,8 +3676,8 @@ ins_complete(c) /* search forwards (upwards) for the first valid (!= -1) * number. This should normally succeed already at the * first loop cycle, so it's fast! */ - for (match = curr_match->next; match != NULL - && match != first_match; match = match->next) + for (match = compl_curr_match->next; match != NULL + && match != compl_first_match; match = match->next) if (match->number != -1) { number = match->number; @@ -3730,16 +3694,17 @@ ins_complete(c) /* The match should always have a sequnce number now, this is just * a safety check. */ - if (curr_match->number != -1) + if (compl_curr_match->number != -1) { /* Space for 10 text chars. + 2x10-digit no.s */ static char_u match_ref[31]; - if (completion_matches > 0) + if (compl_matches > 0) sprintf((char *)IObuff, _("match %d of %d"), - curr_match->number, completion_matches); + compl_curr_match->number, compl_matches); else - sprintf((char *)IObuff, _("match %d"), curr_match->number); + sprintf((char *)IObuff, _("match %d"), + compl_curr_match->number); vim_strncpy(match_ref, IObuff, 30); edit_submode_extra = match_ref; edit_submode_highl = HLF_R; @@ -6268,6 +6233,59 @@ ins_ctrl_g() } /* + * CTRL-^ in Insert mode. + */ + static void +ins_ctrl_hat() +{ + if (map_to_exists_mode((char_u *)"", LANGMAP)) + { + /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ + if (State & LANGMAP) + { + curbuf->b_p_iminsert = B_IMODE_NONE; + State &= ~LANGMAP; + } + else + { + curbuf->b_p_iminsert = B_IMODE_LMAP; + State |= LANGMAP; +#ifdef USE_IM_CONTROL + im_set_active(FALSE); +#endif + } + } +#ifdef USE_IM_CONTROL + else + { + /* There are no ":lmap" mappings, toggle IM */ + if (im_get_status()) + { + curbuf->b_p_iminsert = B_IMODE_NONE; + im_set_active(FALSE); + } + else + { + curbuf->b_p_iminsert = B_IMODE_IM; + State &= ~LANGMAP; + im_set_active(TRUE); + } + } +#endif + set_iminsert_global(); + showmode(); +#ifdef FEAT_GUI + /* may show different cursor shape or color */ + if (gui.in_use) + gui_update_cursor(TRUE, FALSE); +#endif +#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP) + /* Show/unshow value of 'keymap' in status lines. */ + status_redraw_curbuf(); +#endif +} + +/* * Handle ESC in insert mode. * Returns TRUE when leaving insert mode, FALSE when going to repeat the * insert. @@ -6280,6 +6298,9 @@ ins_esc(count, cmdchar) int temp; static int disabled_redraw = FALSE; +#ifdef FEAT_SYN_HL + check_spell_redraw(); +#endif #if defined(FEAT_HANGULIN) # if defined(ESC_CHG_TO_ENG_MODE) hangul_input_state_set(0); @@ -6521,6 +6542,62 @@ ins_start_select(c) #endif /* + * <Insert> key in Insert mode: toggle insert/remplace mode. + */ + static void +ins_insert(replaceState) + int replaceState; +{ +#ifdef FEAT_FKMAP + if (p_fkmap && p_ri) + { + beep_flush(); + EMSG(farsi_text_3); /* encoded in Farsi */ + return; + } +#endif + +#ifdef FEAT_AUTOCMD + set_vim_var_string(VV_INSERTMODE, + (char_u *)((State & REPLACE_FLAG) ? "i" : + replaceState == VREPLACE ? "v" : "r"), 1); + apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf); +#endif + if (State & REPLACE_FLAG) + State = INSERT | (State & LANGMAP); + else + State = replaceState | (State & LANGMAP); + AppendCharToRedobuff(K_INS); + showmode(); +#ifdef CURSOR_SHAPE + ui_cursor_shape(); /* may show different cursor shape */ +#endif +} + +/* + * Pressed CTRL-O in Insert mode. + */ + static void +ins_ctrl_o() +{ +#ifdef FEAT_VREPLACE + if (State & VREPLACE_FLAG) + restart_edit = 'V'; + else +#endif + if (State & REPLACE_FLAG) + restart_edit = 'R'; + else + restart_edit = 'I'; +#ifdef FEAT_VIRTUALEDIT + if (virtual_active()) + ins_at_eol = FALSE; /* cursor always keeps its column */ + else +#endif + ins_at_eol = (gchar_cursor() == NUL); +} + +/* * If the cursor is on an indent, ^T/^D insert/delete one * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". * Always round the indent to 'shiftwith', this is compatible @@ -7792,6 +7869,53 @@ ins_copychar(lnum) return c; } +/* + * CTRL-Y or CTRL-E typed in Insert mode. + */ + static int +ins_ctrl_ey(tc) + int tc; +{ + int c = tc; + +#ifdef FEAT_INS_EXPAND + if (ctrl_x_mode == CTRL_X_SCROLL) + { + if (c == Ctrl_Y) + scrolldown_clamp(); + else + scrollup_clamp(); + redraw_later(VALID); + } + else +#endif + { + c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1)); + if (c != NUL) + { + long tw_save; + + /* The character must be taken literally, insert like it + * was typed after a CTRL-V, and pretend 'textwidth' + * wasn't set. Digits, 'o' and 'x' are special after a + * CTRL-V, don't use it for these. */ + if (c < 256 && !isalnum(c)) + AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ + tw_save = curbuf->b_p_tw; + curbuf->b_p_tw = -1; + insert_special(c, TRUE, FALSE); + curbuf->b_p_tw = tw_save; +#ifdef FEAT_RIGHTLEFT + revins_chars++; + revins_legal++; +#endif + c = Ctrl_V; /* pretend CTRL-V is last character */ + auto_format(FALSE, TRUE); + } + } + return c; +} + #ifdef FEAT_SMARTINDENT /* * Try to do some very smart auto-indenting. |