aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c146
1 files changed, 96 insertions, 50 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index b2abb06075..f2fddc89fe 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -313,6 +313,11 @@ static void insert_enter(InsertState *s)
set_vim_var_string(VV_CHAR, NULL, -1);
ins_apply_autocmds(EVENT_INSERTENTER);
+ // Check for changed highlighting, e.g. for ModeMsg.
+ if (need_highlight_changed) {
+ highlight_changed();
+ }
+
// Make sure the cursor didn't move. Do call check_cursor_col() in
// case the text was modified. Since Insert mode was not started yet
// a call to check_cursor_col() may move the cursor, especially with
@@ -592,7 +597,10 @@ static int insert_check(VimState *state)
s->mincol = curwin->w_wcol;
validate_cursor_col();
- if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
+ if (
+ curwin->w_wcol < s->mincol - tabstop_at(get_nolist_virtcol(),
+ curbuf->b_p_ts,
+ curbuf->b_p_vts_array)
&& curwin->w_wrow == curwin->w_winrow
+ curwin->w_height_inner - 1 - get_scrolloff_value(curwin)
&& (curwin->w_cursor.lnum != curwin->w_topline
@@ -1019,7 +1027,7 @@ static int insert_handle_key(InsertState *s)
break;
case K_EVENT: // some event
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
goto check_pum;
case K_COMMAND: // some command
@@ -1560,7 +1568,7 @@ void edit_putchar(int c, bool highlight)
{
int attr;
- if (curwin->w_grid.chars != NULL || default_grid.chars != NULL) {
+ if (curwin->w_grid_alloc.chars != NULL || default_grid.chars != NULL) {
update_topline(curwin); // just in case w_topline isn't valid
validate_cursor();
if (highlight) {
@@ -1622,11 +1630,11 @@ static void init_prompt(int cmdchar_todo)
ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false);
}
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
changed_bytes(curbuf->b_ml.ml_line_count, 0);
}
if (cmdchar_todo == 'A') {
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
}
if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt)) {
curwin->w_cursor.col = STRLEN(prompt);
@@ -2050,7 +2058,7 @@ static bool check_compl_option(bool dict_opt)
vim_beep(BO_COMPL);
setcursor();
ui_flush();
- os_delay(2000L, false);
+ os_delay(2004L, false);
}
return false;
}
@@ -2311,7 +2319,11 @@ static int ins_compl_add(char_u *const str, int len,
const Direction dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
int flags = flags_arg;
- os_breakcheck();
+ if (flags & CP_FAST) {
+ fast_breakcheck();
+ } else {
+ os_breakcheck();
+ }
#define FREE_CPTEXT(cptext, cptext_allocated) \
do { \
if (cptext != NULL && cptext_allocated) { \
@@ -2515,7 +2527,8 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
- icase ? CP_ICASE : 0, false)) == OK) {
+ CP_FAST | (icase ? CP_ICASE : 0),
+ false)) == OK) {
// If dir was BACKWARD then honor it just once.
dir = FORWARD;
}
@@ -2590,7 +2603,7 @@ void set_completion(colnr_T startcol, list_T *list)
flags |= CP_ICASE;
}
if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
- flags, false) != OK) {
+ flags | CP_FAST, false) != OK) {
return;
}
@@ -3310,8 +3323,8 @@ static int ins_compl_bs(void)
// allow the word to be deleted, we won't match everything.
// Respect the 'backspace' option.
if ((int)(p - line) - (int)compl_col < 0
- || ((int)(p - line) - (int)compl_col == 0
- && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL
+ || ((int)(p - line) - (int)compl_col == 0 && ctrl_x_mode != CTRL_X_OMNI)
+ || ctrl_x_mode == CTRL_X_EVAL
|| (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
- compl_length < 0)) {
return K_BS;
@@ -3926,7 +3939,7 @@ static void ins_compl_add_list(list_T *const list)
// Go through the List with matches and add each of them.
TV_LIST_ITER(list, li, {
- if (ins_compl_add_tv(TV_LIST_ITEM_TV(li), dir) == OK) {
+ if (ins_compl_add_tv(TV_LIST_ITEM_TV(li), dir, true) == OK) {
// If dir was BACKWARD then honor it just once.
dir = FORWARD;
} else if (did_emsg) {
@@ -3965,17 +3978,18 @@ static void ins_compl_add_dict(dict_T *dict)
///
/// @param[in] tv Object to get matches from.
/// @param[in] dir Completion direction.
+/// @param[in] fast use fast_breakcheck() instead of os_breakcheck().
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
/// returned in case of error.
-int ins_compl_add_tv(typval_T *const tv, const Direction dir)
+int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
FUNC_ATTR_NONNULL_ALL
{
const char *word;
bool dup = false;
bool empty = false;
- int flags = 0;
+ int flags = fast ? CP_FAST : 0;
char *(cptext[CPT_COUNT]);
typval_T user_data;
@@ -6241,9 +6255,10 @@ void auto_format(
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
// "cannot happen"
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
- } else
+ coladvance(MAXCOL);
+ } else {
check_cursor_col();
+ }
// Insert mode: If the cursor is now after the end of the line while it
// previously wasn't, the line was broken. Because of the rule above we
@@ -7260,7 +7275,6 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
char_u *p;
char_u *line;
int icase;
- int i;
if (keytyped == NUL) {
// Can happen with CTRL-Y and CTRL-E on a short line.
@@ -7345,8 +7359,9 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
&& p[curwin->w_cursor.col - 1] == ':'
&& p[curwin->w_cursor.col - 2] == ':') {
p[curwin->w_cursor.col - 1] = ' ';
- i = (cin_iscase(p, FALSE) || cin_isscopedecl(p)
- || cin_islabel());
+ const bool i = cin_iscase(p, false)
+ || cin_isscopedecl(p)
+ || cin_islabel();
p = get_cursor_line_ptr();
p[curwin->w_cursor.col - 1] = ':';
if (i) {
@@ -8172,24 +8187,20 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
/*
* Handle deleting one 'shiftwidth' or 'softtabstop'.
*/
- if ( mode == BACKSPACE_CHAR
- && ((p_sta && in_indent)
- || (get_sts_value() != 0
- && curwin->w_cursor.col > 0
- && (*(get_cursor_pos_ptr() - 1) == TAB
- || (*(get_cursor_pos_ptr() - 1) == ' '
- && (!*inserted_space_p
- || arrow_used)))))) {
+ if (mode == BACKSPACE_CHAR
+ && ((p_sta && in_indent)
+ || ((get_sts_value() != 0
+ || tabstop_count(curbuf->b_p_vsts_array))
+ && curwin->w_cursor.col > 0
+ && (*(get_cursor_pos_ptr() - 1) == TAB
+ || (*(get_cursor_pos_ptr() - 1) == ' '
+ && (!*inserted_space_p || arrow_used)))))) {
int ts;
colnr_T vcol;
colnr_T want_vcol;
colnr_T start_vcol;
- *inserted_space_p = FALSE;
- if (p_sta && in_indent)
- ts = get_sw_value(curbuf);
- else
- ts = get_sts_value();
+ *inserted_space_p = false;
// Compute the virtual column where we want to be. Since
// 'showbreak' may get in the way, need to get the last column of
// the previous character.
@@ -8198,7 +8209,14 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
dec_cursor();
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
inc_cursor();
- want_vcol = (want_vcol / ts) * ts;
+ if (p_sta && in_indent) {
+ ts = (int)get_sw_value(curbuf);
+ want_vcol = (want_vcol / ts) * ts;
+ } else {
+ want_vcol = tabstop_start(want_vcol,
+ get_sts_value(),
+ curbuf->b_p_vsts_array);
+ }
// delete characters until we are at or before want_vcol
while (vcol > want_vcol
@@ -8427,8 +8445,8 @@ static void ins_left(void)
// if 'whichwrap' set for cursor in insert mode may go to previous line.
// always break undo when moving upwards/downwards, else undo may break
start_arrow(&tpos);
- --(curwin->w_cursor.lnum);
- coladvance((colnr_T)MAXCOL);
+ curwin->w_cursor.lnum--;
+ coladvance(MAXCOL);
curwin->w_set_curswant = true; // so we stay at the end
} else {
vim_beep(BO_CRSR);
@@ -8462,7 +8480,7 @@ static void ins_end(int c)
tpos = curwin->w_cursor;
if (c == K_C_END)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
curwin->w_curswant = MAXCOL;
start_arrow(&tpos);
@@ -8663,10 +8681,19 @@ static bool ins_tab(void)
can_cindent = false;
}
- // When nothing special, insert TAB like a normal character
+ // When nothing special, insert TAB like a normal character.
if (!curbuf->b_p_et
- && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf))
- && get_sts_value() == 0) {
+ && !(
+ p_sta
+ && ind
+ // These five lines mean 'tabstop' != 'shiftwidth'
+ && ((tabstop_count(curbuf->b_p_vts_array) > 1)
+ || (tabstop_count(curbuf->b_p_vts_array) == 1
+ && tabstop_first(curbuf->b_p_vts_array)
+ != get_sw_value(curbuf))
+ || (tabstop_count(curbuf->b_p_vts_array) == 0
+ && curbuf->b_p_ts != get_sw_value(curbuf))))
+ && tabstop_count(curbuf->b_p_vsts_array) == 0 && get_sts_value() == 0) {
return true;
}
@@ -8680,16 +8707,22 @@ static bool ins_tab(void)
can_si_back = false;
AppendToRedobuff("\t");
- if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
- temp = get_sw_value(curbuf);
- } else if (curbuf->b_p_sts != 0) { // use "softtabstop" when set
- temp = get_sts_value();
- } else { // otherwise use "tabstop"
- temp = (int)curbuf->b_p_ts;
+ if (p_sta && ind) { // insert tab in indent, use 'shiftwidth'
+ temp = (int)get_sw_value(curbuf);
+ temp -= get_nolist_virtcol() % temp;
+ } else if (tabstop_count(curbuf->b_p_vsts_array) > 0
+ || curbuf->b_p_sts != 0) {
+ // use 'softtabstop' when set
+ temp = tabstop_padding(get_nolist_virtcol(),
+ get_sts_value(),
+ curbuf->b_p_vsts_array);
+ } else {
+ // otherwise use 'tabstop'
+ temp = tabstop_padding(get_nolist_virtcol(),
+ curbuf->b_p_ts,
+ curbuf->b_p_vts_array);
}
- temp -= get_nolist_virtcol() % temp;
-
/*
* Insert the first space with ins_char(). It will delete one char in
* replace mode. Insert the rest with ins_str(); it will not delete any
@@ -8710,7 +8743,9 @@ static bool ins_tab(void)
/*
* When 'expandtab' not set: Replace spaces by TABs where possible.
*/
- if (!curbuf->b_p_et && (get_sts_value() || (p_sta && ind))) {
+ if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0
+ || get_sts_value() > 0
+ || (p_sta && ind))) {
char_u *ptr;
char_u *saved_line = NULL; // init for GCC
pos_T pos;
@@ -8807,6 +8842,11 @@ static bool ins_tab(void)
replace_join(repl_off);
}
}
+ if (!(State & VREPLACE_FLAG)) {
+ extmark_splice_cols(curbuf, fpos.lnum - 1, change_col,
+ cursor->col - change_col, fpos.col - change_col,
+ kExtmarkUndo);
+ }
}
cursor->col -= i;
@@ -9118,10 +9158,16 @@ static void ins_try_si(int c)
* Get the value that w_virtcol would have when 'list' is off.
* Unless 'cpo' contains the 'L' flag.
*/
-static colnr_T get_nolist_virtcol(void)
+colnr_T get_nolist_virtcol(void)
{
- if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
+ // check validity of cursor in current buffer
+ if (curwin->w_buffer == NULL || curwin->w_buffer->b_ml.ml_mfp == NULL
+ || curwin->w_cursor.lnum > curwin->w_buffer->b_ml.ml_line_count) {
+ return 0;
+ }
+ if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) {
return getvcol_nolist(&curwin->w_cursor);
+ }
validate_virtcol();
return curwin->w_virtcol;
}