aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ops.c35
-rw-r--r--src/nvim/testdir/test_virtualedit.vim16
2 files changed, 40 insertions, 11 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 2a3b7beb8e..ef440a27a2 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1638,12 +1638,25 @@ static void mb_adjust_opend(oparg_T *oap)
/*
* Put character 'c' at position 'lp'
*/
-static inline void pchar(pos_T lp, int c)
+static inline void pbyte(pos_T lp, int c)
{
assert(c <= UCHAR_MAX);
*(ml_get_buf(curbuf, lp.lnum, true) + lp.col) = (char_u)c;
}
+// Replace the character under the cursor with "c".
+// This takes care of multi-byte characters.
+static void replace_character(int c)
+{
+ const int n = State;
+
+ State = REPLACE;
+ ins_char(c);
+ State = n;
+ // Backup to the replaced character.
+ dec_cursor();
+}
+
/*
* Replace a whole area with one character.
*/
@@ -1795,12 +1808,7 @@ int op_replace(oparg_T *oap, int c)
* with a multi-byte and the other way around. */
if (curwin->w_cursor.lnum == oap->end.lnum)
oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n);
- n = State;
- State = REPLACE;
- ins_char(c);
- State = n;
- /* Backup to the replaced character. */
- dec_cursor();
+ replace_character(c);
} else {
if (n == TAB) {
int end_vcol = 0;
@@ -1815,7 +1823,7 @@ int op_replace(oparg_T *oap, int c)
if (curwin->w_cursor.lnum == oap->end.lnum)
getvpos(&oap->end, end_vcol);
}
- pchar(curwin->w_cursor, c);
+ pbyte(curwin->w_cursor, c);
}
} else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum) {
int virtcols = oap->end.coladd;
@@ -1830,9 +1838,14 @@ int op_replace(oparg_T *oap, int c)
coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1);
curwin->w_cursor.col -= (virtcols + 1);
for (; virtcols >= 0; virtcols--) {
- pchar(curwin->w_cursor, c);
- if (inc(&curwin->w_cursor) == -1)
+ if (utf_char2len(c) > 1) {
+ replace_character(c);
+ } else {
+ pbyte(curwin->w_cursor, c);
+ }
+ if (inc(&curwin->w_cursor) == -1) {
break;
+ }
}
}
@@ -2007,7 +2020,7 @@ int swapchar(int op_type, pos_T *pos)
ins_char(nc);
curwin->w_cursor = sp;
} else
- pchar(*pos, nc);
+ pbyte(*pos, nc);
return TRUE;
}
return FALSE;
diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim
index d49025237b..abe79f6a4a 100644
--- a/src/nvim/testdir/test_virtualedit.vim
+++ b/src/nvim/testdir/test_virtualedit.vim
@@ -42,6 +42,22 @@ func Test_paste_end_of_line()
set virtualedit=
endfunc
+func Test_replace_end_of_line()
+ new
+ set virtualedit=all
+ call setline(1, range(20))
+ exe "normal! gg2jv10lr-"
+ call assert_equal(["1", "-----------", "3"], getline(2,4))
+ if has('multi_byte')
+ call setline(1, range(20))
+ exe "normal! gg2jv10lr\<c-k>hh"
+ call assert_equal(["1", "───────────", "3"], getline(2,4))
+ endif
+
+ bwipe!
+ set virtualedit=
+endfunc
+
func Test_edit_CTRL_G()
new
set virtualedit=insert