[PATCH] Strange behavior of cmd.exe when hammered with clear screen operations from Cygwin program.

Corinna Vinschen corinna-cygwin@cygwin.com
Wed Jul 27 18:45:00 GMT 2016


Hi Kaz,

On Jul 27 08:40, Kaz Kylheku wrote:
> On 27.07.2016 07:35, Kaz Kylheku wrote:
> > On 27.07.2016 07:31, Kaz Kylheku wrote:
> > > The patch below seems to solves it for me:
> > 
> > Oops, no it doesn't. Stay tuned. :)
> 
> This is a bit more like it:
> 
> From: Kaz Kylheku <kaz@kylheku.com>
> Date: Wed, 27 Jul 2016 07:49:54 -0700
> Subject: Replace bogus resize-window-to-clear-screen logic.
> 
> This removes (ab)uses of SetConsoleScreenBufferSize
> which sometimes cause cmd.exe to badly misbehave.
> It probably doesn't like the closely spaced timing of
> shrinking the window down to one line followed by a restore
> of the size. Instead we just output newlines to clear
> the window.

The problem is obvious when observing your test application (thanks a
lot for that), but I'm not convinced that just calling WriteConsole with
a single LF in a loop is the way to go.  The Windows console API has
more nifty ways to fix this problem.

Here's another suggestion.  I attached a patch which utilizes
ScrollConsoleScreenBuffer to save the buffer content when the console
window is at the end of the console buffer.  So we either move the
console window down the buffer if there's enough buffer left, or we move
the buffer up under the window if we're operating at the end of the
buffer.

Please give it a try and report back.  Especially if I screwed up :}

Btw, since you're apparently building your own Cygwin DLL I thought just
sending the patch for testing is sufficient.  If you prefer to get a
developer snapshot with this patch, I can do that, too.  Just say the word.


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
From f9dd1288180b5d88b2915337aa58462811de3168 Mon Sep 17 00:00:00 2001
From: Corinna Vinschen <corinna@vinschen.de>
Date: Wed, 27 Jul 2016 20:39:24 +0200
Subject: [PATCH] Fix buffer scrolling when performing a "clear screen"

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
---
 winsup/cygwin/fhandler_console.cc | 54 +++++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index d4c077b..9c490c5 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -1216,30 +1216,46 @@ dev_console::scroll_window (HANDLE h, int x1, int y1, int x2, int y2)
     return false;
 
   SMALL_RECT sr;
-  int toscroll = 2 + dwEnd.Y - b.srWindow.Top;
-  int shrink = 1 + toscroll + b.srWindow.Bottom - b.dwSize.Y;
+  int toscroll = dwEnd.Y - b.srWindow.Top + 1;
   sr.Left = sr.Right = dwEnd.X = 0;
-  /* Can't increment dwEnd yet since we may not have space in
-     the buffer.  */
-  SetConsoleCursorPosition (h, dwEnd);
-  if (shrink > 0)
+
+  if (b.srWindow.Bottom + toscroll >= b.dwSize.Y)
     {
-      COORD c = b.dwSize;
-      c.Y = dwEnd.Y - shrink;
-      SetConsoleScreenBufferSize (h, c);
-      SetConsoleScreenBufferSize (h, b.dwSize);
-      dwEnd.Y = 0;
-      fillin (h);
-      toscroll = 2 + dwEnd.Y - b.srWindow.Top;
+      /* So we're at the end of the buffer and scrolling the console window
+	 would move us beyond the buffer.  What we do here is to scroll the
+	 console buffer upward by just as much so that the current last line
+	 becomes the last line just prior to the first window line.  That
+	 keeps the end of the console buffer intact, as desired.
+
+	 Since we're moving the console buffer under the console window in
+	 this case, we must not move the console window. */
+      SMALL_RECT br;
+      COORD dest;
+      CHAR_INFO fill;
+
+      br.Left = 0;
+      br.Top = dwEnd.Y - b.srWindow.Top + 1;
+      br.Right = b.dwSize.X - 1;
+      br.Bottom = b.dwSize.Y - 1;
+      dest.X = dest.Y = 0;
+      fill.Char.AsciiChar = ' ';
+      fill.Attributes = current_win32_attr;
+      ScrollConsoleScreenBuffer (h, &br, NULL, dest, &fill);
+      /* Fix dwEnd to reflect the new cursor line (minus 1 to take the
+	 increment a few lines later into account) */
+      dwEnd.Y = b.dwCursorPosition.Y - 1;
     }
-
-  sr.Top = sr.Bottom = toscroll;
-
-  SetConsoleWindowInfo (h, FALSE, &sr);
-
+  else
+    {
+      /* The reminder of the console buffer is big enough to simply move
+         the console window. */
+      sr.Top = sr.Bottom = toscroll;
+      SetConsoleWindowInfo (h, FALSE, &sr);
+    }
+  /* Eventually set cursor to new end position at the top of the window. */
   dwEnd.Y++;
   SetConsoleCursorPosition (h, dwEnd);
-
+  /* Fix up console buffer info. */
   fillin (h);
   return true;
 }
-- 
2.5.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20160727/a2052833/attachment.sig>


More information about the Cygwin mailing list