patch 9.1.0423: getregionpos() wrong with blockwise mode and multibyte

Problem:  getregionpos() wrong with blockwise mode and multibyte.
Solution: Use textcol and textlen instead of start_vcol and end_vcol.
          Handle coladd properly (zeertzjq).

Also remove unnecessary buflist_findnr() in add_regionpos_range(), as
getregionpos() has already switched buffer.

closes: #14805

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index b304928..8c850d1 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1640,6 +1640,7 @@
     #" Visual mode
     call cursor(1, 1)
     call feedkeys("\<ESC>vjl", 'tx')
+
     call assert_equal(['one', 'tw'],
           \ 'v'->getpos()->getregion(getpos('.')))
     call assert_equal([
@@ -1647,6 +1648,7 @@
           \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 0]]
           \ ],
           \ 'v'->getpos()->getregionpos(getpos('.')))
+
     call assert_equal(['one', 'tw'],
           \ '.'->getpos()->getregion(getpos('v')))
     call assert_equal([
@@ -1654,18 +1656,21 @@
           \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 0]]
           \ ],
           \ '.'->getpos()->getregionpos(getpos('v')))
+
     call assert_equal(['o'],
           \ 'v'->getpos()->getregion(getpos('v')))
     call assert_equal([
           \   [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 1, 0]],
           \ ],
           \ 'v'->getpos()->getregionpos(getpos('v')))
+
     call assert_equal(['w'],
           \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' }))
     call assert_equal([
           \   [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 0]],
           \ ],
           \ '.'->getpos()->getregionpos(getpos('.'), {'type': 'v' }))
+
     call assert_equal(['one', 'two'],
           \ getpos('.')->getregion(getpos('v'), {'type': 'V' }))
     call assert_equal([
@@ -1673,6 +1678,7 @@
           \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]],
           \ ],
           \ getpos('.')->getregionpos(getpos('v'), {'type': 'V' }))
+
     call assert_equal(['on', 'tw'],
           \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
     call assert_equal([
@@ -1815,6 +1821,12 @@
         call assert_equal(range(10)->mapnew('string(v:val)'),
               \ getregion([g:buf, 10, 2, 0], [g:buf, 1, 1, 0],
               \ {'type': type, 'exclusive': exclusive }))
+        call assert_equal(range(1, 10)->mapnew('repeat([[g:buf, v:val, 1, 0]], 2)'),
+              \ getregionpos([g:buf, 1, 1, 0], [g:buf, 10, 2, 0],
+              \ {'type': type, 'exclusive': exclusive }))
+        call assert_equal(range(1, 10)->mapnew('repeat([[g:buf, v:val, 1, 0]], 2)'),
+              \ getregionpos([g:buf, 10, 2, 0], [g:buf, 1, 1, 0],
+              \ {'type': type, 'exclusive': exclusive }))
       endfor
     endfor
 
@@ -1848,28 +1860,55 @@
           \   "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9",
           \   "1234567890"
           \ ])
+
     call cursor(1, 3)
     call feedkeys("\<Esc>\<C-v>ljj", 'xt')
     call assert_equal(['cd', "\u00ab ", '34'],
           \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 4, 0]],
+          \   [[bufnr('%'), 2, 5, 0], [bufnr('%'), 2, 7, 1]],
+          \   [[bufnr('%'), 3, 3, 0], [bufnr('%'), 3, 4, 0]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
     call cursor(1, 4)
     call feedkeys("\<Esc>\<C-v>ljj", 'xt')
     call assert_equal(['de', "\U0001f1e7", '45'],
           \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 5, 0]],
+          \   [[bufnr('%'), 2, 7, 0], [bufnr('%'), 2, 10, 0]],
+          \   [[bufnr('%'), 3, 4, 0], [bufnr('%'), 3, 5, 0]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
     call cursor(1, 5)
     call feedkeys("\<Esc>\<C-v>jj", 'xt')
     call assert_equal(['e', ' ', '5'],
           \ 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('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal([
           \   [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 13, 0]],
           \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 22, 0]],
           \   [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]],
           \ ],
           \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
     call cursor(1, 1)
     call feedkeys("\<Esc>vj", '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
@@ -1877,12 +1916,29 @@
     call setpos("'b", [0, 2, 16, 0])
     call setpos("'c", [0, 2, 0, 0])
     call cursor(1, 1)
+
     call assert_equal(['ghijk', '🇨«ðŸ‡©'],
           \ getregion(getpos("'a"), getpos("'b"), {'type': "\<C-v>" }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 7, 0], [bufnr('%'), 1, 11, 0]],
+          \   [[bufnr('%'), 2, 13, 0], [bufnr('%'), 2, 22, 0]],
+          \ ],
+          \ getregionpos(getpos("'a"), getpos("'b"), {'type': "\<C-v>" }))
+
     call assert_equal(['k«', '🇦«ðŸ‡§«ðŸ‡¨'],
           \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 11, 0], [bufnr('%'), 1, 13, 0]],
+          \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 16, 0]],
+          \ ],
+          \ getregionpos(getpos("'a"), getpos("'b"), {'type': 'v' }))
+
     call assert_equal(['k«'],
           \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 11, 0], [bufnr('%'), 1, 13, 0]],
+          \ ],
+          \ getregionpos(getpos("'a"), getpos("'c"), {'type': 'v' }))
 
     #" use inclusive selection, although 'selection' is exclusive
     call setpos("'a", [0, 1, 11, 0])
@@ -1975,14 +2031,28 @@
     #" virtualedit
     set selection=exclusive
     set virtualedit=all
+
     call cursor(1, 1)
     call feedkeys("\<Esc>2lv2lj", 'xt')
     call assert_equal(['      c', 'x   '],
           \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call assert_equal([
+          \   [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 3, 0]],
+          \   [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 3]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': '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('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
+          \ ],
+          \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
     set virtualedit&
     set selection&