summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-07-27 07:49:54 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-26 21:52:26 -0700
commit8288dcb545ecb6fa5034788c6918241bfe067ff4 (patch)
tree15cdf8bc9bc5203e54086f70125181769bf8abde
parentef259ef3fab9605fef316797cda3ff1a12c7d88d (diff)
downloadcygnal-8288dcb545ecb6fa5034788c6918241bfe067ff4.tar.gz
cygnal-8288dcb545ecb6fa5034788c6918241bfe067ff4.tar.bz2
cygnal-8288dcb545ecb6fa5034788c6918241bfe067ff4.zip
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. * winsup/cygwin/fhandler.h (dev_console::scroll_window): Member function declaration removed. (dev_console::clear_should_scroll): New member function declared. * winsup/cygwin/fhandler_console.cc (dev_console::scroll_window): Member function removed. (dev_console::clear_should_scroll): New member function. Performs only the test that was performed by scroll_window, not the actual scrolling. The scrolling is now done in the caller in the fhandler_console class. (fhandler_console::clear_screen): Call con.clear_should_scroll instead of con.scroll_window. If this returns false, act as before. Otherwise, clear the screen by scrolling the window. This is done not by making SetConsoleScreenBufferSize calls to shrink and restore the window, but by earnestly emitting a number of carriage returns equal to the vertical screen size and then restoring the cursor position.
-rw-r--r--winsup/cygwin/fhandler.h2
-rw-r--r--winsup/cygwin/fhandler_console.cc77
2 files changed, 23 insertions, 56 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 53798d047..3bbf471b8 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2077,7 +2077,7 @@ class dev_console
int set_cl_x (cltype);
int set_cl_y (cltype);
bool fillin (HANDLE);
- bool __reg3 scroll_window (HANDLE, int, int, int, int);
+ bool __reg3 clear_should_scroll (HANDLE, int, int, int, int);
void __reg3 scroll_buffer (HANDLE, int, int, int, int, int, int);
void __reg3 clear_screen (HANDLE, int, int, int, int);
void __reg3 save_restore (HANDLE, char);
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index d3611eaaa..94c4b9fcf 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -1667,63 +1667,11 @@ dev_console::set_cl_y (cltype y)
}
bool
-dev_console::scroll_window (HANDLE h, int x1, int y1, int x2, int y2)
+dev_console::clear_should_scroll (HANDLE h, int x1, int y1, int x2, int y2)
{
if (save_buf || x1 != 0 || x2 != dwWinSize.X - 1 || y1 != b.srWindow.Top
|| y2 != b.srWindow.Bottom || b.dwSize.Y <= dwWinSize.Y)
return false;
-
- SMALL_RECT sr;
- int toscroll = dwEnd.Y - b.srWindow.Top + 1;
- sr.Left = sr.Right = dwEnd.X = 0;
-
- if (b.srWindow.Bottom + toscroll >= b.dwSize.Y)
- {
- /* 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.UnicodeChar = L' ';
- 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;
- }
- else
- {
- /* The reminder of the console buffer is big enough to simply move
- the console window. We have to set the cursor first, otherwise
- the scroll bars will not be corrected. */
- SetConsoleCursorPosition (h, dwEnd);
- /* If we scroll backwards, setting the cursor position will scroll
- the console window up so that the cursor is at the bottom. Correct
- the action by moving the window down again so the cursor is one line
- above the new window position. */
- if (toscroll < 0)
- toscroll = b.srWindow.Bottom - b.srWindow.Top;
- /* Move the window accordingly. */
- 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;
}
@@ -1755,8 +1703,27 @@ fhandler_console::clear_screen (cltype xc1, cltype yc1, cltype xc2, cltype yc2)
/* Detect special case - scroll the screen if we have a buffer in order to
preserve the buffer. */
- if (!con.scroll_window (h, x1, y1, x2, y2))
- con.clear_screen (h, x1, y1, x2, y2);
+ if (!con.clear_should_scroll (h, x1, y1, x2, y2))
+ {
+ con.clear_screen (h, x1, y1, x2, y2);
+ return;
+ }
+
+ int xpos, ypos;
+ DWORD done;
+ cursor_get(&xpos, &ypos);
+ cursor_set(false, 0, con.b.dwSize.Y - 1);
+
+ for (int i = 0; i < con.dwWinSize.Y; i += done)
+ {
+ if (!WriteConsoleW (h, L"\n", 1, &done, 0))
+ {
+ __seterrno ();
+ break;
+ }
+ }
+
+ cursor_set(false, xpos, ypos);
}
void __reg3