patch 9.0.0595: extra newline in messages after a verbose shell message

Problem:    Extra newline in messages after a verbose shell message.
Solution:   Output the newline with msg_putchar_attr(). (closes #11233)
            Make it possible to filter a screendump before comparing it.
diff --git a/src/message.c b/src/message.c
index ee11758..fe02aed 100644
--- a/src/message.c
+++ b/src/message.c
@@ -2602,7 +2602,8 @@
     if (msg_win != NULL)
 	popup_show_message_win();
 #endif
-    if (p_more && !recurse)
+    // Store the text for scroll back, unless it's a newline by itself.
+    if (p_more && !recurse && !(s == sb_str + 1 && *sb_str == '\n'))
 	store_sb_text(&sb_str, s, attr, &sb_col, FALSE);
 
     msg_check();
diff --git a/src/misc2.c b/src/misc2.c
index 8419402..5d36cc1 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1795,7 +1795,7 @@
     {
 	verbose_enter();
 	smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd);
-	out_char('\n');
+	msg_putchar_attr('\n', 0);
 	cursor_on();
 	verbose_leave();
     }
diff --git a/src/testdir/dumps/Test_verbose_system_1.dump b/src/testdir/dumps/Test_verbose_system_1.dump
new file mode 100644
index 0000000..6723b54
--- /dev/null
+++ b/src/testdir/dumps/Test_verbose_system_1.dump
@@ -0,0 +1,10 @@
+|C+0&#ffffff0|a|l@1|i|n|g| |s|h|e|l@1| |t|o| |e|x|e|c|u|t|e|:| |"|(|s|e|q| |2|0|)|>|/|t|m|p|/|v|W|4|d|k|0|a|/|0| |2|>|&|1|"| @18
+|1| @73
+|2| @73
+|3| @73
+|4| @73
+|5| @73
+|6| @73
+|7| @73
+|8| @73
+|-+0#00e0003&@1| |M|o|r|e| |-@1> +0#0000000&@64
diff --git a/src/testdir/dumps/Test_verbose_system_1.vim b/src/testdir/dumps/Test_verbose_system_1.vim
new file mode 100644
index 0000000..816a55a
--- /dev/null
+++ b/src/testdir/dumps/Test_verbose_system_1.vim
@@ -0,0 +1,3 @@
+" Filter that removes the ever changing temp directory name from the screendump
+" that shows the system() command executed.
+1s+|t|m|p|/|.|.|.*| |+|t|m|p|/|x|x|x|x|x|x|x|/|1| |+
diff --git a/src/testdir/dumps/Test_verbose_system_2.dump b/src/testdir/dumps/Test_verbose_system_2.dump
new file mode 100644
index 0000000..ed65719
--- /dev/null
+++ b/src/testdir/dumps/Test_verbose_system_2.dump
@@ -0,0 +1,10 @@
+|C+0&#ffffff0|a|l@1|i|n|g| |s|h|e|l@1| |t|o| |e|x|e|c|u|t|e|:| |"|(|s|e|q| |2|0|)|>|/|t|m|p|/|v|V|v|w|c|g|V|/|1| |2|>|&|1|"| @18
+|1| @73
+|2| @73
+|3| @73
+|4| @73
+|5| @73
+|6| @73
+|7| @73
+|8| @73
+|-+0#00e0003&@1| |M|o|r|e| |-@1> +0#0000000&@64
diff --git a/src/testdir/dumps/Test_verbose_system_2.vim b/src/testdir/dumps/Test_verbose_system_2.vim
new file mode 100644
index 0000000..816a55a
--- /dev/null
+++ b/src/testdir/dumps/Test_verbose_system_2.vim
@@ -0,0 +1,3 @@
+" Filter that removes the ever changing temp directory name from the screendump
+" that shows the system() command executed.
+1s+|t|m|p|/|.|.|.*| |+|t|m|p|/|x|x|x|x|x|x|x|/|1| |+
diff --git a/src/testdir/screendump.vim b/src/testdir/screendump.vim
index e19d4f5..a2a54f4 100644
--- a/src/testdir/screendump.vim
+++ b/src/testdir/screendump.vim
@@ -13,16 +13,43 @@
   finish
 endif
 
+" Read a dump file "fname" and if "filter" exists apply it to the text.
+def ReadAndFilter(fname: string, filter: string): list<string>
+  var contents = readfile(fname)
+
+  if filereadable(filter)
+    # do this in the bottom window so that the terminal window is unaffected
+    wincmd j
+    enew
+    setline(1, contents)
+    exe "source " .. filter
+    contents = getline(1, '$')
+    enew!
+    wincmd k
+    redraw
+  endif
+
+  return contents
+enddef
+
+
 " Verify that Vim running in terminal buffer "buf" matches the screen dump.
 " "options" is passed to term_dumpwrite().
 " Additionally, the "wait" entry can specify the maximum time to wait for the
 " screen dump to match in msec (default 1000 msec).
 " The file name used is "dumps/{filename}.dump".
+"
+" To ignore part of the dump, provide a "dumps/{filename}.vim" file with
+" Vim commands to be applied to both the reference and the current dump, so
+" that parts that are irrelevant are not used for the comparison.  The result
+" is NOT written, thus "term_dumpdiff()" shows the difference anyway.
+"
 " Optionally an extra argument can be passed which is prepended to the error
 " message.  Use this when using the same dump file with different options.
 " Returns non-zero when verification fails.
 func VerifyScreenDump(buf, filename, options, ...)
   let reference = 'dumps/' . a:filename . '.dump'
+  let filter = 'dumps/' . a:filename . '.vim'
   let testfile = 'failed/' . a:filename . '.dump'
 
   let max_loops = get(a:options, 'wait', 1000) / 10
@@ -37,6 +64,13 @@
   " text and attributes only from the internal buffer.
   redraw
 
+  if filereadable(reference)
+    let refdump = ReadAndFilter(reference, filter)
+  else
+    " Must be a new screendump, always fail
+    let refdump = []
+  endif
+
   let did_mkdir = 0
   if !isdirectory('failed')
     let did_mkdir = 1
@@ -49,13 +83,7 @@
     sleep 10m
     call delete(testfile)
     call term_dumpwrite(a:buf, testfile, a:options)
-    let testdump = readfile(testfile)
-    if filereadable(reference)
-      let refdump = readfile(reference)
-    else
-      " Must be a new screendump, always fail
-      let refdump = []
-    endif
+    let testdump = ReadAndFilter(testfile, filter)
     if refdump == testdump
       call delete(testfile)
       if did_mkdir
diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim
index c69d0a9..486adcb 100644
--- a/src/testdir/test_messages.vim
+++ b/src/testdir/test_messages.vim
@@ -336,6 +336,40 @@
   call StopVimInTerminal(buf)
 endfunc
 
+" Test verbose message before echo command
+func Test_echo_verbose_system()
+  CheckRunVimInTerminal
+  CheckUnix
+
+  let buf = RunVimInTerminal('', {'rows': 10})
+  call term_sendkeys(buf, ":4 verbose echo system('seq 20')\<CR>")
+  " Note that the screendump is filtered to remove the name of the temp file
+  call VerifyScreenDump(buf, 'Test_verbose_system_1', {})
+
+  " display a page and go back, results in exactly the same view
+  call term_sendkeys(buf, ' ')
+  call TermWait(buf)
+  call term_sendkeys(buf, 'b')
+  call VerifyScreenDump(buf, 'Test_verbose_system_1', {})
+
+  " do the same with 'cmdheight' set to 2
+  call term_sendkeys(buf, 'q')
+  call TermWait(buf)
+  call term_sendkeys(buf, ":set ch=2\<CR>")
+  call TermWait(buf)
+  call term_sendkeys(buf, ":4 verbose echo system('seq 20')\<CR>")
+  call VerifyScreenDump(buf, 'Test_verbose_system_2', {})
+
+  call term_sendkeys(buf, ' ')
+  call TermWait(buf)
+  call term_sendkeys(buf, 'b')
+  call VerifyScreenDump(buf, 'Test_verbose_system_2', {})
+
+  call term_sendkeys(buf, 'q')
+  call TermWait(buf)
+  call StopVimInTerminal(buf)
+endfunc
+
 
 func Test_ask_yesno()
   CheckRunVimInTerminal
diff --git a/src/version.c b/src/version.c
index 6b05454..35f37e9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    595,
+/**/
     594,
 /**/
     593,