# HG changeset patch # User Bram Moolenaar # Date 1659369605 -7200 # Node ID 32aee589fc9a6ba438bf8e73c95181456ff1d20a # Parent 902abc03f8ee7c915c09e53c3dfe46ed29895d06 patch 9.0.0132: multi-byte characters in virtual text not handled correctly Commit: https://github.com/vim/vim/commit/09ff4b54fb86a64390ba9c609853c6410ea6197c Author: Bram Moolenaar Date: Mon Aug 1 16:51:02 2022 +0100 patch 9.0.0132: multi-byte characters in virtual text not handled correctly Problem: Multi-byte characters in virtual text not handled correctly. Solution: Count screen cells instead of bytes. diff --git a/src/charset.c b/src/charset.c --- a/src/charset.c +++ b/src/charset.c @@ -1097,9 +1097,8 @@ win_lbr_chartabsize( { char_u *p = ((char_u **)wp->w_buffer->b_textprop_text.ga_data)[ -tp->tp_id - 1]; - int len = (int)STRLEN(p); + int len = vim_strsize(p); - // TODO: count screen cells if (tp->tp_col == MAXCOL) { // TODO: truncating @@ -1454,8 +1453,9 @@ getvcol( if (cursor != NULL) { #ifdef FEAT_PROP_POPUP - // cursor is after inserted text - vcol += cts.cts_cur_text_width; + if ((State & MODE_INSERT) == 0) + // cursor is after inserted text + vcol += cts.cts_cur_text_width; #endif if (*ptr == TAB && (State & MODE_NORMAL) diff --git a/src/drawline.c b/src/drawline.c --- a/src/drawline.c +++ b/src/drawline.c @@ -279,7 +279,7 @@ win_line( int screen_row; // row on the screen, incl w_winrow char_u extra[21]; // "%ld " and 'fdc' must fit in here - int n_extra = 0; // number of extra chars + int n_extra = 0; // number of extra bytes char_u *p_extra = NULL; // string of extra chars, plus NUL char_u *p_extra_free = NULL; // p_extra needs to be freed int c_extra = NUL; // extra chars, all the same @@ -1560,7 +1560,7 @@ win_line( c_final = NUL; n_extra = (int)STRLEN(p); extra_attr = used_attr; - n_attr = n_extra; + n_attr = mb_charlen(p); text_prop_attr = 0; if (*ptr == NUL) // don't combine char attr after EOL @@ -1573,9 +1573,8 @@ win_line( char_u *l; // Right-align: fill with spaces - // TODO: count screen columns if (right) - added -= n_extra; + added -= vim_strsize(p_extra); if (added < 0 || (below && col == 0)) added = 0; l = alloc(n_extra + added + 1); diff --git a/src/testdir/dumps/Test_prop_inserts_text_1.dump b/src/testdir/dumps/Test_prop_inserts_text_1.dump --- a/src/testdir/dumps/Test_prop_inserts_text_1.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_1.dump @@ -1,6 +1,6 @@ |i+0&#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| |s|o |m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @27 +|p|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @40 |~+0#4040ff13&| @58 |~| @58 -|~| @58 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_2.dump b/src/testdir/dumps/Test_prop_inserts_text_2.dump --- a/src/testdir/dumps/Test_prop_inserts_text_2.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_2.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @23 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38 |~+0#4040ff13&| @58 |~| @58 -|~| @58 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_after_1.dump b/src/testdir/dumps/Test_prop_with_text_after_1.dump --- a/src/testdir/dumps/Test_prop_with_text_after_1.dump +++ b/src/testdir/dumps/Test_prop_with_text_after_1.dump @@ -1,6 +1,6 @@ |s+0&#ffffff0|o|m|e| |t|e|x|t| |h|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |t|h|e|r|e| +0&#ffff4012|A|F|T|E|R| | +0&#ffffff0@10| +0#ffffff16#e000002|R|I|G|H|T| | +0#0000000#5fd7ff255|B|E|L|O|W| | +0&#ffffff0@52 |L|a|s|t| |l|i|n|e>.| +0&#ffff4012|A|f|t|e|r| |L|a|s|t| | +0&#ffffff0@37 -|~+0#4040ff13&| @58 -|~| @58 +|r|i|g|h|t| |h|e|r|e| @37|s+0#ffffff16#e000002|ö|m|e|和*&|平|t+&|é|x|t +|~+0#4040ff13#ffffff0| @58 | +0#0000000&@41|2|,|1|0| @9|A|l@1| diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -2199,8 +2199,11 @@ func Test_prop_inserts_text() call prop_add(1, 18, #{type: 'someprop', text: 'SOME '}) call prop_add(1, 38, #{type: 'otherprop', text: "OTHER\t"}) call prop_add(1, 69, #{type: 'moreprop', text: 'MORE '}) - redraw normal $ + + call setline(2, 'prepost') + call prop_type_add('multibyte', #{highlight: 'Visual'}) + call prop_add(2, 4, #{type: 'multibyte', text: 'söme和平téxt'}) END call writefile(lines, 'XscriptPropsWithText') let buf = RunVimInTerminal('-S XscriptPropsWithText', #{rows: 6, cols: 60}) @@ -2228,6 +2231,9 @@ func Test_props_with_text_after() call setline(2, 'Last line.') call prop_add(2, 0, #{type: 'afterprop', text: ' After Last ', text_align: 'after'}) normal G$ + + call setline(3, 'right here') + call prop_add(3, 0, #{type: 'rightprop', text: 'söme和平téxt', text_align: 'right'}) END call writefile(lines, 'XscriptPropsWithTextAfter') let buf = RunVimInTerminal('-S XscriptPropsWithTextAfter', #{rows: 6, cols: 60}) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -736,6 +736,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 132, +/**/ 131, /**/ 130,