From: Hirohito Higashi Date: Sat, 18 Jul 2026 16:57:57 +0000 (+0000) Subject: patch 9.2.0804: wincol() is wrong for a double-wide character with 'rightleft' X-Git-Tag: v9.2.0804^0 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=6f02e5cd7c27fc098d0b8dfec99542c7663a807e;p=thirdparty%2Fvim.git patch 9.2.0804: wincol() is wrong for a double-wide character with 'rightleft' Problem: With 'rightleft' set and the cursor on a double-wide character, wincol() returns the column one to the right of where the cursor actually is (after v9.2.0791) Solution: Take the width of the character under the cursor into account, like the cursor positioning already does. related: #20763 closes: #20785 Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- diff --git a/src/evalwindow.c b/src/evalwindow.c index 23cd92b677..f913980404 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -1129,7 +1129,7 @@ f_wincol(typval_T *argvars UNUSED, typval_T *rettv) int col = curwin->w_wcol + 1; # ifdef FEAT_RIGHTLEFT if (curwin->w_p_rl) - col = curwin->w_width - col + 1; + col = curwin->w_width - curwin->w_wcol - cursor_screen_cells() + 1; # endif rettv->vval.v_number = col; } diff --git a/src/proto/screen.pro b/src/proto/screen.pro index a1d5714d8f..4a10729e21 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -36,6 +36,7 @@ int can_clear(char_u *p); void screen_start(void); void windgoto(int row, int col); void setcursor(void); +int cursor_screen_cells(void); void setcursor_mayforce(int force); int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear); int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear, int clear_attr); diff --git a/src/screen.c b/src/screen.c index 7d75af0226..17d4c1563c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -4038,6 +4038,19 @@ setcursor(void) setcursor_mayforce(FALSE); } +#ifdef FEAT_RIGHTLEFT +/* + * Return the number of screen cells used by the character under the cursor + * in the current window. + */ + int +cursor_screen_cells(void) +{ + return has_mbyte && (*mb_ptr2cells)(ml_get_cursor()) == 2 + && vim_isprintc(gchar_cursor()) ? 2 : 1; +} +#endif + /* * Set cursor to its position in the current window. * When "force" is TRUE also when not redrawing. @@ -4054,9 +4067,7 @@ setcursor_mayforce(int force) // With 'rightleft' set and the cursor on a double-wide // character, position it on the leftmost column. curwin->w_p_rl ? ((int)curwin->w_width - curwin->w_wcol - - ((has_mbyte - && (*mb_ptr2cells)(ml_get_cursor()) == 2 - && vim_isprintc(gchar_cursor())) ? 2 : 1)) : + - cursor_screen_cells()) : #endif curwin->w_wcol)); } diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 9882183429..645ff531ed 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -4738,6 +4738,24 @@ func Test_wincol() set rightleft& endif + " With 'rightleft' the cursor is on the leftmost cell of a double-wide + " character, so wincol() is one less than where the character starts. + call setline(1, "あいうえお") + + norm! 0 + call assert_equal([1, 1], [winline(), wincol()]) + norm! l + call assert_equal([1, 3], [winline(), wincol()]) + + if has('rightleft') + set rightleft + norm! 0 + call assert_equal([1, win_width - 1], [winline(), wincol()]) + norm! l + call assert_equal([1, win_width - 3], [winline(), wincol()]) + set rightleft& + endif + set ff& mouse& bw! endfunc diff --git a/src/version.c b/src/version.c index 29624fe211..349057f289 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 804, /**/ 803, /**/