changeset 32801:6e1734ac14eb v9.0.1717

patch 9.0.1717: virtcol2col returns last byte of a multi-byte char Commit: https://github.com/vim/vim/commit/b209b86e6636a16088ccacdac98213416c065bf2 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Tue Aug 15 23:01:44 2023 +0200 patch 9.0.1717: virtcol2col returns last byte of a multi-byte char Problem: virtcol2col returns last byte of a multi-byte char Solution: Make it return the first byte for a multi-byte char closes: #12786 closes: #12799 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Tue, 15 Aug 2023 23:15:03 +0200
parents 324a39b11de9
children e94bc9044deb
files runtime/doc/builtin.txt src/move.c src/testdir/test_cursor_func.vim src/version.c
diffstat 4 files changed, 34 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -10347,6 +10347,9 @@ virtcol2col({winid}, {lnum}, {col})			*v
 		{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.
 
--- a/src/move.c
+++ b/src/move.c
@@ -1557,6 +1557,25 @@ f_screenpos(typval_T *argvars UNUSED, ty
 }
 
 /*
+ * 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_u	*line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+    char_u	*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
@@ -1586,7 +1605,7 @@ f_virtcol2col(typval_T *argvars UNUSED, 
     if (error || screencol < 0)
 	return;
 
-    rettv->vval.v_number = vcol2col(wp, lnum, screencol);
+    rettv->vval.v_number = virtcol2col(wp, lnum, screencol);
 }
 #endif
 
--- a/src/testdir/test_cursor_func.vim
+++ b/src/testdir/test_cursor_func.vim
@@ -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(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, "1")', 'E1210:')
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1717,
+/**/
     1716,
 /**/
     1715,