mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.0.1725: cursor pos wrong after concealed text with 'virtualedit'
Problem: Wrong cursor position when clicking after concealed text with 'virtualedit'. Solution: Store virtual columns in ScreenCols[] instead of text columns, and always use coladvance() when clicking. This also fixes incorrect curswant when clicking on a TAB, so now Test_normal_click_on_ctrl_char() asserts the same results as the ones before patch 9.0.0048. closes: #12808 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
This commit is contained in:
committed by
Christian Brabandt
parent
2261c89a49
commit
e500ae8e29
@@ -1829,7 +1829,6 @@ win_line(
|
||||
|
||||
win_line_start(wp, &wlv, FALSE);
|
||||
|
||||
char_u *prev_ptr = ptr;
|
||||
// Repeat for the whole displayed line.
|
||||
for (;;)
|
||||
{
|
||||
@@ -2261,9 +2260,9 @@ win_line(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SEARCH_EXTRA
|
||||
if (wlv.n_extra == 0)
|
||||
{
|
||||
#ifdef FEAT_SEARCH_EXTRA
|
||||
// Check for start/end of 'hlsearch' and other matches.
|
||||
// After end, check for start/end of next match.
|
||||
// When another match, have to check for start again.
|
||||
@@ -2278,10 +2277,8 @@ win_line(
|
||||
// and bad things happen.
|
||||
if (*ptr == NUL)
|
||||
has_match_conc = 0;
|
||||
#endif
|
||||
|
||||
prev_ptr = ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_DIFF
|
||||
if (wlv.diff_hlf != (hlf_T)0)
|
||||
@@ -2356,7 +2353,6 @@ win_line(
|
||||
// have made it invalid.
|
||||
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||
ptr = line + v;
|
||||
prev_ptr = ptr;
|
||||
# ifdef FEAT_CONCEAL
|
||||
// no concealing past the end of the line, it interferes
|
||||
// with line highlighting
|
||||
@@ -2567,7 +2563,9 @@ win_line(
|
||||
#ifdef FEAT_LINEBREAK
|
||||
int c0;
|
||||
#endif
|
||||
prev_ptr = ptr;
|
||||
#ifdef FEAT_SPELL
|
||||
char_u *prev_ptr = ptr;
|
||||
#endif
|
||||
|
||||
// Get a character from the line itself.
|
||||
c = *ptr;
|
||||
@@ -3809,7 +3807,7 @@ win_line(
|
||||
else
|
||||
ScreenAttrs[wlv.off] = wlv.char_attr;
|
||||
|
||||
ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
|
||||
ScreenCols[wlv.off] = wlv.vcol;
|
||||
|
||||
if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
|
||||
{
|
||||
@@ -3833,7 +3831,7 @@ win_line(
|
||||
if (wlv.tocol == wlv.vcol)
|
||||
++wlv.tocol;
|
||||
|
||||
ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
|
||||
ScreenCols[wlv.off] = wlv.vcol;
|
||||
|
||||
#ifdef FEAT_RIGHTLEFT
|
||||
if (wp->w_p_rl)
|
||||
|
@@ -32,7 +32,7 @@ EXTERN long Columns INIT(= 80); // nr of columns in the screen
|
||||
* The characters that are currently on the screen are kept in ScreenLines[].
|
||||
* It is a single block of characters, the size of the screen plus one line.
|
||||
* The attributes for those characters are kept in ScreenAttrs[].
|
||||
* The byte offset in the line is kept in ScreenCols[].
|
||||
* The virtual column in the line is kept in ScreenCols[].
|
||||
*
|
||||
* "LineOffset[n]" is the offset from ScreenLines[] for the start of line 'n'.
|
||||
* The same value is used for ScreenLinesUC[], ScreenAttrs[] and ScreenCols[].
|
||||
|
62
src/mouse.c
62
src/mouse.c
@@ -2060,7 +2060,7 @@ retnomove:
|
||||
// Only use ScreenCols[] after the window was redrawn. Mainly matters
|
||||
// for tests, a user would not click before redrawing.
|
||||
// Do not use when 'virtualedit' is active.
|
||||
if (curwin->w_redr_type <= UPD_VALID_NO_UPDATE && !virtual_active())
|
||||
if (curwin->w_redr_type <= UPD_VALID_NO_UPDATE)
|
||||
col_from_screen = ScreenCols[off];
|
||||
#ifdef FEAT_FOLDING
|
||||
// Remember the character under the mouse, it might be a '-' or '+' in
|
||||
@@ -2098,41 +2098,47 @@ retnomove:
|
||||
redraw_cmdline = TRUE; // show visual mode later
|
||||
}
|
||||
|
||||
if (col_from_screen >= 0)
|
||||
if (col_from_screen == MAXCOL)
|
||||
{
|
||||
// Use the column from ScreenCols[], it is accurate also after
|
||||
// concealed characters.
|
||||
curwin->w_cursor.col = col_from_screen;
|
||||
if (col_from_screen == MAXCOL)
|
||||
// When clicking after end of line, still need to set correct curswant
|
||||
int off_l = LineOffset[prev_row];
|
||||
if (ScreenCols[off_l] < MAXCOL)
|
||||
{
|
||||
curwin->w_curswant = col_from_screen;
|
||||
curwin->w_set_curswant = FALSE; // May still have been TRUE
|
||||
mouse_past_eol = TRUE;
|
||||
if (inclusive != NULL)
|
||||
*inclusive = TRUE;
|
||||
// Binary search to find last char in line
|
||||
int off_r = off_l + prev_col;
|
||||
int off_click = off_r;
|
||||
while (off_l < off_r)
|
||||
{
|
||||
int off_m = (off_l + off_r + 1) / 2;
|
||||
if (ScreenCols[off_m] < MAXCOL)
|
||||
off_l = off_m;
|
||||
else
|
||||
off_r = off_m - 1;
|
||||
}
|
||||
col = ScreenCols[off_r] + (off_click - off_r);
|
||||
}
|
||||
else
|
||||
{
|
||||
curwin->w_set_curswant = TRUE;
|
||||
if (inclusive != NULL)
|
||||
*inclusive = FALSE;
|
||||
}
|
||||
check_cursor_col();
|
||||
// Shouldn't normally happen
|
||||
col = MAXCOL;
|
||||
}
|
||||
else
|
||||
else if (col_from_screen >= 0)
|
||||
{
|
||||
curwin->w_curswant = col;
|
||||
curwin->w_set_curswant = FALSE; // May still have been TRUE
|
||||
if (coladvance(col) == FAIL) // Mouse click beyond end of line
|
||||
{
|
||||
if (inclusive != NULL)
|
||||
*inclusive = TRUE;
|
||||
mouse_past_eol = TRUE;
|
||||
}
|
||||
else if (inclusive != NULL)
|
||||
*inclusive = FALSE;
|
||||
// Use the virtual column from ScreenCols[], it is accurate also after
|
||||
// concealed characters.
|
||||
col = col_from_screen;
|
||||
}
|
||||
|
||||
curwin->w_curswant = col;
|
||||
curwin->w_set_curswant = FALSE; // May still have been TRUE
|
||||
if (coladvance(col) == FAIL) // Mouse click beyond end of line
|
||||
{
|
||||
if (inclusive != NULL)
|
||||
*inclusive = TRUE;
|
||||
mouse_past_eol = TRUE;
|
||||
}
|
||||
else if (inclusive != NULL)
|
||||
*inclusive = FALSE;
|
||||
|
||||
count = IN_BUFFER;
|
||||
if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
|
||||
|| curwin->w_cursor.col != old_cursor.col)
|
||||
|
@@ -351,9 +351,55 @@ func Test_conceal_mouse_click()
|
||||
call test_setmouse(1, 16)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 20, 0, 20], getcurpos())
|
||||
" click on 'e' of "here" puts cursor there
|
||||
call test_setmouse(1, 19)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 23], getcurpos())
|
||||
" click after end of line puts cursor on 'e' without 'virtualedit'
|
||||
call test_setmouse(1, 20)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 24], getcurpos())
|
||||
call test_setmouse(1, 21)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 25], getcurpos())
|
||||
call test_setmouse(1, 22)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 26], getcurpos())
|
||||
call test_setmouse(1, 31)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 35], getcurpos())
|
||||
call test_setmouse(1, 32)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 36], getcurpos())
|
||||
|
||||
set virtualedit=all
|
||||
" click on 'h' of "here" puts cursor there
|
||||
call test_setmouse(1, 16)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 20, 0, 20], getcurpos())
|
||||
" click on 'e' of "here" puts cursor there
|
||||
call test_setmouse(1, 19)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 23, 0, 23], getcurpos())
|
||||
" click after end of line puts cursor there without 'virtualedit'
|
||||
call test_setmouse(1, 20)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 24, 0, 24], getcurpos())
|
||||
call test_setmouse(1, 21)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 24, 1, 25], getcurpos())
|
||||
call test_setmouse(1, 22)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 24, 2, 26], getcurpos())
|
||||
call test_setmouse(1, 31)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 24, 11, 35], getcurpos())
|
||||
call test_setmouse(1, 32)
|
||||
call feedkeys("\<LeftMouse>", "tx")
|
||||
call assert_equal([0, 1, 24, 12, 36], getcurpos())
|
||||
|
||||
bwipe!
|
||||
set mouse&
|
||||
set mouse& virtualedit&
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@@ -4049,13 +4049,13 @@ func Test_normal_click_on_ctrl_char()
|
||||
call assert_equal([0, 1, 1, 0, 1], getcurpos())
|
||||
call test_setmouse(1, 2)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 2, 0, 8], getcurpos())
|
||||
call assert_equal([0, 1, 2, 0, 2], getcurpos())
|
||||
call test_setmouse(1, 3)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 2, 0, 8], getcurpos())
|
||||
call assert_equal([0, 1, 2, 0, 3], getcurpos())
|
||||
call test_setmouse(1, 7)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 2, 0, 8], getcurpos())
|
||||
call assert_equal([0, 1, 2, 0, 7], getcurpos())
|
||||
call test_setmouse(1, 8)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 2, 0, 8], getcurpos())
|
||||
@@ -4067,13 +4067,13 @@ func Test_normal_click_on_ctrl_char()
|
||||
call assert_equal([0, 1, 4, 0, 10], getcurpos())
|
||||
call test_setmouse(1, 11)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 4, 0, 10], getcurpos())
|
||||
call assert_equal([0, 1, 4, 0, 11], getcurpos())
|
||||
call test_setmouse(1, 12)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 5, 0, 12], getcurpos())
|
||||
call test_setmouse(1, 13)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal([0, 1, 5, 0, v:maxcol], getcurpos())
|
||||
call assert_equal([0, 1, 5, 0, 13], getcurpos())
|
||||
|
||||
bwipe!
|
||||
let &mouse = save_mouse
|
||||
|
@@ -586,6 +586,12 @@ func Test_virtualedit_mouse()
|
||||
call test_setmouse(1, 9)
|
||||
call feedkeys("\<LeftMouse>", "xt")
|
||||
call assert_equal([0, 1, 6, 0, 9], getcurpos())
|
||||
call test_setmouse(1, 12)
|
||||
call feedkeys("\<LeftMouse>", "xt")
|
||||
call assert_equal([0, 1, 9, 0, 12], getcurpos())
|
||||
call test_setmouse(1, 13)
|
||||
call feedkeys("\<LeftMouse>", "xt")
|
||||
call assert_equal([0, 1, 10, 0, 13], getcurpos())
|
||||
call test_setmouse(1, 15)
|
||||
call feedkeys("\<LeftMouse>", "xt")
|
||||
call assert_equal([0, 1, 10, 2, 15], getcurpos())
|
||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1725,
|
||||
/**/
|
||||
1724,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user