diff options
author | zeertzjq <zeertzjq@outlook.com> | 2025-02-09 08:30:58 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2025-02-09 08:46:55 +0800 |
commit | 6f0a91579f3b5d30d23420249a74fba432a27a24 (patch) | |
tree | 0f0f0ef5c355ad2f81d60b4d3306f3121f5da40f | |
parent | 00bce2723fb3b6e36bb7b0b0570c33ffc9508b78 (diff) | |
download | rneovim-6f0a91579f3b5d30d23420249a74fba432a27a24.tar.gz rneovim-6f0a91579f3b5d30d23420249a74fba432a27a24.tar.bz2 rneovim-6f0a91579f3b5d30d23420249a74fba432a27a24.zip |
vim-patch:9.1.1083: setreg() doesn't correctly handle mbyte chars in blockwise mode
Problem: setreg() doesn't correctly handle mbyte chars in blockwise
mode
Solution: use mb_ptr2len_len function pointer (Yee Cheng Chin)
setreg() will automatically calculate the width when a blockwise mode is
specified, but it does not properly calculate the line widths of mbyte
characters when value is passed as newline-terminated string. It does
work when value is passed as a list of lines though.
Fix this by properly using the mbyte function pointer to increment the
loop counter.
closes: vim/vim#16596
https://github.com/vim/vim/commit/a17f8bfb282805ee8ded014089d3094ef6dbf913
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
-rw-r--r-- | src/nvim/ops.c | 11 | ||||
-rw-r--r-- | test/old/testdir/test_registers.vim | 17 |
2 files changed, 26 insertions, 2 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6c15d9a555..2491621fbc 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5248,14 +5248,21 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, start < end + extraline; start += line_len + 1, lnum++) { int charlen = 0; - const char *line_end; - for (line_end = start; line_end < end; line_end++) { + + const char *line_end = start; + while (line_end < end) { // find the end of the line if (*line_end == '\n') { break; } if (yank_type == kMTBlockWise) { charlen += utf_ptr2cells_len(line_end, (int)(end - line_end)); } + + if (*line_end == NUL) { + line_end++; // registers can have NUL chars + } else { + line_end += utf_ptr2len_len(line_end, (int)(end - line_end)); + } } assert(line_end - start >= 0); line_len = (size_t)(line_end - start); diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim index e5add9414f..fbacdaa2a0 100644 --- a/test/old/testdir/test_registers.vim +++ b/test/old/testdir/test_registers.vim @@ -435,6 +435,23 @@ func Test_set_register() enew! endfunc +" Test for blockwise register width calculations +func Test_set_register_blockwise_width() + " Test for regular calculations and overriding the width + call setreg('a', "12\n1234\n123", 'b') + call assert_equal("\<c-v>4", getreginfo('a').regtype) + call setreg('a', "12\n1234\n123", 'b1') + call assert_equal("\<c-v>1", getreginfo('a').regtype) + call setreg('a', "12\n1234\n123", 'b6') + call assert_equal("\<c-v>6", getreginfo('a').regtype) + + " Test for Unicode parsing + call setreg('a', "z😅😅z\n12345", 'b') + call assert_equal("\<c-v>6", getreginfo('a').regtype) + call setreg('a', ["z😅😅z", "12345"], 'b') + call assert_equal("\<c-v>6", getreginfo('a').regtype) +endfunc + " Test for clipboard registers (* and +) func Test_clipboard_regs() throw 'skipped: needs clipboard=autoselect,autoselectplus' |