]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1785: wrong cursor position with 'showbreak' and lcs-eol v9.0.1785
authorzeertzjq <zeertzjq@outlook.com>
Wed, 23 Aug 2023 18:58:01 +0000 (20:58 +0200)
committerChristian Brabandt <cb@256bit.org>
Wed, 23 Aug 2023 18:58:01 +0000 (20:58 +0200)
Problem:  wrong cursor position with 'showbreak' and lcs-eol
Solution: Add size of 'showbreak' before when 'listchars' "eol" is used.
          Also fix wrong cursor position with wrapping virtual text on
          empty line and 'showbreak'.

closes: #12891

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
src/charset.c
src/move.c
src/testdir/dumps/Test_cursor_position_with_showbreak_1.dump [moved from src/testdir/dumps/Test_cursor_position_with_showbreak.dump with 71% similarity]
src/testdir/dumps/Test_cursor_position_with_showbreak_2.dump [new file with mode: 0644]
src/testdir/dumps/Test_prop_inserts_text_showbreak_22.dump [new file with mode: 0644]
src/testdir/test_breakindent.vim
src/testdir/test_textprop.vim
src/version.c

index a79b1d9aee4c3c7a98dc53f336286ee499802f22..971fefc61464dbc10d60e1b0f281c75e89465fe3 100644 (file)
@@ -1157,11 +1157,13 @@ win_lbr_chartabsize(
     }
 
 #if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
+    int has_lcs_eol = wp->w_p_list && wp->w_lcs_chars.eol != NUL;
+
     /*
      * First get the normal size, without 'linebreak' or text properties
      */
     size = win_chartabsize(wp, s, vcol);
-    if (*s == NUL)
+    if (*s == NUL && !has_lcs_eol)
        size = 0;  // NUL is not displayed
 
 # ifdef FEAT_PROP_POPUP
@@ -1175,8 +1177,11 @@ win_lbr_chartabsize(
 
        // The "$" for 'list' mode will go between the EOL and
        // the text prop, account for that.
-       if (wp->w_p_list && wp->w_lcs_chars.eol != NUL)
+       if (has_lcs_eol)
+       {
            ++vcol;
+           --size;
+       }
 
        for (i = 0; i < cts->cts_text_prop_count; ++i)
        {
@@ -1235,8 +1240,11 @@ win_lbr_chartabsize(
            if (tp->tp_col != MAXCOL && tp->tp_col - 1 > col)
                break;
        }
-       if (wp->w_p_list && wp->w_lcs_chars.eol != NUL)
+       if (has_lcs_eol)
+       {
            --vcol;
+           ++size;
+       }
     }
 # endif
 
@@ -1298,12 +1306,12 @@ win_lbr_chartabsize(
 
     /*
      * May have to add something for 'breakindent' and/or 'showbreak'
-     * string at start of line.
-     * Do not use 'showbreak' at the NUL after the text.
+     * string at the start of a screen line.
      */
     int head = mb_added;
-    sbr = (c == NUL || no_sbr) ? empty_option : get_showbreak_value(wp);
-    if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap)
+    sbr = no_sbr ? empty_option : get_showbreak_value(wp);
+    // When "size" is 0, no new screen line is started.
+    if (size > 0 && wp->w_p_wrap && (*sbr != NUL || wp->w_p_bri))
     {
        int     col_off_prev = win_col_off(wp);
        int     width2 = wp->w_width - col_off_prev + win_col_off2(wp);
@@ -1348,37 +1356,34 @@ win_lbr_chartabsize(
                head_mid += vim_strsize(sbr);
            if (wp->w_p_bri)
                head_mid += get_breakindent_win(wp, line);
-           if (head_mid > 0)
+           if (head_mid > 0 && wcol + size > wp->w_width)
            {
-               if (wcol + size > wp->w_width)
-               {
-                   // calculate effective window width
-                   int prev_rem = wp->w_width - wcol;
-                   int width = width2 - head_mid;
-
-                   if (width <= 0)
-                       width = 1;
-                   // divide "size - prev_width" by "width", rounding up
-                   int cnt = (size - prev_rem + width - 1) / width;
-                   added += cnt * head_mid;
-
-                   if (max_head_vcol == 0
-                                       || vcol + size + added < max_head_vcol)
-                       head += cnt * head_mid;
-                   else if (max_head_vcol > vcol + head_prev + prev_rem)
-                       head += (max_head_vcol - (vcol + head_prev + prev_rem)
+               // calculate effective window width
+               int prev_rem = wp->w_width - wcol;
+               int width = width2 - head_mid;
+
+               if (width <= 0)
+                   width = 1;
+               // divide "size - prev_width" by "width", rounding up
+               int cnt = (size - prev_rem + width - 1) / width;
+               added += cnt * head_mid;
+
+               if (max_head_vcol == 0 || vcol + size + added < max_head_vcol)
+                   head += cnt * head_mid;
+               else if (max_head_vcol > vcol + head_prev + prev_rem)
+                   head += (max_head_vcol - (vcol + head_prev + prev_rem)
                                             + width2 - 1) / width2 * head_mid;
 #ifdef FEAT_PROP_POPUP
-                   else if (max_head_vcol < 0)
-                   {
-                       int off = 0;
-                       if ((State & MODE_NORMAL) || cts->cts_start_incl)
-                           off += cts->cts_cur_text_width;
-                       if (off >= prev_rem)
-                           head += (1 + (off - prev_rem) / width) * head_mid;
-                   }
-#endif
+               else if (max_head_vcol < 0)
+               {
+                   int off = 0;
+                   if (c != NUL
+                            && ((State & MODE_NORMAL) || cts->cts_start_incl))
+                       off += cts->cts_cur_text_width;
+                   if (off >= prev_rem)
+                       head += (1 + (off - prev_rem) / width) * head_mid;
                }
+#endif
            }
 
            size += added;
index 2ba02cf5dc748644d0f56045fe9d91b0a633e569..26a66c1172adcc0957d22ed2b1d688cfe818c669 100644 (file)
@@ -1212,7 +1212,8 @@ curs_columns(
            // column
            char_u *sbr = get_showbreak_value(curwin);
            if (*sbr && *ml_get_cursor() == NUL
-                                   && curwin->w_wcol == vim_strsize(sbr))
+                   && curwin->w_wcol
+                             == (curwin->w_width - width2) + vim_strsize(sbr))
                curwin->w_wcol = 0;
 #endif
        }
similarity index 71%
rename from src/testdir/dumps/Test_cursor_position_with_showbreak.dump
rename to src/testdir/dumps/Test_cursor_position_with_showbreak_1.dump
index 92b79cc4732b86c2b5dd76503694137fb264864f..fd42880e14b2d9698769f206627a2c7d95b70ac6 100644 (file)
@@ -1,5 +1,5 @@
 | +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@71|X
-> +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|e|c|o|n|d| |l|i|n|e| @61
+| +0#0000e05#a8a8a8255@1>s+0#0000000#ffffff0|e|c|o|n|d| |l|i|n|e| @61
 |~+0#4040ff13&| @73
 |~| @73
 |~| @73
diff --git a/src/testdir/dumps/Test_cursor_position_with_showbreak_2.dump b/src/testdir/dumps/Test_cursor_position_with_showbreak_2.dump
new file mode 100644 (file)
index 0000000..e3577d5
--- /dev/null
@@ -0,0 +1,6 @@
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@71|X
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|++0#4040ff13&>$| +0#0000000&@68
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|e|c|o|n|d| |l|i|n|e|$+0#4040ff13&| +0#0000000&@60
+|~+0#4040ff13&| @73
+|~| @73
+|-+2#0000000&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|7|4| @9|A|l@1| 
diff --git a/src/testdir/dumps/Test_prop_inserts_text_showbreak_22.dump b/src/testdir/dumps/Test_prop_inserts_text_showbreak_22.dump
new file mode 100644 (file)
index 0000000..6481f6d
--- /dev/null
@@ -0,0 +1,6 @@
+| +0&#ffffff0@1|1| >1+0#e000e06&|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2
+| +0#0000000&@5|++0#4040ff13&|3+0#e000e06&|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1
+| +0#0000000&@5|++0#4040ff13&|2+0#e000e06&|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3| +0#0000000&@2
+|~+0#4040ff13&| @28
+|~| @28
+| +0#0000000&@29
index 27b1d98475dd7d7adb08402fd9c4ed03d1602f1e..2bc85a35ba35efab5862f94103d9f2aa54428452 100644 (file)
@@ -897,7 +897,9 @@ func Test_cursor_position_with_showbreak()
   let lines =<< trim END
       vim9script
       &signcolumn = 'yes'
-      &showbreak = '+ '
+      &showbreak = '++'
+      &breakindent = true
+      &breakindentopt = 'shift:2'
       var leftcol: number = win_getid()->getwininfo()->get(0, {})->get('textoff')
       repeat('x', &columns - leftcol - 1)->setline(1)
       'second line'->setline(2)
@@ -906,7 +908,13 @@ func Test_cursor_position_with_showbreak()
   let buf = RunVimInTerminal('-S XscriptShowbreak', #{rows: 6})
 
   call term_sendkeys(buf, "AX")
-  call VerifyScreenDump(buf, 'Test_cursor_position_with_showbreak', {})
+  call VerifyScreenDump(buf, 'Test_cursor_position_with_showbreak_1', {})
+  " No line wraps, so changing 'showbreak' should lead to the same screen.
+  call term_sendkeys(buf, "\<C-\>\<C-O>:setlocal showbreak=+\<CR>")
+  call VerifyScreenDump(buf, 'Test_cursor_position_with_showbreak_1', {})
+  " The first line now wraps because of "eol" in 'listchars'.
+  call term_sendkeys(buf, "\<C-\>\<C-O>:setlocal list\<CR>")
+  call VerifyScreenDump(buf, 'Test_cursor_position_with_showbreak_2', {})
 
   call StopVimInTerminal(buf)
 endfunc
index c272f2e5d05e0729b0c99e1e3d05d0ad3bb00607..05bba61644c6f076221834c3a077d2ddf90f88d7 100644 (file)
@@ -2687,6 +2687,8 @@ func Run_test_prop_inserts_text_showbreak(cmd)
   call VerifyScreenDump(buf, 'Test_prop_inserts_text_showbreak_20', {})
   call term_sendkeys(buf, "\<C-E>")
   call VerifyScreenDump(buf, 'Test_prop_inserts_text_showbreak_21', {})
+  call term_sendkeys(buf, "zbx")
+  call VerifyScreenDump(buf, 'Test_prop_inserts_text_showbreak_22', {})
 
   call StopVimInTerminal(buf)
 endfunc
index bcabd0b9c6a7b99ce01185679596ecd3933cbb6c..87584608868f3d6205ebf0e5bb8443573c9dc222 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1785,
 /**/
     1784,
 /**/