changeset 30763:8ea77a6ceff0 v9.0.0716

patch 9.0.0716: with 'nowrap' virtual text "after" does not scroll left Commit: https://github.com/vim/vim/commit/cd105417a53fcf97c0935f3468201ef11516c9f1 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Mon, 10 Oct 2022 21:00:05 +0200
parents df5ddde37685
children 26f6dfa606cf
files src/drawline.c src/testdir/dumps/Test_text_after_nowrap_1.dump src/testdir/dumps/Test_text_after_nowrap_2.dump src/testdir/dumps/Test_text_after_nowrap_3.dump src/testdir/dumps/Test_text_after_nowrap_4.dump src/testdir/test_textprop.vim src/version.c
diffstat 7 files changed, 99 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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| 
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| 
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| 
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| 
--- 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
 
--- 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,