summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-10-14 11:32:28 +0200
committerChristian Brabandt <cb@256bit.org>2023-10-14 11:32:28 +0200
commitb583eda7031b1f6a3469a2537d0c10ca5fa5568e (patch)
tree60bfbbf0770516cb9411197ad049048a2c74a9cc /src
parentcd6ee6935811ab223605a3f39a550d26a617867d (diff)
patch 9.0.2022: getmousepos() returns wrong index for TAB charv9.0.2022
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>
Diffstat (limited to 'src')
-rw-r--r--src/mouse.c7
-rw-r--r--src/move.c13
-rw-r--r--src/testdir/test_cursor_func.vim5
-rw-r--r--src/testdir/test_functions.vim40
-rw-r--r--src/version.c2
5 files changed, 60 insertions, 7 deletions
diff --git a/src/mouse.c b/src/mouse.c
index f3342f9056..fe5c14cac5 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -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);
diff --git a/src/move.c b/src/move.c
index 42878e4ad9..72490d2f85 100644
--- a/src/move.c
+++ b/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.
- MB_PTR_BACK(line, p);
-
+ 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);
}
diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim
index 4fc59288c0..3cdf4cb7f9 100644
--- a/src/testdir/test_cursor_func.vim
+++ b/src/testdir/test_cursor_func.vim
@@ -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()
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index bf0bf9036d..50b7fb23ca 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -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,
diff --git a/src/version.c b/src/version.c
index 2c9354634b..d842108880 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2022,
+/**/
2021,
/**/
2020,