# HG changeset patch # User Christian Brabandt # Date 1697357705 -7200 # Node ID 8fc442c731ca44fadf222d1bbf6e39e4e7556452 # Parent a559d0a21b251ff781bd13fcb9309ede2ee649b9 patch 9.0.2032: cannot get mouse click pos for tab or virt text Commit: https://github.com/vim/vim/commit/f5a94d5165bb9e390797da50a1fa7a87df3fbee4 Author: zeertzjq Date: Sun Oct 15 10:03:30 2023 +0200 patch 9.0.2032: cannot get mouse click pos for tab or virt text Problem: Cannot accurately get mouse clicking position when clicking on a TAB or with virtual text. Solution: Add a "coladd" field to getmousepos() result. closes: #13335 Signed-off-by: Christian Brabandt Co-authored-by: zeertzjq diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -3928,6 +3928,8 @@ getmousepos() *getmousepos()* wincol column inside "winid" line text line inside "winid" column text column inside "winid" + coladd offset (in screen columns) from the + start of the clicked char All numbers are 1-based. If not over a window, e.g. when in the command line, then only diff --git a/src/beval.c b/src/beval.c --- a/src/beval.c +++ b/src/beval.c @@ -74,7 +74,7 @@ find_word_under_cursor( } } - col = vcol2col(wp, lnum, col); + col = vcol2col(wp, lnum, col, NULL); scol = col; if (VIsual_active diff --git a/src/mouse.c b/src/mouse.c --- a/src/mouse.c +++ b/src/mouse.c @@ -172,9 +172,7 @@ get_fpos_of_mouse(pos_T *mpos) if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum, NULL)) return IN_STATUS_LINE; // past bottom - mpos->col = vcol2col(wp, mpos->lnum, col); - - mpos->coladd = 0; + mpos->col = vcol2col(wp, mpos->lnum, col, &mpos->coladd); return IN_BUFFER; } #endif @@ -3204,7 +3202,7 @@ mouse_find_win(int *rowp, int *colp, mou * The first column is zero. */ int -vcol2col(win_T *wp, linenr_T lnum, int vcol) +vcol2col(win_T *wp, linenr_T lnum, int vcol, colnr_T *coladdp) { char_u *line; chartabsize_T cts; @@ -3222,6 +3220,8 @@ vcol2col(win_T *wp, linenr_T lnum, int v } clear_chartabsize_arg(&cts); + if (coladdp != NULL) + *coladdp = vcol - cts.cts_vcol; return (int)(cts.cts_ptr - line); } #endif @@ -3242,6 +3242,7 @@ f_getmousepos(typval_T *argvars UNUSED, varnumber_T wincol = 0; linenr_T lnum = 0; varnumber_T column = 0; + colnr_T coladd = 0; if (rettv_dict_alloc(rettv) == FAIL) return; @@ -3275,7 +3276,7 @@ f_getmousepos(typval_T *argvars UNUSED, if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) { (void)mouse_comp_pos(wp, &row, &col, &lnum, NULL); - col = vcol2col(wp, lnum, col); + col = vcol2col(wp, lnum, col, &coladd); column = col + 1; } } @@ -3285,5 +3286,6 @@ f_getmousepos(typval_T *argvars UNUSED, dict_add_number(d, "wincol", wincol); dict_add_number(d, "line", (varnumber_T)lnum); dict_add_number(d, "column", column); + dict_add_number(d, "coladd", coladd); } #endif diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -1547,7 +1547,7 @@ f_screenpos(typval_T *argvars UNUSED, ty static int virtcol2col(win_T *wp, linenr_T lnum, int vcol) { - int offset = vcol2col(wp, lnum, vcol - 1); + int offset = vcol2col(wp, lnum, vcol - 1, NULL); char_u *line = ml_get_buf(wp->w_buffer, lnum, FALSE); char_u *p = line + offset; diff --git a/src/proto/mouse.pro b/src/proto/mouse.pro --- a/src/proto/mouse.pro +++ b/src/proto/mouse.pro @@ -21,6 +21,6 @@ void reset_held_button(void); int check_termcode_mouse(char_u *tp, int *slen, char_u *key_name, char_u *modifiers_start, int idx, int *modifiers); int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int *plines_cache); win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup); -int vcol2col(win_T *wp, linenr_T lnum, int vcol); +int vcol2col(win_T *wp, linenr_T lnum, int vcol, colnr_T *coladdp); void f_getmousepos(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3365,6 +3365,7 @@ func Test_getmousepos() \ wincol: 1, \ line: 1, \ column: 1, + \ coladd: 0, \ }, getmousepos()) call test_setmouse(1, 2) call assert_equal(#{ @@ -3375,6 +3376,7 @@ func Test_getmousepos() \ wincol: 2, \ line: 1, \ column: 1, + \ coladd: 1, \ }, getmousepos()) call test_setmouse(1, 8) call assert_equal(#{ @@ -3385,6 +3387,7 @@ func Test_getmousepos() \ wincol: 8, \ line: 1, \ column: 1, + \ coladd: 7, \ }, getmousepos()) call test_setmouse(1, 9) call assert_equal(#{ @@ -3395,6 +3398,7 @@ func Test_getmousepos() \ wincol: 9, \ line: 1, \ column: 2, + \ coladd: 0, \ }, getmousepos()) call test_setmouse(1, 12) call assert_equal(#{ @@ -3405,6 +3409,7 @@ func Test_getmousepos() \ wincol: 12, \ line: 1, \ column: 2, + \ coladd: 3, \ }, getmousepos()) call test_setmouse(1, 25) call assert_equal(#{ @@ -3415,6 +3420,29 @@ func Test_getmousepos() \ wincol: 25, \ line: 1, \ column: 4, + \ coladd: 0, + \ }, getmousepos()) + call test_setmouse(1, 28) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 28, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 28, + \ line: 1, + \ column: 7, + \ coladd: 0, + \ }, getmousepos()) + call test_setmouse(1, 29) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 29, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 29, + \ line: 1, + \ column: 8, + \ coladd: 0, \ }, getmousepos()) call test_setmouse(1, 50) call assert_equal(#{ @@ -3425,6 +3453,7 @@ func Test_getmousepos() \ wincol: 50, \ line: 1, \ column: 8, + \ coladd: 21, \ }, getmousepos()) " If the mouse is positioned past the last buffer line, "line" and "column" @@ -3438,6 +3467,7 @@ func Test_getmousepos() \ wincol: 25, \ line: 1, \ column: 4, + \ coladd: 0, \ }, getmousepos()) call test_setmouse(2, 50) call assert_equal(#{ @@ -3448,6 +3478,7 @@ func Test_getmousepos() \ wincol: 50, \ line: 1, \ column: 8, + \ coladd: 21, \ }, getmousepos()) bwipe! endfunc diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2671,21 +2671,21 @@ func Test_popupwin_filter_mouse() eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ \ screenrow: a:row, screencol: a:col, \ winid: win_getid(), winrow: a:row, wincol: a:col, - \ line: a:row, column: a:col, + \ line: a:row, column: a:col, coladd: 0, \ }}) endfunc func AddItemInPopupBorder(tests, winid, row, col) eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ \ screenrow: a:row, screencol: a:col, \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, - \ line: 0, column: 0, + \ line: 0, column: 0, coladd: 0, \ }}) endfunc - func AddItemInPopupText(tests, winid, row, col, textline, textcol) + func AddItemInPopupText(tests, winid, row, col, textline, textcol, coladd = 0) eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ \ screenrow: a:row, screencol: a:col, \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, - \ line: a:textline, column: a:textcol, + \ line: a:textline, column: a:textcol, coladd: a:coladd, \ }}) endfunc @@ -2717,7 +2717,7 @@ func Test_popupwin_filter_mouse() call AddItemInPopupText(tests, winid, 4, 6, 1, 1) call AddItemInPopupText(tests, winid, 4, 10, 1, 5) call AddItemInPopupText(tests, winid, 4, 11, 1, 6) - call AddItemInPopupText(tests, winid, 4, 17, 1, 6) + call AddItemInPopupText(tests, winid, 4, 17, 1, 6, 6) " text "long line th" call AddItemInPopupText(tests, winid, 5, 6, 2, 1) call AddItemInPopupText(tests, winid, 5, 10, 2, 5) @@ -2730,7 +2730,7 @@ func Test_popupwin_filter_mouse() call AddItemInPopupText(tests, winid, 7, 6, 3, 1) call AddItemInPopupText(tests, winid, 7, 10, 3, 5) call AddItemInPopupText(tests, winid, 7, 11, 3, 6) - call AddItemInPopupText(tests, winid, 7, 17, 3, 6) + call AddItemInPopupText(tests, winid, 7, 17, 3, 6, 6) for item in tests call test_setmouse(item.clickrow, item.clickcol) diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 2032, +/**/ 2031, /**/ 2030,