patch 9.0.0139: truncating virtual text after a line not implemented

Problem:    Truncating virtual text after a line not implemented.
            Cursor positioning wrong with Newline in the text.
Solution:   Implement truncating.  Disallow control characters in the text.
            (closes #10842)
diff --git a/src/testdir/dumps/Test_prop_with_text_after_trunc_1.dump b/src/testdir/dumps/Test_prop_with_text_after_trunc_1.dump
new file mode 100644
index 0000000..c8e6369
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_trunc_1.dump
@@ -0,0 +1,9 @@
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N|E| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @26
+| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e| |l|e|t|s| |w|r|a|p| |a|f|t|e|r| |s|o|…
+|c+0&#ffffff0|u|r|s|o|r| >h|e|r|e| @48
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+| +0#0000000&@41|4|,|8| @10|A|l@1| 
diff --git a/src/testdir/dumps/Test_prop_with_text_after_trunc_2.dump b/src/testdir/dumps/Test_prop_with_text_after_trunc_2.dump
new file mode 100644
index 0000000..c6fd499
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_trunc_2.dump
@@ -0,0 +1,9 @@
+>o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N|…||+1&#ffffff0|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v
+|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|…||+1&#ffffff0|e+0&&| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @3||+1&&|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v
+| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |…||+1&#ffffff0|e+0&&| |s|i|x| |s|e|v|e|n| @10
+|c|u|r|s|o|r| |h|e|r|e| @25||+1&&| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e|…
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|c+0&&|u|r|s|o|r| |h|e|r|e| @10
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @20
+|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |<+1&&|N|a|m|e|]| |[|+|]| |4|,|8| @4|B|o|t
+|:+0&&|3|7|v|s|p| @53
diff --git a/src/testdir/dumps/Test_prop_with_text_after_trunc_3.dump b/src/testdir/dumps/Test_prop_with_text_after_trunc_3.dump
new file mode 100644
index 0000000..5834170
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_trunc_3.dump
@@ -0,0 +1,9 @@
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N||+1&#ffffff0|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e
+|E+0&#ffff4012| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d| |F|O|U|R| |a|n|d| |F|I|…||+1&#ffffff0| +0&&|s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e>n| +0&#ffff4012|o|n||+1&#ffffff0|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e
+|e+0&#ffff4012| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|…||+1&#ffffff0| +0&&|s|i|x| |s|e|v|e|n| @12
+|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @2||+1&&| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1|…
+| |o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D|…||+1&#ffffff0|c+0&&|u|r|s|o|r| |h|e|r|e| @11
+|c|u|r|s|o|r| |h|e|r|e| @24||+1&&|~+0#4040ff13&| @21
+|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @4|2|,|3@1| @10|A|l@1| |<+1&&| |N|a|m|e|]| |[|+|]| |4|,|8| @4|B|o|t
+|:+0&&|3|6|w|i|n|c|m|d| ||| @48
diff --git a/src/testdir/dumps/Test_prop_with_text_after_trunc_4.dump b/src/testdir/dumps/Test_prop_with_text_after_trunc_4.dump
new file mode 100644
index 0000000..165020a
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_trunc_4.dump
@@ -0,0 +1,9 @@
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n||+1&&|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i
+| +0&#ffff4012|O|N|E| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d| |F|O|U|R| |…||+1&#ffffff0|x+0&&| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e>n||+1&&|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i
+| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |…||+1&#ffffff0|x+0&&| |s|e|v|e|n| @18
+|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n||+1&&| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|…
+| |o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |…||+1&#ffffff0|c+0&&|u|r|s|o|r| |h|e|r|e| @14
+|c|u|r|s|o|r| |h|e|r|e| @21||+1&&|~+0#4040ff13&| @24
+|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @3|2|,|3@1| @8|A|l@1| |<+1&&|o| |N|a|m|e|]| |[|+|]| |4|,|8| @6|B|o|t
+|:+0&&|3@1|w|i|n|c|m|d| ||| @48
diff --git a/src/testdir/dumps/Test_prop_with_text_after_trunc_5.dump b/src/testdir/dumps/Test_prop_with_text_after_trunc_5.dump
new file mode 100644
index 0000000..e134443
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_trunc_5.dump
@@ -0,0 +1,9 @@
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r||+1&&|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|…
+| +0&#ffffff0|f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N||+1&#ffffff0|o+0&&|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @7
+|E+0&#ffff4012| |a|n|d| |T|W|O| |a|n|d| |T|H|R|…||+1&#ffffff0| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e|…
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r||+1&&|c+0&&|u|r|s|o|r| |h|e|r|e| @29
+@1|f|i|v|e| |s|i>x| |s|e|v|e|n| +0&#ffff4012|o|n||+1&#ffffff0|~+0#4040ff13&| @39
+|e+0#0000000#ffff4012| |A|N|D| |t|w|o| |A|N|D| |t|h|r|…||+1&#ffffff0|~+0#4040ff13&| @39
+|@@2| @14||+1#0000000&|~+0#4040ff13&| @39
+|<+3#0000000&|m|e|]| |[|+|]| |2|,|2|7| @1|T|o|p| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @9|4|,|8| @11|B|o|t
+|:+0&&|1|8|w|i|n|c|m|d| ||| @48
diff --git a/src/testdir/dumps/Test_prop_with_text_after_wraps_1.dump b/src/testdir/dumps/Test_prop_with_text_after_wraps_1.dump
new file mode 100644
index 0000000..674ea84
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_with_text_after_wraps_1.dump
@@ -0,0 +1,9 @@
+|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N|E| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d| 
+|F|O|U|R| |a|n|d| |F|I|V|E| +0&#ffffff0@46
+|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| 
+|f|o|u|r| |A|N|D| |f|i|v|e| +0&#ffffff0@46
+|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @26
+| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e| |l|e|t|s| |w|r|a|p| |a|f|t|e|r| |s|o|m
+|e| |m|o|r|e| |t|e|x|t| +0&#ffffff0@48
+|c|u|r|s|o|r| >h|e|r|e| @48
+@42|4|,|8| @10|A|l@1| 
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index 216ae20..c6f6739 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -2286,6 +2286,70 @@
   call delete('XscriptPropsWithTextAfterJoined')
 endfunc
 
+func Test_props_with_text_after_truncated()
+  CheckRunVimInTerminal
+
+  let lines =<< trim END
+      call setline(1, ['one two three four five six seven'])
+      call prop_type_add('afterprop', #{highlight: 'Search'})
+      call prop_add(1, 0, #{type: 'afterprop', text: ' ONE and TWO and THREE and FOUR and FIVE'})
+
+      call setline(2, ['one two three four five six seven'])
+      call prop_add(2, 0, #{type: 'afterprop', text: ' one AND two AND three AND four AND five', text_align: 'right'})
+
+      call setline(3, ['one two three four five six seven'])
+      call prop_add(3, 0, #{type: 'afterprop', text: ' one AND two AND three AND four AND five lets wrap after some more text', text_align: 'below'})
+
+      call setline(4, ['cursor here'])
+      normal 4Gfh
+  END
+  call writefile(lines, 'XscriptPropsWithTextAfterTrunc')
+  let buf = RunVimInTerminal('-S XscriptPropsWithTextAfterTrunc', #{rows: 9, cols: 60})
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_trunc_1', {})
+
+  call term_sendkeys(buf, ":37vsp\<CR>gg")
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_trunc_2', {})
+
+  call term_sendkeys(buf, ":36wincmd |\<CR>")
+  call term_sendkeys(buf, "2G$")
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_trunc_3', {})
+
+  call term_sendkeys(buf, ":33wincmd |\<CR>")
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_trunc_4', {})
+
+  call term_sendkeys(buf, ":18wincmd |\<CR>")
+  call term_sendkeys(buf, "0fx")
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_trunc_5', {})
+
+  call StopVimInTerminal(buf)
+  call delete('XscriptPropsWithTextAfterTrunc')
+endfunc
+
+func Test_props_with_text_after_wraps()
+  CheckRunVimInTerminal
+
+  let lines =<< trim END
+      call setline(1, ['one two three four five six seven'])
+      call prop_type_add('afterprop', #{highlight: 'Search'})
+      call prop_add(1, 0, #{type: 'afterprop', text: ' ONE and TWO and THREE and FOUR and FIVE', text_wrap: 'wrap'})
+
+      call setline(2, ['one two three four five six seven'])
+      call prop_add(2, 0, #{type: 'afterprop', text: ' one AND two AND three AND four AND five', text_align: 'right', text_wrap: 'wrap'})
+
+      call setline(3, ['one two three four five six seven'])
+      call prop_add(3, 0, #{type: 'afterprop', text: ' one AND two AND three AND four AND five lets wrap after some more text', text_align: 'below', text_wrap: 'wrap'})
+
+      call setline(4, ['cursor here'])
+      normal 4Gfh
+  END
+  call writefile(lines, 'XscriptPropsWithTextAfterWraps')
+  let buf = RunVimInTerminal('-S XscriptPropsWithTextAfterWraps', #{rows: 9, cols: 60})
+  call VerifyScreenDump(buf, 'Test_prop_with_text_after_wraps_1', {})
+
+  call StopVimInTerminal(buf)
+  call delete('XscriptPropsWithTextAfterWraps')
+endfunc
+
 func Test_removed_prop_with_text_cleans_up_array()
   new
   call setline(1, 'some text here')