From a245dd79a267c8b56866023e84b49d0ecffca65b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 16 Aug 2023 06:28:52 +0800 Subject: 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 https://github.com/vim/vim/commit/b209b86e6636a16088ccacdac98213416c065bf2 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval.lua | 3 +++ src/nvim/move.c | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 8a0d7575b3..8a36509f9a 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -11931,6 +11931,9 @@ M.funcs = { {lnum}, then the byte index of the character at the last 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 |window-ID|. If this is zero, then the current window is used. diff --git a/src/nvim/move.c b/src/nvim/move.c index 0ed30070a5..a68f6a2d50 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1163,6 +1163,21 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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 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; } - 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" -- cgit