summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-08-30 16:55:09 +0200
committerChristian Brabandt <cb@256bit.org>2023-08-30 16:55:09 +0200
commit6e55e85f92aff43c1b3cb564201440f3552d63f0 (patch)
tree51bc0fb9927fe63e9c2b6696989d3fb3f5bb1d8a
parent5bbcfbc4a260bc082829311086c3a1109c40f2d3 (diff)
patch 9.0.1825: wrong cursor position with virt text and 'linebreak'v9.0.1825
Problem: Wrong cursor position with virtual text before a whitespace character and 'linebreak'. Solution: Always set "col_adj" to "size - 1" and apply 'linebreak' after adding the size of 'breakindent' and 'showbreak'. closes: #12956 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
-rw-r--r--src/charset.c113
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_before_linebreak_1.dump6
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_before_linebreak_2.dump6
-rw-r--r--src/testdir/test_textprop.vim19
-rw-r--r--src/version.c2
5 files changed, 87 insertions, 59 deletions
diff --git a/src/charset.c b/src/charset.c
index 03ef3fd1c6..3cba7a5e06 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1118,14 +1118,8 @@ win_lbr_chartabsize(
char_u *s = cts->cts_ptr;
colnr_T vcol = cts->cts_vcol;
#ifdef FEAT_LINEBREAK
- int c;
int size;
- colnr_T col2;
- colnr_T col_adj = 0; // vcol + screen size of tab
- colnr_T colmax;
int mb_added = 0;
- char_u *ps;
- int tab_corr = (*s == TAB);
int n;
char_u *sbr;
int no_sbr = FALSE;
@@ -1248,55 +1242,7 @@ win_lbr_chartabsize(
# endif
# ifdef FEAT_LINEBREAK
- c = *s;
- if (tab_corr)
- col_adj = size - 1;
-
- /*
- * If 'linebreak' set check at a blank before a non-blank if the line
- * needs a break here
- */
- if (wp->w_p_lbr
- && VIM_ISBREAK(c)
- && !VIM_ISBREAK((int)s[1])
- && wp->w_p_wrap
- && wp->w_width != 0)
- {
- /*
- * Count all characters from first non-blank after a blank up to next
- * non-blank after a blank.
- */
- int numberextra = win_col_off(wp);
- col2 = vcol;
- colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
- if (vcol >= colmax)
- {
- colmax += col_adj;
- n = colmax + win_col_off2(wp);
- if (n > 0)
- colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
- }
-
- for (;;)
- {
- ps = s;
- MB_PTR_ADV(s);
- c = *s;
- if (!(c != NUL
- && (VIM_ISBREAK(c)
- || (!VIM_ISBREAK(c)
- && (col2 == vcol || !VIM_ISBREAK((int)*ps))))))
- break;
-
- col2 += win_chartabsize(wp, s, col2);
- if (col2 >= colmax) // doesn't fit
- {
- size = colmax - vcol + col_adj;
- break;
- }
- }
- }
- else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
+ if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
&& wp->w_p_wrap && in_win_border(wp, vcol))
{
++size; // Count the ">" in the last column.
@@ -1314,11 +1260,10 @@ win_lbr_chartabsize(
{
int col_off_prev = win_col_off(wp);
int width2 = wp->w_width - col_off_prev + win_col_off2(wp);
- vcol += mb_added;
+ colnr_T wcol = vcol + col_off_prev;
#ifdef FEAT_PROP_POPUP
- vcol -= wp->w_virtcol_first_char;
+ wcol -= wp->w_virtcol_first_char;
#endif
- colnr_T wcol = vcol + col_off_prev;
colnr_T max_head_vcol = cts->cts_max_head_vcol;
int added = 0;
@@ -1342,6 +1287,8 @@ win_lbr_chartabsize(
if (max_head_vcol <= 0 || vcol < max_head_vcol)
head += head_prev;
}
+ else
+ head_prev = 0;
wcol += col_off_prev;
}
@@ -1374,7 +1321,7 @@ win_lbr_chartabsize(
else if (max_head_vcol < 0)
{
int off = 0;
- if (c != NUL
+ if (*s != NUL
&& ((State & MODE_NORMAL) || cts->cts_start_incl))
off += cts->cts_cur_text_width;
if (off >= prev_rem)
@@ -1386,8 +1333,56 @@ win_lbr_chartabsize(
size += added;
}
+
if (headp != NULL)
*headp = head;
+
+ /*
+ * If 'linebreak' set check at a blank before a non-blank if the line
+ * needs a break here
+ */
+ if (wp->w_p_lbr
+ && VIM_ISBREAK((int)s[0])
+ && !VIM_ISBREAK((int)s[1])
+ && wp->w_p_wrap
+ && wp->w_width != 0)
+ {
+ /*
+ * Count all characters from first non-blank after a blank up to next
+ * non-blank after a blank.
+ */
+ int numberextra = win_col_off(wp);
+ colnr_T col_adj = size - 1;
+ colnr_T colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
+ if (vcol >= colmax)
+ {
+ colmax += col_adj;
+ n = colmax + win_col_off2(wp);
+ if (n > 0)
+ colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
+ }
+
+ colnr_T vcol2 = vcol;
+ for (;;)
+ {
+ char_u *ps = s;
+ MB_PTR_ADV(s);
+ int c = *s;
+ if (!(c != NUL
+ && (VIM_ISBREAK(c)
+ || (!VIM_ISBREAK(c)
+ && (vcol2 == vcol || !VIM_ISBREAK((int)*ps))))))
+ break;
+
+ vcol2 += win_chartabsize(wp, s, vcol2);
+ if (vcol2 >= colmax) // doesn't fit
+ {
+ size = colmax - vcol + col_adj;
+ break;
+ }
+ }
+ }
+
return size;
# endif
#endif
diff --git a/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_1.dump b/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_1.dump
new file mode 100644
index 0000000000..2009f23e8b
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_1.dump
@@ -0,0 +1,6 @@
+|a+0&#ffffff0@49
+| @1|++0#4040ff13&|b+0#e000e06&@9| +0#0000000&@36
+@2|++0#4040ff13&|c+0#0000000&@43>c| @1
+|~+0#4040ff13&| @48
+|~| @48
+| +0#0000000&@31|1|,|9|6|-|1|4|8| @5|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_2.dump b/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_2.dump
new file mode 100644
index 0000000000..2d8bc50c07
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_inserts_text_before_linebreak_2.dump
@@ -0,0 +1,6 @@
+|a+0&#ffffff0@44|b+0#e000e06&@4
+| +0#0000000&@1|++0#4040ff13&|b+0#e000e06&@4| +0#0000000&@41
+@2|++0#4040ff13&|c+0#0000000&@43>c| @1
+|~+0#4040ff13&| @48
+|~| @48
+| +0#0000000&@31|1|,|9|1|-|1|4|8| @5|A|l@1|
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index 209b804e88..030955b802 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -2791,6 +2791,25 @@ func Test_prop_before_tab_skipcol()
call StopVimInTerminal(buf)
endfunc
+func Test_prop_inserts_text_before_linebreak()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ setlocal linebreak showbreak=+ breakindent breakindentopt=shift:2
+ call setline(1, repeat('a', 50) .. ' ' .. repeat('c', 45))
+ call prop_type_add('theprop', #{highlight: 'Special'})
+ call prop_add(1, 51, #{type: 'theprop', text: repeat('b', 10), text_wrap: 'wrap'})
+ normal! $
+ END
+ call writefile(lines, 'XscriptPropsBeforeLinebreak', 'D')
+ let buf = RunVimInTerminal('-S XscriptPropsBeforeLinebreak', #{rows: 6, cols: 50})
+ call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_linebreak_1', {})
+ call term_sendkeys(buf, '05x$')
+ call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_linebreak_2', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_prop_inserts_text_lcs_extends()
CheckRunVimInTerminal
diff --git a/src/version.c b/src/version.c
index 843db4c5bb..593b7d5f2f 100644
--- 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 */
/**/
+ 1825,
+/**/
1824,
/**/
1823,