# HG changeset patch # User Bram Moolenaar # Date 1670337004 -3600 # Node ID 1c43d8bad31d9ec9024eb5c10dbcfa6f8e71cc32 # Parent b34c56a60bcba51d3dcd24e98dcc1056a6fe056f patch 9.0.1019: 'smoothscroll' and virtual text above don't work together Commit: https://github.com/vim/vim/commit/56a40fea9c28f8fc918a0db6de4c048da241cf32 Author: Bram Moolenaar Date: Tue Dec 6 14:17:57 2022 +0000 patch 9.0.1019: 'smoothscroll' and virtual text above don't work together Problem: 'smoothscroll' and virtual text above don't work together. (Yee Cheng Chin) Solution: Skip virtual text above when w_skipcol is non-zero. (closes #11665) diff --git a/src/charset.c b/src/charset.c --- a/src/charset.c +++ b/src/charset.c @@ -1195,7 +1195,7 @@ win_lbr_chartabsize( cells = text_prop_position(wp, tp, vcol, (vcol + size) % (wp->w_width - col_off) + col_off, - &n_extra, &p, NULL, NULL); + &n_extra, &p, NULL, NULL, FALSE); #ifdef FEAT_LINEBREAK no_sbr = TRUE; // don't use 'showbreak' now #endif diff --git a/src/drawline.c b/src/drawline.c --- a/src/drawline.c +++ b/src/drawline.c @@ -637,7 +637,8 @@ text_prop_position( int *n_extra, // nr of bytes for virtual text char_u **p_extra, // virtual text int *n_attr, // attribute cells, NULL if not used - int *n_attr_skip) // cells to skip attr, NULL if not used + int *n_attr_skip, // cells to skip attr, NULL if not used + int do_skip) // skip_cells is not zero { int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT); int above = (tp->tp_flags & TP_FLAG_ALIGN_ABOVE); @@ -690,6 +691,8 @@ text_prop_position( else n_used = *n_extra; } + else if (below && before > vcol && do_skip) + before -= vcol; else before = 0; } @@ -1500,15 +1503,75 @@ win_line( area_highlighting = TRUE; } + // When w_skipcol is non-zero and there is virtual text above the actual + // text, then this much of the virtual text is skipped. + int skipcol_in_text_prop_above = 0; + #ifdef FEAT_PROP_POPUP if (WIN_IS_POPUP(wp)) wlv.screen_line_flags |= SLF_POPUP; + + char_u *prop_start; + text_prop_count = get_text_props(wp->w_buffer, lnum, &prop_start, FALSE); + if (text_prop_count > 0) + { + // Make a copy of the properties, so that they are properly + // aligned. + text_props = ALLOC_MULT(textprop_T, text_prop_count); + if (text_props != NULL) + mch_memmove(text_props, prop_start, + text_prop_count * sizeof(textprop_T)); + + // Allocate an array for the indexes. + text_prop_idxs = ALLOC_MULT(int, text_prop_count); + if (text_prop_idxs == NULL) + VIM_CLEAR(text_props); + + if (text_props != NULL) + { + area_highlighting = TRUE; + extra_check = TRUE; + + // When skipping virtual text the props need to be sorted. The + // order is reversed! + if (lnum == wp->w_topline && wp->w_skipcol > 0) + { + for (int i = 0; i < text_prop_count; ++i) + text_prop_idxs[i] = i; + sort_text_props(wp->w_buffer, text_props, + text_prop_idxs, text_prop_count); + } + + // Text props "above" move the line number down to where the text + // is. Only count the ones that are visible, not those that are + // skipped because of w_skipcol. + int text_width = wp->w_width - win_col_off(wp); + for (int i = text_prop_count - 1; i >= 0; --i) + if (text_props[i].tp_flags & TP_FLAG_ALIGN_ABOVE) + { + if (lnum == wp->w_topline + && wp->w_skipcol - skipcol_in_text_prop_above + >= text_width) + { + // This virtual text above is skipped, remove it from + // the array. + skipcol_in_text_prop_above += text_width; + for (int j = i + 1; j < text_prop_count; ++j) + text_props[j - 1] = text_props[j]; + ++i; + --text_prop_count; + } + else + ++wlv.text_prop_above_count; + } + } + } #endif // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the // first character to be displayed. if (wp->w_p_wrap) - v = startrow == 0 ? wp->w_skipcol : 0; + v = startrow == 0 ? wp->w_skipcol - skipcol_in_text_prop_above : 0; else v = wp->w_leftcol; if (v > 0 && !number_only) @@ -1559,7 +1622,8 @@ win_line( #ifdef FEAT_PROP_POPUP // 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) + if ((!wp->w_p_wrap || (lnum == wp->w_topline && wp->w_skipcol > 0)) + && v > wlv.vcol) skip_cells = v - wlv.vcol; #endif @@ -1703,40 +1767,6 @@ win_line( } #endif -#ifdef FEAT_PROP_POPUP - { - char_u *prop_start; - - text_prop_count = get_text_props(wp->w_buffer, lnum, - &prop_start, FALSE); - if (text_prop_count > 0) - { - // Make a copy of the properties, so that they are properly - // aligned. - text_props = ALLOC_MULT(textprop_T, text_prop_count); - if (text_props != NULL) - mch_memmove(text_props, prop_start, - text_prop_count * sizeof(textprop_T)); - - // Allocate an array for the indexes. - text_prop_idxs = ALLOC_MULT(int, text_prop_count); - if (text_prop_idxs == NULL) - VIM_CLEAR(text_props); - - if (text_props != NULL) - { - area_highlighting = TRUE; - extra_check = TRUE; - // text props "above" move the line number down to where the - // text is. - for (int i = 0; i < text_prop_count; ++i) - if (text_props[i].tp_flags & TP_FLAG_ALIGN_ABOVE) - ++wlv.text_prop_above_count; - } - } - } -#endif - win_line_start(wp, &wlv, FALSE); // Repeat for the whole displayed line. @@ -2059,7 +2089,8 @@ win_line( wlv.vcol, wlv.col, &wlv.n_extra, &wlv.p_extra, - &n_attr, &wlv.n_attr_skip); + &n_attr, &wlv.n_attr_skip, + skip_cells > 0); if (wlv.p_extra != prev_p_extra) { // wlv.p_extra was allocated diff --git a/src/proto/drawline.pro b/src/proto/drawline.pro --- a/src/proto/drawline.pro +++ b/src/proto/drawline.pro @@ -1,4 +1,4 @@ /* drawline.c */ -int text_prop_position(win_T *wp, textprop_T *tp, int vcol, int scr_col, int *n_extra, char_u **p_extra, int *n_attr, int *n_attr_skip); +int text_prop_position(win_T *wp, textprop_T *tp, int vcol, int scr_col, int *n_extra, char_u **p_extra, int *n_attr, int *n_attr_skip, int do_skip); int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int nochange, int number_only); /* vim: set ft=c : */ diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_1.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_1.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_1.dump @@ -0,0 +1,8 @@ +>"+0&#ffffff0| |l|i|n|e| |1| @51 +|"| |l|i|n|e| |2| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| +0&#ffffff0@47 +|"| |l|i|n|e| |3| @51 +|"| |l|i|n|e| |4| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|@+0#4040ff13&@2| @56 +| +0#0000000&@41|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_10.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_10.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_10.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +|"| |l|i|n|e| |8| @51 +>"| |l|i|n|e| |9| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |1|0| @50 +@42|9|,|1| @10|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_11.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_11.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_11.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2|e+0#0000000#ffd7ff255|r|t| |b|e|l|o|w| +0&#ffffff0@47 +|"| |l|i|n|e| |8| @51 +>"| |l|i|n|e| |9| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +| +0#0000000&@41|9|,|1| @10|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_12.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_12.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_12.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |8| @51 +|"| |l|i|n|e| |9| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +>"| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +|~| @58 +| +0#0000000&@41|1|0|,|1| @9|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_13.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_13.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_13.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |9| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +>"| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|0|,|1| @9|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_14.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_14.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_14.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2|e+0#0000000#ffd7ff255|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +>"| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|0|,|1| @9|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_15.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_15.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_15.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2| +0#0000000&@2|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@39 +>"| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|0|,|1| @9|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_16.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_16.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_16.dump @@ -0,0 +1,8 @@ +>"+0&#ffffff0| |l|i|n|e| |1|0| @50 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|0|,|1| @9|B|o|t| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_2.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_2.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_2.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |2| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| +0&#ffffff0@47 +|"| |l|i|n|e| |3| @51 +>"| |l|i|n|e| |4| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +@42|4|,|1| @10|1|6|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_3.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_3.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_3.dump @@ -0,0 +1,8 @@ +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| +0&#ffffff0@47 +|"| |l|i|n|e| |3| @51 +>"| |l|i|n|e| |4| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +|"| |l|i|n|e| |6| @51 +@42|4|,|1| @10|3@1|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_4.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_4.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_4.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2|i+0#0000000&|n|e| |3| @51 +>"| |l|i|n|e| |4| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +|"| |l|i|n|e| |6| @51 +|@+0#4040ff13&@2| @56 +| +0#0000000&@41|4|,|1| @10|3@1|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_5.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_5.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_5.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |4| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +>"| |l|i|n|e| |6| @51 +|"| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +@42|6|,|1| @10|5|0|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_6.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_6.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_6.dump @@ -0,0 +1,8 @@ +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +>"| |l|i|n|e| |6| @51 +|"| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +|"| |l|i|n|e| |8| @51 +@42|6|,|1| @10|6@1|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_7.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_7.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_7.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2|e+0#0000000#ffd7ff255|r|t| |a|b|o|v|e| |2| +0&#ffffff0@45 +|"| |l|i|n|e| |5| @51 +>"| |l|i|n|e| |6| @51 +|"| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +|"| |l|i|n|e| |8| @51 +|@+0#4040ff13&@2| @56 +| +0#0000000&@41|6|,|1| @10|6@1|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_8.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_8.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_8.dump @@ -0,0 +1,8 @@ +|<+0#4040ff13#ffffff0@2|i+0#0000000&|n|e| |5| @51 +>"| |l|i|n|e| |6| @51 +|"| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +|"| |l|i|n|e| |8| @51 +|"| |l|i|n|e| |9| @51 +|@+0#4040ff13&@2| @56 +| +0#0000000&@41|6|,|1| @10|6@1|%| diff --git a/src/testdir/dumps/Test_prop_above_below_smoothscroll_9.dump b/src/testdir/dumps/Test_prop_above_below_smoothscroll_9.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_smoothscroll_9.dump @@ -0,0 +1,8 @@ +|"+0&#ffffff0| |l|i|n|e| |6| @51 +|"| |l|i|n|e| |7| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| +0&#ffffff0@47 +>"| |l|i|n|e| |8| @51 +|"| |l|i|n|e| |9| @51 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |1| +0&#ffffff0@45 +|i+0&#ffd7ff255|n|s|e|r|t| |b|e|l|o|w| |2| +0&#ffffff0@45 +@42|8|,|1| @10|8|3|%| 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 @@ -3113,6 +3113,34 @@ func Test_prop_below_split_line() call StopVimInTerminal(buf) endfunc +func Test_prop_above_below_smoothscroll() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + setline(1, range(1, 10)->mapnew((_, v) => '" line ' .. v)) + + set smoothscroll wrap + call prop_type_add('mytype', {highlight: 'DiffChange'}) + call prop_add(3, 0, {text: "insert above", type: "mytype", text_align: 'above'}) + call prop_add(5, 0, {text: "insert above 1", type: "mytype", text_align: 'above'}) + call prop_add(5, 0, {text: "insert above 2", type: "mytype", text_align: 'above'}) + call prop_add(7, 0, {text: "insert below", type: "mytype", text_align: 'below'}) + call prop_add(9, 0, {text: "insert below 1", type: "mytype", text_align: 'below'}) + call prop_add(9, 0, {text: "insert below 2", type: "mytype", text_align: 'below'}) + END + call writefile(lines, 'XscriptPropsSmoothscroll', 'D') + let buf = RunVimInTerminal('-S XscriptPropsSmoothscroll', #{rows: 8, cols: 60}) + call VerifyScreenDump(buf, 'Test_prop_above_below_smoothscroll_1', {}) + + for nr in range(2, 16) + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_prop_above_below_smoothscroll_' .. nr, {}) + endfor + + call StopVimInTerminal(buf) +endfunc + func Test_props_with_text_override() CheckRunVimInTerminal diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1019, +/**/ 1018, /**/ 1017,