patch 9.1.0430: getregionpos() doesn't handle one char selection

Commit: 
https://github.com/vim/vim/commit/52a6f348874778cf315b47d9e8b5f818f4b97277
Author: zeertzjq <zeert...@outlook.com>
Date:   Wed May 22 16:42:44 2024 +0200

    patch 9.1.0430: getregionpos() doesn't handle one char selection
    
    Problem:  getregionpos() doesn't handle one char selection.
    Solution: Handle startspaces differently when is_oneChar is set.
              Also add a test for an exclusive charwise selection with
              multibyte chars (zeertzjq)
    
    closes: #14825
    
    Signed-off-by: zeertzjq <zeert...@outlook.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index b9dd4d20b..4177a0181 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt*  For Vim version 9.1.  Last change: 2024 May 20
+*builtin.txt*  For Vim version 9.1.  Last change: 2024 May 22
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -4345,8 +4345,8 @@ getregionpos({pos1}, {pos2} [, {opts}])            
*getregionpos()*
                the offset in screen columns from the start of the character.
                E.g., a position within a <Tab> or after the last character.
                If the "off" number of an ending position is non-zero, it is
-               the character's number of cells included in the selection,
-               otherwise the whole character is included.
+               the offset of the character's first cell not included in the
+               selection, otherwise all its cells are included.
 
                Can also be used as a |method|: >
                        getpos('.')->getregionpos(getpos("'a"))
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 903205ad3..b65df5dd9 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5793,7 +5793,6 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
 
     for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
     {
-       struct block_def        bd;
        pos_T                   ret_p1, ret_p2;
 
        if (region_type == MLINE)
@@ -5805,11 +5804,28 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
        }
        else
        {
+           struct block_def    bd;
+
            if (region_type == MBLOCK)
                block_prep(&oa, &bd, lnum, FALSE);
            else
                charwise_block_prep(p1, p2, &bd, lnum, inclusive);
-           if (bd.startspaces > 0)
+
+           if (bd.is_oneChar)  // selection entirely inside one char
+           {
+               if (region_type == MBLOCK)
+               {
+                   ret_p1.col = bd.textcol;
+                   ret_p1.coladd = bd.start_char_vcols
+                                            - (bd.start_vcol - oa.start_vcol);
+               }
+               else
+               {
+                   ret_p1.col = p1.col + 1;
+                   ret_p1.coladd = p1.coladd;
+               }
+           }
+           else if (bd.startspaces > 0)
            {
                ret_p1.col = bd.textcol;
                ret_p1.coladd = bd.start_char_vcols - bd.startspaces;
@@ -5819,7 +5835,13 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
                ret_p1.col = bd.textcol + 1;
                ret_p1.coladd = 0;
            }
-           if (bd.endspaces > 0)
+
+           if (bd.is_oneChar)  // selection entirely inside one char
+           {
+               ret_p2.col = ret_p1.col;
+               ret_p2.coladd = ret_p1.coladd + bd.startspaces;
+           }
+           else if (bd.endspaces > 0)
            {
                ret_p2.col = bd.textcol + bd.textlen + 1;
                ret_p2.coladd = bd.endspaces;
diff --git a/src/ops.c b/src/ops.c
index 605a66494..1dd36ab28 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -2444,13 +2444,13 @@ charwise_block_prep(
     int                        inclusive)
 {
     colnr_T startcol = 0, endcol = MAXCOL;
-    int            is_oneChar = FALSE;
     colnr_T cs, ce;
     char_u *p;
 
     p = ml_get(lnum);
     bdp->startspaces = 0;
     bdp->endspaces = 0;
+    bdp->is_oneChar = FALSE;
     bdp->start_char_vcols = 0;
 
     if (lnum == start.lnum)
@@ -2487,7 +2487,7 @@ charwise_block_prep(
                if (start.lnum == end.lnum && start.col == end.col)
                {
                    // Special case: inside a single char
-                   is_oneChar = TRUE;
+                   bdp->is_oneChar = TRUE;
                    bdp->startspaces = end.coladd - start.coladd + inclusive;
                    endcol = startcol;
                }
@@ -2501,7 +2501,7 @@ charwise_block_prep(
     }
     if (endcol == MAXCOL)
        endcol = ml_get_len(lnum);
-    if (startcol > endcol || is_oneChar)
+    if (startcol > endcol || bdp->is_oneChar)
        bdp->textlen = 0;
     else
        bdp->textlen = endcol - startcol + inclusive;
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index 8c850d1ac..621be298d 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1889,7 +1889,7 @@ func Test_visual_getregion()
           \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
     call assert_equal([
           \   [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 5, 0]],
-          \   [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 0]],
+          \   [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 2]],
           \   [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]],
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
@@ -1900,6 +1900,7 @@ func Test_visual_getregion()
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
 
+    #" characterwise selection with multibyte chars
     call cursor(1, 1)
     call feedkeys("\<Esc>vj", 'xt')
     call assert_equal(['abcdefghijk«', "\U0001f1e6"],
@@ -1910,8 +1911,17 @@ func Test_visual_getregion()
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
 
+    set selection=exclusive
+    call feedkeys('l', 'xt')
+    call assert_equal(['abcdefghijk«', "\U0001f1e6"],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 13, 0]],
+          \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
     #" marks on multibyte chars
-    :set selection=exclusive
     call setpos("'a", [0, 1, 11, 0])
     call setpos("'b", [0, 2, 16, 0])
     call setpos("'c", [0, 2, 0, 0])
@@ -1997,6 +2007,7 @@ func Test_visual_getregion()
     call assert_equal(["c", "x z"],
           \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
     set selection&
+    bwipe!
 
     #" Exclusive selection 2
     new
@@ -2033,7 +2044,24 @@ func Test_visual_getregion()
     set virtualedit=all
 
     call cursor(1, 1)
-    call feedkeys("\<Esc>2lv2lj", 'xt')
+    call feedkeys("\<Esc>lv2l", 'xt')
+    call assert_equal(['  '],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
+    call cursor(1, 1)
+    call feedkeys("\<Esc>2lv2l", 'xt')
+    call assert_equal(['  '],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
+    call feedkeys('j', 'xt')
     call assert_equal(['      c', 'x   '],
           \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
     call assert_equal([
@@ -2042,13 +2070,34 @@ func Test_visual_getregion()
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
 
+    call cursor(1, 1)
+    call feedkeys("\<Esc>6l\<C-v>2lj", 'xt')
+    call assert_equal(['  ', '  '],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 7]],
+          \   [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 7]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+    call cursor(1, 1)
+    call feedkeys("\<Esc>l\<C-v>2l2j", 'xt')
+    call assert_equal(['  ', '  ', '  '],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]],
+          \   [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 2]],
+          \   [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
     call cursor(1, 1)
     call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
     call assert_equal(['  ', '  ', '  '],
           \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
     call assert_equal([
-          \   [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 0]],
-          \   [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 0]],
+          \   [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]],
+          \   [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 3]],
           \   [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
diff --git a/src/version.c b/src/version.c
index b2f04169f..28dad4526 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    430,
 /**/
     429,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1s9nDO-000OjE-9G%40256bit.org.

Raspunde prin e-mail lui