From bcda800933f6de09392c3c91e290077952989722 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 14 Oct 2023 19:18:25 +0800 Subject: vim-patch:9.0.2022: getmousepos() returns wrong index for TAB char (#25636) 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: vim/vim#13321 https://github.com/vim/vim/commit/b583eda7031b1f6a3469a2537d0c10ca5fa5568e --- src/nvim/eval.lua | 2 ++ src/nvim/mouse.c | 8 ++++++-- src/nvim/move.c | 12 ++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 14476e29d4..6ba5a171f9 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -12107,6 +12107,8 @@ M.funcs = { 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. diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 0433031393..75c399bcad 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1754,7 +1754,7 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp) } /// Convert a virtual (screen) column to a character column. -/// The first column is one. +/// The first column is zero. colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { @@ -1763,7 +1763,11 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol) chartabsize_T cts; 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/nvim/move.c b/src/nvim/move.c index 25dee0a114..dfd2bf795d 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1142,13 +1142,17 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// returned. 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 *line = ml_get_buf(wp->w_buffer, lnum); char *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); } -- cgit