Problem: When virtualedit is set to all, the cursor is supposed to be
permitted to reside anywhere, including on the virtual space
beyond the end of the buffer's text. Switching modes triggered
a routine that "fixed" a cursor that was past the end of the
line by shifting it back to the last actual character in the
line and compensating with a virtual column offset. While
visually identical, this re-encoding changed the underlying
byte index, causing position-reporting functions to return
inconsistent values after a mode change.
Solution: Skip this coordinate adjustment when virtual editing is fully
enabled. By treating the line terminator as a valid, stable
position, the cursor’s internal representation remains
unchanged when entering or exiting Visual mode, ensuring
consistent coordinate reporting. Add a regression test to
check this functionality.
(McAuley Penney)
fixes: #16276
closes: #19009
Signed-off-by: McAuley Penney <jacobmpenney@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
int adj_cursor = (curwin->w_cursor.col > 0
&& gchar_cursor() == NUL
&& (cur_ve_flags & VE_ONEMORE) == 0
+ && (cur_ve_flags & VE_ALL) == 0
&& !(restart_edit || (State & MODE_INSERT)));
if (!adj_cursor)
return;
bwipe!
endfunc
+" Verify that getpos() remains consistent when the cursor is past EOL after toggling Visual mode with virtualedit=all.
+func Test_virtualedit_getpos_stable_past_eol_after_visual()
+ new
+ set virtualedit=all
+ call setline(1, 'abc')
+
+ normal! gg$3l
+ let p1 = getpos('.')
+
+ normal! v
+ redraw
+ normal! \<Esc>
+
+ let p2 = getpos('.')
+ call assert_equal(p1, p2, 'Position should not be re-encoded after leaving Visual mode')
+
+ set virtualedit&
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 2019,
/**/
2018,
/**/