# HG changeset patch # User Bram Moolenaar # Date 1665428405 -7200 # Node ID 8ea77a6ceff067ba5731089c70d84e1720b666a7 # Parent df5ddde37685e19e2d7c4beac19fad09444b1fdf patch 9.0.0716: with 'nowrap' virtual text "after" does not scroll left Commit: https://github.com/vim/vim/commit/cd105417a53fcf97c0935f3468201ef11516c9f1 Author: Bram Moolenaar Date: Mon Oct 10 19:50:42 2022 +0100 patch 9.0.0716: with 'nowrap' virtual text "after" does not scroll left Problem: With 'nowrap' virtual text "after" does not scroll left. Solution: Skip part of the virtual text that is left of the window. (closes #11320) Fix going beyond the last column of the window. diff --git a/src/drawline.c b/src/drawline.c --- a/src/drawline.c +++ b/src/drawline.c @@ -975,7 +975,11 @@ win_line( int n_attr3 = 0; // chars with overruling special attr int saved_attr3 = 0; // char_attr saved for n_attr3 - int n_skip = 0; // nr of chars to skip for 'nowrap' + int n_skip = 0; // nr of cells to skip for 'nowrap' or + // concealing + int skip_cells = 0; // nr of cells to skip for virtual text + // after the line, when w_skipcol is + // larger than the text length int fromcol_prev = -2; // start of inverting after cursor int noinvcur = FALSE; // don't invert the cursor @@ -1504,6 +1508,11 @@ win_line( n_skip = v - wlv.vcol; } + // If there the text doesn't reach to the desired column, need to skip + // "skip_cells" cells when virtual text follows. + if (!wp->w_p_wrap && v > wlv.vcol) + skip_cells = v - wlv.vcol; + // Adjust for when the inverted text is before the screen, // and when the start of the inverted text is before the screen. if (wlv.tocol <= wlv.vcol) @@ -1897,10 +1906,20 @@ win_line( int tpi = text_prop_idxs[pi]; textprop_T *tp = &text_props[tpi]; proptype_T *pt = text_prop_type_by_id( - wp->w_buffer, tp->tp_type); + wp->w_buffer, tp->tp_type); - if (pt != NULL && (pt->pt_hl_id > 0 - || tp->tp_id < 0) && tp->tp_id != -MAXCOL) + // Only use a text property that can be displayed. + // Skip "after" properties when wrap is off and at the + // end of the window. + if (pt != NULL + && (pt->pt_hl_id > 0 || tp->tp_id < 0) + && tp->tp_id != -MAXCOL + && !(tp->tp_id < 0 + && !wp->w_p_wrap + && (tp->tp_flags & (TP_FLAG_ALIGN_RIGHT + | TP_FLAG_ALIGN_ABOVE + | TP_FLAG_ALIGN_BELOW)) == 0 + && wlv.col >= wp->w_width)) { if (pt->pt_hl_id > 0) used_attr = syn_id2attr(pt->pt_hl_id); @@ -2015,6 +2034,30 @@ win_line( } } + // If the text didn't reach until the first window + // column we need to skip cells. + if (skip_cells > 0) + { + if (wlv.n_extra > skip_cells) + { + wlv.n_extra -= skip_cells; + wlv.p_extra += skip_cells; + n_attr_skip -= skip_cells; + if (n_attr_skip < 0) + n_attr_skip = 0; + skip_cells = 0; + } + else + { + // the whole text is left of the window, drop + // it and advance to the next one + skip_cells -= wlv.n_extra; + wlv.n_extra = 0; + n_attr_skip = 0; + bail_out = TRUE; + } + } + // If another text prop follows the condition below at // the last window column must know. // If this is an "above" text prop and 'nowrap' the we diff --git a/src/testdir/dumps/Test_text_after_nowrap_1.dump b/src/testdir/dumps/Test_text_after_nowrap_1.dump --- a/src/testdir/dumps/Test_text_after_nowrap_1.dump +++ b/src/testdir/dumps/Test_text_after_nowrap_1.dump @@ -1,8 +1,8 @@ -|f+0&#ffffff0|i|r|s|t| |l|i|n|e| @1|a+0&#ffd7ff255|f|t|e|r| |t|h|e| |t|e|x|t| |a|f|t|e|r| |t|h|e| |t|e|x|t| |a|f|t|e|r| |t|h|e| |t|e|x|t| |a|f|t -|s+0&#ffffff0|e|c|o|n|d| >l|i|n|e| |s|e|c|o|n|d| |l|i|n|e| |s|e|c|o|n|d| |l|i|n|e| |s|e|c|o|n|d| |l|i|n|e| |s|e|c|o|n|d| |l|i|n|e| +|f+0&#ffffff0|i|r|s|t| |l|i|n|e| @1|r+0&#ffd7ff255|i|g|h|t| |a|f|t|e|r| |t|h|e| |t|e|x|t| |r|i|g|h|t| |a|f|t|e|r| |t|h|e| |t|e|x|t| |r|i|g|h|t| +|0+0&#ffffff0| >1| |2| |3| |4| |5| |6| |7| |8| |9| |1|0| |1@1| |1|2| |1|3| |1|4| |1|5| |1|6| |1|7| |1|8| |1|9| |2|0| |2|1| |2@1| |2 |t|h|i|r|d| @54 |f|o|u|r|t|h| @53 |~+0#4040ff13&| @58 |~| @58 |~| @58 -| +0#0000000&@41|2|,|8| @10|A|l@1| +| +0#0000000&@41|2|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_text_after_nowrap_2.dump b/src/testdir/dumps/Test_text_after_nowrap_2.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_text_after_nowrap_2.dump @@ -0,0 +1,8 @@ +| +0&#ffd7ff255|r|i|g|h|t| |a|f|t|e|r| |t|h|e| | +0&#ffffff0@2|i+0&#ffd7ff255|n| |t|h|e| |m|i|d@1|l|e| |i|n| |t|h|e| |m|i|d@1|l|e| |i|n| |t|h|e| |m|i|d@1|l +|2+0&#ffffff0|1| |2@1| |2|3| |2|4| |2|5| |2|6| |2|7| |2|8| |2|9| |3|0| >3|1| |3|2| |3@1| |3|4| |3|5| |3|6| |3|7| |3|8| |3|9| |4|0| +@60 +@60 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|8|4| @9|A|l@1| diff --git a/src/testdir/dumps/Test_text_after_nowrap_3.dump b/src/testdir/dumps/Test_text_after_nowrap_3.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_text_after_nowrap_3.dump @@ -0,0 +1,8 @@ +|h+0&#ffd7ff255|e| |m|i|d@1|l|e| | +0&#ffffff0|t+0&#ffd7ff255|h|e| |l|a|s|t| |o|n|e| |t|h|e| |l|a|s|t| |o|n|e| |t|h|e| |l|a|s|t| |o|n|e| | +0&#ffffff0@9 +|4|3| |4@1| |4|5| |4|6| |4|7| |4|8| |4|9| |5|0| |5|1| |5|2| >5|3| |5|4| |5@1| |5|6| |5|7| |5|8| |5|9| |6|0| |6|1| |6|2| +@60 +@60 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|1|5|0| @8|A|l@1| diff --git a/src/testdir/dumps/Test_text_after_nowrap_4.dump b/src/testdir/dumps/Test_text_after_nowrap_4.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_text_after_nowrap_4.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@59 +|9| |7|0| |7|1| |7|2| |7|3| |7|4| |7|5| |7|6| |7@1| |7|8| |7>9| @28 +@60 +@60 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|2@1|9| @8|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 @@ -3214,30 +3214,44 @@ endfunc func Test_text_after_nowrap() CheckRunVimInTerminal - " FIXME: the second property causes a hang let lines =<< trim END vim9script - setline(1, ['first line', 'second line '->repeat(50), 'third', 'fourth']) + setline(1, ['first line', range(80)->join(' '), 'third', 'fourth']) set nowrap prop_type_add('theprop', {highlight: 'DiffChange'}) prop_add(1, 0, { type: 'theprop', - text: 'after the text '->repeat(5), + text: 'right after the text '->repeat(3), text_align: 'after', text_padding_left: 2, }) - #prop_add(1, 0, { - # type: 'theprop', - # text: 'after the text '->repeat(5), - # text_align: 'after', - # text_padding_left: 2, - #}) + prop_add(1, 0, { + type: 'theprop', + text: 'in the middle '->repeat(4), + text_align: 'after', + text_padding_left: 3, + }) + prop_add(1, 0, { + type: 'theprop', + text: 'the last one '->repeat(3), + text_align: 'after', + text_padding_left: 1, + }) normal 2Gw END call writefile(lines, 'XTextAfterNowrap', 'D') let buf = RunVimInTerminal('-S XTextAfterNowrap', #{rows: 8, cols: 60}) call VerifyScreenDump(buf, 'Test_text_after_nowrap_1', {}) + call term_sendkeys(buf, "30w") + call VerifyScreenDump(buf, 'Test_text_after_nowrap_2', {}) + + call term_sendkeys(buf, "22w") + call VerifyScreenDump(buf, 'Test_text_after_nowrap_3', {}) + + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_text_after_nowrap_4', {}) + call StopVimInTerminal(buf) endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -700,6 +700,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 716, +/**/ 715, /**/ 714,