]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0913: statusline: cell below the vertical separator keeps the old highlight v9.2.0913
authorHirohito Higashi <h.east.727@gmail.com>
Wed, 5 Aug 2026 18:58:22 +0000 (18:58 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 5 Aug 2026 18:58:22 +0000 (18:58 +0000)
Problem:  When 'statusline' is set, the cell below a vertical separator keeps
          the highlight of the previous status line update and only catches
          up on the next key press (dougaak).
Solution: Also update that cell when the status line of the current window is
          redrawn while showing the ruler (Hirohito Higashi).

related: #20182
fixes:   #20948
closes:  #20949

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/drawscreen.c
src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_01.dump [new file with mode: 0644]
src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_02.dump [new file with mode: 0644]
src/testdir/test_statusline.vim
src/version.c

index d85ae57dcee0662a43533936838d177516ba5f80..d0e3a83734379eadc19dfb2a1c7a9ec19afa02f4 100644 (file)
@@ -651,6 +651,8 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
  *    over the join without changing visible characters.
  *  - Cells where the vsep char is drawn (stl_connected == FALSE) are left
  *    untouched so the VertSplit highlight is preserved.
+ * Called for every cursor movement, thus only cells whose attribute changed
+ * are written to the screen.
  */
     static void
 borrow_stl_vsep_hl(void)
@@ -713,10 +715,14 @@ borrow_stl_vsep_hl(void)
 
        for (int r = start; r < end; r++)
        {
-           unsigned dst_off = LineOffset[r] + dst_col;
+           unsigned    dst_off = LineOffset[r] + dst_col;
+           sattr_T     attr = ScreenAttrs[LineOffset[r] + src_col];
 
-           ScreenAttrs[dst_off] = ScreenAttrs[LineOffset[r] + src_col];
-           screen_char(dst_off, r, dst_col);
+           if (ScreenAttrs[dst_off] != attr)
+           {
+               ScreenAttrs[dst_off] = attr;
+               screen_char(dst_off, r, dst_col);
+           }
        }
     }
 }
@@ -759,7 +765,10 @@ showruler(int always)
     }
 #if defined(FEAT_STL_OPT)
     if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height)
+    {
        redraw_custom_statusline(curwin);
+       borrow_stl_vsep_hl();
+    }
     else
 #endif
        win_redr_ruler(curwin, always, FALSE);
diff --git a/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_01.dump b/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_01.dump
new file mode 100644 (file)
index 0000000..57439b3
--- /dev/null
@@ -0,0 +1,6 @@
+|a+0&#ffffff0@2| @35||+1&&>a+0&&@2| @34
+|b@2| @35||+1&&|b+0&&@2| @34
+|~+0#4040ff13&| @37||+1#0000000&|~+0#4040ff13&| @36
+|~| @37||+1#0000000&|~+0#4040ff13&| @36
+|N+2&#40ff4011|O|R|M|A|L| @32| +0&&|N|O|R|M|A|L| @31
+| +0#0000000#ffffff0@77
diff --git a/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_02.dump b/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_02.dump
new file mode 100644 (file)
index 0000000..27e3a9b
--- /dev/null
@@ -0,0 +1,6 @@
+|a+0&#ffffff0@2| @35||+1&&>a+0&&@2| @34
+|b@2| @35||+1&&|b+0&&@2| @34
+|~+0#4040ff13&| @37||+1#0000000&|~+0#4040ff13&| @36
+|~| @37||+1#0000000&|~+0#4040ff13&| @36
+|N+2&#40ff4011|O|R|M|A|L| @32| +0#ff404010#ffff4012|I|N|S|E|R|T| @31
+|-+2#0000000#ffffff0@1| |I|N|S|E|R|T| |-@1| +0&&@65
index c0dc861a8d91e2c98d13d56630fc1f5614f1b773..ad182fcf36dafcab3b04fa24bf65291158752591 100644 (file)
@@ -1091,4 +1091,38 @@ func Test_statusline_vsep_borrow_hl()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_statusline_vsep_borrow_hl_mode_change()
+  CheckScreendump
+
+  " With 'statusline' set, a mode change repaints the status line through
+  " showruler().  The vsep cell must follow without another key press.
+  let lines =<< trim END
+    hi User1 ctermfg=Red ctermbg=Yellow
+    hi User2 ctermfg=Blue ctermbg=Green
+    set laststatus=2
+    func MyStl()
+      return mode() ==# 'i' ? '%1*INSERT' : '%2*NORMAL'
+    endfunc
+    set statusline=%!MyStl()
+    call setline(1, ['aaa', 'bbb'])
+    vsplit
+    wincmd w
+  END
+  call writefile(lines, 'XTest_statusline_vsep_mode', 'D')
+
+  let buf = RunVimInTerminal('-S XTest_statusline_vsep_mode',
+        \ {'rows': 6, 'cols': 78})
+  call term_sendkeys(buf, "\<C-L>")
+  call VerifyScreenDump(buf, 'Test_statusline_vsep_borrow_hl_mode_01', {})
+
+  call term_sendkeys(buf, "i")
+  call VerifyScreenDump(buf, 'Test_statusline_vsep_borrow_hl_mode_02', {})
+
+  " Leaving Insert mode restores the state of the first dump.
+  call term_sendkeys(buf, "\<Esc>")
+  call VerifyScreenDump(buf, 'Test_statusline_vsep_borrow_hl_mode_01', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index ef0edee5ec9f943bf221bf25aa0a3fe6172f40c4..a5145fff9f77409f951e0929ba3b25097c2d9d19 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    913,
 /**/
     912,
 /**/