vim-patch:9.0.1717: virtcol2col returns last byte of a multi-byte char (#24729)

Problem: virtcol2col returns last byte of a multi-byte char
Solution: Make it return the first byte for a multi-byte char

closes: vim/vim#12786
closes: vim/vim#12799

b209b86e66

Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
zeertzjq 2023-08-16 06:28:52 +08:00 committed by GitHub
parent 10c5f35a8d
commit a245dd79a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 1 deletions

View File

@ -8434,6 +8434,9 @@ virtcol2col({winid}, {lnum}, {col}) *virtcol2col()*
{lnum}, then the byte index of the character at the last {lnum}, then the byte index of the character at the last
virtual column is returned. virtual column is returned.
For a multi-byte character, the column number of the first
byte in the character is returned.
The {winid} argument can be the window number or the The {winid} argument can be the window number or the
|window-ID|. If this is zero, then the current window is used. |window-ID|. If this is zero, then the current window is used.

View File

@ -10016,6 +10016,9 @@ function vim.fn.virtcol(expr, list) end
--- {lnum}, then the byte index of the character at the last --- {lnum}, then the byte index of the character at the last
--- virtual column is returned. --- virtual column is returned.
--- ---
--- For a multi-byte character, the column number of the first
--- byte in the character is returned.
---
--- The {winid} argument can be the window number or the --- The {winid} argument can be the window number or the
--- |window-ID|. If this is zero, then the current window is used. --- |window-ID|. If this is zero, then the current window is used.
--- ---

View File

@ -11931,6 +11931,9 @@ M.funcs = {
{lnum}, then the byte index of the character at the last {lnum}, then the byte index of the character at the last
virtual column is returned. virtual column is returned.
For a multi-byte character, the column number of the first
byte in the character is returned.
The {winid} argument can be the window number or the The {winid} argument can be the window number or the
|window-ID|. If this is zero, then the current window is used. |window-ID|. If this is zero, then the current window is used.

View File

@ -1163,6 +1163,21 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_dict_add_nr(dict, S_LEN("endcol"), ecol); tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
} }
/// Convert a virtual (screen) column to a character column. The first column
/// is one. For a multibyte character, the column number of the first byte is
/// returned.
static int virtcol2col(win_T *wp, linenr_T lnum, int vcol)
{
int offset = vcol2col(wp, lnum, vcol);
char *line = ml_get_buf(wp->w_buffer, lnum, false);
char *p = line + offset;
// For a multibyte character, need to return the column number of the first byte.
MB_PTR_BACK(line, p);
return (int)(p - line + 1);
}
/// "virtcol2col({winid}, {lnum}, {col})" function /// "virtcol2col({winid}, {lnum}, {col})" function
void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {
@ -1190,7 +1205,7 @@ void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return; return;
} }
rettv->vval.v_number = vcol2col(wp, lnum, screencol); rettv->vval.v_number = virtcol2col(wp, lnum, screencol);
} }
/// Scroll the current window down by "line_count" logical lines. "CTRL-Y" /// Scroll the current window down by "line_count" logical lines. "CTRL-Y"

View File

@ -531,6 +531,15 @@ func Test_virtcol2col()
call assert_equal(-1, virtcol2col(0, -1, 1)) call assert_equal(-1, virtcol2col(0, -1, 1))
call assert_equal(-1, virtcol2col(0, 1, -1)) call assert_equal(-1, virtcol2col(0, 1, -1))
call assert_equal(5, virtcol2col(0, 1, 20)) call assert_equal(5, virtcol2col(0, 1, 20))
" Multibyte character
call setline(1, ['a✅✅✅'])
call assert_equal(1, virtcol2col(0, 1, 1))
call assert_equal(2, virtcol2col(0, 1, 3))
call assert_equal(5, virtcol2col(0, 1, 5))
call assert_equal(8, virtcol2col(0, 1, 7))
call assert_equal(8, virtcol2col(0, 1, 8))
call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:') call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:') call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:') call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:')