To: vim_dev@googlegroups.com Subject: Patch 9.0.0132 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0132 Problem: Multi-byte characters in virtual text not handled correctly. Solution: Count screen cells instead of bytes. Files: src/charset.c, src/drawline.c, src/testdir/test_textprop.vim, src/testdir/dumps/Test_prop_inserts_text_1.dump, src/testdir/dumps/Test_prop_inserts_text_2.dump, src/testdir/dumps/Test_prop_with_text_after_1.dump *** ../vim-9.0.0131/src/charset.c 2022-08-01 12:06:37.302107057 +0100 --- src/charset.c 2022-08-01 16:26:19.058848297 +0100 *************** *** 1097,1105 **** { char_u *p = ((char_u **)wp->w_buffer->b_textprop_text.ga_data)[ -tp->tp_id - 1]; ! int len = (int)STRLEN(p); - // TODO: count screen cells if (tp->tp_col == MAXCOL) { // TODO: truncating --- 1097,1104 ---- { char_u *p = ((char_u **)wp->w_buffer->b_textprop_text.ga_data)[ -tp->tp_id - 1]; ! int len = vim_strsize(p); if (tp->tp_col == MAXCOL) { // TODO: truncating *************** *** 1454,1461 **** if (cursor != NULL) { #ifdef FEAT_PROP_POPUP ! // cursor is after inserted text ! vcol += cts.cts_cur_text_width; #endif if (*ptr == TAB && (State & MODE_NORMAL) --- 1453,1461 ---- if (cursor != NULL) { #ifdef FEAT_PROP_POPUP ! if ((State & MODE_INSERT) == 0) ! // cursor is after inserted text ! vcol += cts.cts_cur_text_width; #endif if (*ptr == TAB && (State & MODE_NORMAL) *** ../vim-9.0.0131/src/drawline.c 2022-08-01 15:52:51.727352432 +0100 --- src/drawline.c 2022-08-01 16:46:29.446876135 +0100 *************** *** 279,285 **** 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 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 --- 279,285 ---- 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 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,1566 **** c_final = NUL; n_extra = (int)STRLEN(p); extra_attr = used_attr; ! n_attr = n_extra; text_prop_attr = 0; if (*ptr == NUL) // don't combine char attr after EOL --- 1560,1566 ---- c_final = NUL; n_extra = (int)STRLEN(p); extra_attr = used_attr; ! n_attr = mb_charlen(p); text_prop_attr = 0; if (*ptr == NUL) // don't combine char attr after EOL *************** *** 1573,1581 **** char_u *l; // Right-align: fill with spaces - // TODO: count screen columns if (right) ! added -= n_extra; if (added < 0 || (below && col == 0)) added = 0; l = alloc(n_extra + added + 1); --- 1573,1580 ---- char_u *l; // Right-align: fill with spaces if (right) ! added -= vim_strsize(p_extra); if (added < 0 || (below && col == 0)) added = 0; l = alloc(n_extra + added + 1); *** ../vim-9.0.0131/src/testdir/test_textprop.vim 2022-08-01 16:11:02.656646804 +0100 --- src/testdir/test_textprop.vim 2022-08-01 16:45:22.883239515 +0100 *************** *** 2199,2206 **** 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 $ END call writefile(lines, 'XscriptPropsWithText') let buf = RunVimInTerminal('-S XscriptPropsWithText', #{rows: 6, cols: 60}) --- 2199,2209 ---- 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 '}) 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,2233 **** --- 2231,2239 ---- 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}) *** ../vim-9.0.0131/src/testdir/dumps/Test_prop_inserts_text_1.dump 2022-08-01 15:52:51.727352432 +0100 --- src/testdir/dumps/Test_prop_inserts_text_1.dump 2022-08-01 16:40:19.065219675 +0100 *************** *** 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 |~+0#4040ff13&| @58 |~| @58 - |~| @58 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| --- 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 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| *** ../vim-9.0.0131/src/testdir/dumps/Test_prop_inserts_text_2.dump 2022-08-01 15:52:51.727352432 +0100 --- src/testdir/dumps/Test_prop_inserts_text_2.dump 2022-08-01 16:40:20.213210932 +0100 *************** *** 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#4040ff13&| @58 |~| @58 - |~| @58 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| --- 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 | +0#0000000&@41|1|,|7|6|-|9|2| @6|A|l@1| *** ../vim-9.0.0131/src/testdir/dumps/Test_prop_with_text_after_1.dump 2022-08-01 11:17:36.761985329 +0100 --- src/testdir/dumps/Test_prop_with_text_after_1.dump 2022-08-01 16:46:41.130814366 +0100 *************** *** 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 | +0#0000000&@41|2|,|1|0| @9|A|l@1| --- 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 ! |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| *** ../vim-9.0.0131/src/version.c 2022-08-01 16:11:02.656646804 +0100 --- src/version.c 2022-08-01 16:48:07.838372781 +0100 *************** *** 737,738 **** --- 737,740 ---- { /* Add new patch number below this line */ + /**/ + 132, /**/ -- Your fault: core dumped /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///