diff options
-rw-r--r-- | src/nvim/ops.c | 35 | ||||
-rw-r--r-- | test/old/testdir/test_registers.vim | 17 |
2 files changed, 45 insertions, 7 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c index d51b4cc88b..2491621fbc 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5236,18 +5236,37 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, // Find the end of each line and save it into the array. if (str_list) { for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) { - size_t ss_len = strlen(*ss); - pp[lnum] = cbuf_to_string(*ss, ss_len); - maxlen = MAX(maxlen, ss_len); + pp[lnum] = cstr_to_string(*ss); + if (yank_type == kMTBlockWise) { + size_t charlen = mb_string2cells(*ss); + maxlen = MAX(maxlen, charlen); + } } } else { size_t line_len; for (const char *start = str, *end = str + len; start < end + extraline; start += line_len + 1, lnum++) { - assert(end - start >= 0); - line_len = (size_t)((char *)xmemscan(start, '\n', (size_t)(end - start)) - start); - maxlen = MAX(maxlen, line_len); + int charlen = 0; + + 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); + maxlen = MAX(maxlen, (size_t)charlen); // When appending, copy the previous line and free it after. size_t extra = append ? pp[--lnum].size : 0; @@ -5255,7 +5274,9 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, if (extra > 0) { memcpy(s, pp[lnum].data, extra); } - memcpy(s + extra, start, line_len); + if (line_len > 0) { + memcpy(s + extra, start, line_len); + } size_t s_len = extra + line_len; if (append) { 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' |