mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 9.0.2022: getmousepos() returns wrong index for TAB char
Problem: When clicking in the middle of a TAB, getmousepos() returns the column of the next char instead of the TAB. Solution: Break out of the loop when the vcol to find is inside current char. Fix invalid memory access when calling virtcol2col() on an empty line. closes: #13321 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
cd6ee69358
commit
b583eda703
@@ -10376,6 +10376,8 @@ virtcol2col({winid}, {lnum}, {col}) *virtcol2col()*
|
||||
character in window {winid} at buffer line {lnum} and virtual
|
||||
column {col}.
|
||||
|
||||
If buffer line {lnum} is an empty line, 0 is returned.
|
||||
|
||||
If {col} is greater than the last virtual column in line
|
||||
{lnum}, then the byte index of the character at the last
|
||||
virtual column is returned.
|
||||
|
@@ -3201,7 +3201,7 @@ mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED)
|
||||
|| defined(FEAT_EVAL) || defined(PROTO)
|
||||
/*
|
||||
* Convert a virtual (screen) column to a character column.
|
||||
* The first column is one.
|
||||
* The first column is zero.
|
||||
*/
|
||||
int
|
||||
vcol2col(win_T *wp, linenr_T lnum, int vcol)
|
||||
@@ -3214,7 +3214,10 @@ vcol2col(win_T *wp, linenr_T lnum, int vcol)
|
||||
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||
while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL)
|
||||
{
|
||||
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||
int size = win_lbr_chartabsize(&cts, NULL);
|
||||
if (cts.cts_vcol + size > vcol)
|
||||
break;
|
||||
cts.cts_vcol += size;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
11
src/move.c
11
src/move.c
@@ -1547,14 +1547,17 @@ f_screenpos(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
static int
|
||||
virtcol2col(win_T *wp, linenr_T lnum, int vcol)
|
||||
{
|
||||
int offset = vcol2col(wp, lnum, vcol);
|
||||
int offset = vcol2col(wp, lnum, vcol - 1);
|
||||
char_u *line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||
char_u *p = line + offset;
|
||||
|
||||
// For a multibyte character, need to return the column number of the first
|
||||
// byte.
|
||||
if (*p == NUL)
|
||||
{
|
||||
if (p == line) // empty line
|
||||
return 0;
|
||||
// Move to the first byte of the last char.
|
||||
MB_PTR_BACK(line, p);
|
||||
|
||||
}
|
||||
return (int)(p - line + 1);
|
||||
}
|
||||
|
||||
|
@@ -573,6 +573,11 @@ func Test_virtcol2col()
|
||||
call assert_equal(8, virtcol2col(0, 1, 7))
|
||||
call assert_equal(8, virtcol2col(0, 1, 8))
|
||||
|
||||
" These used to cause invalid memory access
|
||||
call setline(1, '')
|
||||
call assert_equal(0, virtcol2col(0, 1, 1))
|
||||
call assert_equal(0, virtcol2col(0, 1, 2))
|
||||
|
||||
let w = winwidth(0)
|
||||
call setline(2, repeat('a', w + 2))
|
||||
let win_nosbr = win_getid()
|
||||
|
@@ -3366,6 +3366,46 @@ func Test_getmousepos()
|
||||
\ line: 1,
|
||||
\ column: 1,
|
||||
\ }, getmousepos())
|
||||
call test_setmouse(1, 2)
|
||||
call assert_equal(#{
|
||||
\ screenrow: 1,
|
||||
\ screencol: 2,
|
||||
\ winid: win_getid(),
|
||||
\ winrow: 1,
|
||||
\ wincol: 2,
|
||||
\ line: 1,
|
||||
\ column: 1,
|
||||
\ }, getmousepos())
|
||||
call test_setmouse(1, 8)
|
||||
call assert_equal(#{
|
||||
\ screenrow: 1,
|
||||
\ screencol: 8,
|
||||
\ winid: win_getid(),
|
||||
\ winrow: 1,
|
||||
\ wincol: 8,
|
||||
\ line: 1,
|
||||
\ column: 1,
|
||||
\ }, getmousepos())
|
||||
call test_setmouse(1, 9)
|
||||
call assert_equal(#{
|
||||
\ screenrow: 1,
|
||||
\ screencol: 9,
|
||||
\ winid: win_getid(),
|
||||
\ winrow: 1,
|
||||
\ wincol: 9,
|
||||
\ line: 1,
|
||||
\ column: 2,
|
||||
\ }, getmousepos())
|
||||
call test_setmouse(1, 12)
|
||||
call assert_equal(#{
|
||||
\ screenrow: 1,
|
||||
\ screencol: 12,
|
||||
\ winid: win_getid(),
|
||||
\ winrow: 1,
|
||||
\ wincol: 12,
|
||||
\ line: 1,
|
||||
\ column: 2,
|
||||
\ }, getmousepos())
|
||||
call test_setmouse(1, 25)
|
||||
call assert_equal(#{
|
||||
\ screenrow: 1,
|
||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2022,
|
||||
/**/
|
||||
2021,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user