]> granicus.if.org Git - vim/commitdiff
patch 9.0.0099: scrollback can be wrong after redrawing the command line v9.0.0099
authorzeertzjq <zeertzjq@outlook.com>
Thu, 28 Jul 2022 11:34:09 +0000 (12:34 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 28 Jul 2022 11:34:09 +0000 (12:34 +0100)
Problem:    Scrollback can be wrong after redrawing the command line.
Solution:   Clear unfinished scrollback when redrawing. (closes #10807)

src/ex_getln.c
src/message.c
src/proto/message.pro
src/testdir/test_messages.vim
src/version.c

index a5196fcf6b207c96bef9a17f76645de8822fe246..2a1fe3dc6fd42e9d29f619e08792c6dc7524b7ca 100644 (file)
@@ -3892,6 +3892,7 @@ redrawcmd(void)
        return;
     }
 
+    sb_text_restart_cmdline();
     msg_start();
     redrawcmdprompt();
 
@@ -4106,7 +4107,7 @@ get_cmdline_info(void)
 
 #if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO)
 /*
- * Get pointer to the command line info to use. save_ccline() may clear
+ * Get pointer to the command line info to use. save_cmdline() may clear
  * ccline and put the previous value in prev_ccline.
  */
     static cmdline_info_T *
index 7ba82fa050ba5dc4217a4ac318b241c1e4d88aea..50a174928c4891f918001426eb4db609d22a0ab7 100644 (file)
@@ -2535,6 +2535,7 @@ store_sb_text(
            || do_clear_sb_text == SB_CLEAR_CMDLINE_DONE)
     {
        clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL);
+       msg_sb_eol();  // prevent messages from overlapping
        do_clear_sb_text = SB_CLEAR_NONE;
     }
 
@@ -2579,23 +2580,58 @@ may_clear_sb_text(void)
 }
 
 /*
- * Starting to edit the command line, do not clear messages now.
+ * Starting to edit the command line: do not clear messages now.
  */
     void
 sb_text_start_cmdline(void)
 {
+    if (do_clear_sb_text == SB_CLEAR_CMDLINE_BUSY)
+       // Invoking command line recursively: the previous-level command line
+       // doesn't need to be remembered as it will be redrawn when returning
+       // to that level.
+       sb_text_restart_cmdline();
+    else
+    {
+       msg_sb_eol();
+       do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
+    }
+}
+
+/*
+ * Redrawing the command line: clear the last unfinished line.
+ */
+    void
+sb_text_restart_cmdline(void)
+{
+    msgchunk_T *tofree;
+
+    // Needed when returning from nested command line.
     do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
-    msg_sb_eol();
+
+    if (last_msgchunk == NULL || last_msgchunk->sb_eol)
+       // No unfinished line: don't clear anything.
+       return;
+
+    tofree = msg_sb_start(last_msgchunk);
+    last_msgchunk = tofree->sb_prev;
+    if (last_msgchunk != NULL)
+       last_msgchunk->sb_next = NULL;
+    while (tofree != NULL)
+    {
+       msgchunk_T *tofree_next = tofree->sb_next;
+
+       vim_free(tofree);
+       tofree = tofree_next;
+    }
 }
 
 /*
- * Ending to edit the command line.  Clear old lines but the last one later.
+ * Ending to edit the command line: clear old lines but the last one later.
  */
     void
 sb_text_end_cmdline(void)
 {
     do_clear_sb_text = SB_CLEAR_CMDLINE_DONE;
-    msg_sb_eol();
 }
 
 /*
index d3ec9490308f45b15158745c004a0bff4936abb8..3f8a8fe2e39eeaab93a9fa9b62fa2cf0439229b8 100644 (file)
@@ -48,6 +48,7 @@ void msg_puts_attr(char *s, int attr);
 int message_filtered(char_u *msg);
 void may_clear_sb_text(void);
 void sb_text_start_cmdline(void);
+void sb_text_restart_cmdline(void);
 void sb_text_end_cmdline(void);
 void clear_sb_text(int all);
 void show_sb_text(void);
index 1967a3efa783be2daec2d806358c3773a9ecc161..acdbe189ab2d858979d30c3e548376f71aa6e42c 100644 (file)
@@ -176,7 +176,9 @@ func Test_message_more()
   let buf = RunVimInTerminal('', {'rows': 6})
   call term_sendkeys(buf, ":call setline(1, range(1, 100))\n")
 
-  call term_sendkeys(buf, ":%p#\n")
+  call term_sendkeys(buf, ":%pfoo\<C-H>\<C-H>\<C-H>#")
+  call WaitForAssert({-> assert_equal(':%p#', term_getline(buf, 6))})
+  call term_sendkeys(buf, "\n")
   call WaitForAssert({-> assert_equal('  5 5', term_getline(buf, 5))})
   call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))})
 
@@ -252,6 +254,13 @@ func Test_message_more()
   call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 5))})
   call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))})
 
+  " A command line that doesn't print text is appended to scrollback,
+  " even if it invokes a nested command line.
+  call term_sendkeys(buf, ":\<C-R>=':'\<CR>:\<CR>g<")
+  call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 4))})
+  call WaitForAssert({-> assert_equal(':::', term_getline(buf, 5))})
+  call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))})
+
   call term_sendkeys(buf, ":%p#\n")
   call WaitForAssert({-> assert_equal('  5 5', term_getline(buf, 5))})
   call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))})
index e576860823e18deb1e3f330b8f8a15b63311c149..c0a0315a9a317932721f83b9e48e0dbd1b437f42 100644 (file)
@@ -735,6 +735,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    99,
 /**/
     98,
 /**/