]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1825: wrong cursor position with virt text and 'linebreak' v9.0.1825
authorzeertzjq <zeertzjq@outlook.com>
Wed, 30 Aug 2023 14:55:09 +0000 (16:55 +0200)
committerChristian Brabandt <cb@256bit.org>
Wed, 30 Aug 2023 14:55:09 +0000 (16:55 +0200)
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>
src/charset.c
src/testdir/dumps/Test_prop_inserts_text_before_linebreak_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_prop_inserts_text_before_linebreak_2.dump [new file with mode: 0644]
src/testdir/test_textprop.vim
src/version.c

index 03ef3fd1c6bddc3f371435ecc5c9316a94151241..3cba7a5e0628259c8ffc0429ac6ab8aea0fe8593 100644 (file)
@@ -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 (file)
index 0000000..2009f23
--- /dev/null
@@ -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 (file)
index 0000000..2d8bc50
--- /dev/null
@@ -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| 
index 209b804e88dc536e5736e9a1e28ec01df7bbb825..030955b802c5024f8fd1f6955e858537f0e9163c 100644 (file)
@@ -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
 
index 843db4c5bb0e827c3b071e01c0a02f7e215a92ac..593b7d5f2fe1cff6c744201f8052615b16b4b352 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1825,
 /**/
     1824,
 /**/