Commit: patch 9.2.0913: statusline: cell below the vertical separator keeps the old highlight

Christian Brabandt <[email protected]> Wed, 5 Aug 2026 21:15:07 +0200
Newsgroups gmane.editors.vim.devel
Message-ID <[email protected]>
patch 9.2.0913: statusline: cell below the vertical separator keeps the old highlight

Commit: https://github.com/vim/vim/commit/d1bfcd17c4db302b70ddd585bfcc7fa046baba35
Author: Hirohito Higashi <[email protected]>
Date:   Wed Aug 5 18:58:22 2026 +0000

    patch 9.2.0913: statusline: cell below the vertical separator keeps the old highlight
    
    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) <[email protected]>
    Signed-off-by: Hirohito Higashi <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/drawscreen.c b/src/drawscreen.c
index d85ae57dc..d0e3a8373 100644
--- a/src/drawscreen.c
+++ b/src/drawscreen.c
@@ -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
index 000000000..57439b32c
--- /dev/null
+++ b/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_01.dump
@@ -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
index 000000000..27e3a9b16
--- /dev/null
+++ b/src/testdir/dumps/Test_statusline_vsep_borrow_hl_mode_02.dump
@@ -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
diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim
index c0dc861a8..ad182fcf3 100644
--- a/src/testdir/test_statusline.vim
+++ b/src/testdir/test_statusline.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index ef0edee5e..a5145fff9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    913,
 /**/
     912,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups "vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1wrh51-00Eksv-F4%40256bit.org.