summaryrefslogtreecommitdiffstats
path: root/src/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/edit.c')
-rw-r--r--src/edit.c95
1 files changed, 57 insertions, 38 deletions
diff --git a/src/edit.c b/src/edit.c
index 69ec255..075b39b 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -845,9 +845,10 @@ doESCkey:
did_cursorhold = FALSE;
// ins_redraw() triggers TextChangedI only when no characters
- // are in the typeahead buffer, so only reset curbuf->b_last_changedtick
+ // are in the typeahead buffer, so reset curbuf->b_last_changedtick only
// if the TextChangedI was not blocked by char_avail() (e.g. using :norm!)
- if (!char_avail())
+ // and the TextChangedI autocommand has been triggered.
+ if (!char_avail() && curbuf->b_last_changedtick_i == CHANGEDTICK(curbuf))
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
return (c == Ctrl_O);
}
@@ -3958,10 +3959,9 @@ ins_del(void)
* Delete one character for ins_bs().
*/
static void
-ins_bs_one(colnr_T *vcolp)
+ins_bs_one(void)
{
dec_cursor();
- getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
if (State & REPLACE_FLAG)
{
// Don't delete characters before the insert point when in
@@ -4211,44 +4211,69 @@ ins_bs(
&& (!*inserted_space_p
|| arrow_used))))))
{
- int ts;
- colnr_T vcol;
+ colnr_T vcol = 0;
colnr_T want_vcol;
- colnr_T start_vcol;
+ char_u *line;
+ char_u *ptr;
+ char_u *cursor_ptr;
+ char_u *space_ptr;
+ colnr_T space_vcol = 0;
+ int prev_space = FALSE;
+ colnr_T want_col;
*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.
- getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
- start_vcol = vcol;
- dec_cursor();
- getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
- inc_cursor();
-#ifdef FEAT_VARTABS
- if (p_sta && in_indent)
+
+ space_ptr = ptr = line = ml_get_curline();
+ cursor_ptr = line + curwin->w_cursor.col;
+
+ // Compute virtual column of cursor position, and find the last
+ // whitespace before cursor that is preceded by non-whitespace.
+ // Use chartabsize() so that virtual text and wrapping are ignored.
+ while (ptr < cursor_ptr)
{
- ts = (int)get_sw_value(curbuf);
- want_vcol = (want_vcol / ts) * ts;
+ int cur_space = VIM_ISWHITE(*ptr);
+
+ if (!prev_space && cur_space)
+ {
+ space_ptr = ptr;
+ space_vcol = vcol;
+ }
+ vcol += chartabsize(ptr, vcol);
+ MB_PTR_ADV(ptr);
+ prev_space = cur_space;
}
+
+ // Compute the virtual column where we want to be.
+ want_vcol = vcol > 0 ? vcol - 1 : 0;
+ if (p_sta && in_indent)
+ want_vcol -= want_vcol % (int)get_sw_value(curbuf);
else
+#ifdef FEAT_VARTABS
want_vcol = tabstop_start(want_vcol, get_sts_value(),
curbuf->b_p_vsts_array);
#else
- if (p_sta && in_indent)
- ts = (int)get_sw_value(curbuf);
- else
- ts = (int)get_sts_value();
- want_vcol = (want_vcol / ts) * ts;
+ want_vcol -= want_vcol % (int)get_sts_value();
#endif
- // delete characters until we are at or before want_vcol
- while (vcol > want_vcol && curwin->w_cursor.col > 0
- && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc)))
- ins_bs_one(&vcol);
+ // Find the position to stop backspacing.
+ // Use chartabsize() so that virtual text and wrapping are ignored.
+ while (TRUE)
+ {
+ int size = chartabsize(space_ptr, space_vcol);
- // insert extra spaces until we are at want_vcol
- while (vcol < want_vcol)
+ if (space_vcol + size > want_vcol)
+ break;
+ space_vcol += size;
+ MB_PTR_ADV(space_ptr);
+ }
+ want_col = space_ptr - line;
+
+ // Delete characters until we are at or before want_col.
+ while (curwin->w_cursor.col > want_col)
+ ins_bs_one();
+
+ // Insert extra spaces until we are at want_vcol.
+ for (; space_vcol < want_vcol; space_vcol++)
{
// Remember the first char we inserted
if (curwin->w_cursor.lnum == Insstart_orig.lnum
@@ -4263,13 +4288,7 @@ ins_bs(
if ((State & REPLACE_FLAG))
replace_push(NUL);
}
- getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
}
-
- // If we are now back where we started delete one character. Can
- // happen when using 'sts' and 'linebreak'.
- if (vcol >= start_vcol)
- ins_bs_one(&vcol);
}
/*
@@ -4783,7 +4802,7 @@ ins_pageup(void)
}
tpos = curwin->w_cursor;
- if (onepage(BACKWARD, 1L) == OK)
+ if (pagescroll(BACKWARD, 1L, FALSE) == OK)
{
start_arrow(&tpos);
can_cindent = TRUE;
@@ -4840,7 +4859,7 @@ ins_pagedown(void)
}
tpos = curwin->w_cursor;
- if (onepage(FORWARD, 1L) == OK)
+ if (pagescroll(FORWARD, 1L, FALSE) == OK)
{
start_arrow(&tpos);
can_cindent = TRUE;