diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b5b4cec9f..7cef30e13 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,30 @@ +2014-02-15 Christopher Faylor + + * DevNotes: Add entry cgf-000024. + * fhandler.h (dev_console::state): Remove trailing underscore. + (dev_console::args): Ditto. + (dev_console::nargs): Ditto. + (dev_console::info): Eliminate subclass. + (dev_console::dwEnd): New field. + (dev_console::scroll_window): New function. + (dev_console::is_fullscreen): Ditto. + (dev_console::fillin): Rename from fillin_info. + (fhandler_console::scroll_buffer): Rename from scroll_screen. + * fhandler_console.cc: Throughout s/dev_state\.info/dev_state/g. + Accommodate other name changes. + (dev_console::fillin): Accommodate rename. Notice max x/y written to. + Forgo memset if GetConsoleScreenBufferInfo fails. + (fhandler_console::scroll_buffer): Accommodate rename. Don't treat y + coordinate of zero as top of screen. + (dev_console::is_fullscreen): New function. + (dev_console::scroll_window): Ditto. + (fhandler_console::clear_screen): Just scroll the screen when clearing + the screen in a state where the screen buffer is bigger than the + screen. + (fhandler_console::char_command): Try harder to get 'S' and 'T' working + in the presence of a screen buffer. Use temporary 'n' variable rather + than dev_state.args[0]. Use GNU ?: shortcut method. + 2014-02-14 Christopher Faylor * pinfo.cc (winpids::add): Always copy pinfo structure when winpid. diff --git a/winsup/cygwin/DevNotes b/winsup/cygwin/DevNotes index 3016075ec..b8820a96b 100644 --- a/winsup/cygwin/DevNotes +++ b/winsup/cygwin/DevNotes @@ -1,3 +1,11 @@ +2014-02-15 cgf-000024 + +Wow. It's hard getting the screen handling stuff working correctly when +there is a screen buffer larger than screen size and vice versa. These +changes attempt to use SetConsoleWindowInfo whenever possible so that +the contents of the screen buffer are never wiped out. They also fix +some previously misbehaving "scroll the screen" commands. + 2013-06-07 cgf-000023 Given the fact that the signal thread never exits there is no need diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index aa3c351c4..ad916b963 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1263,9 +1263,9 @@ class dev_console int meta_mask; /* Output state */ - int state_; - int args_[MAXARGS]; - int nargs_; + int state; + int args[MAXARGS]; + int nargs; unsigned rarg; bool saw_question_mark; bool saw_greater_than_sign; @@ -1295,17 +1295,14 @@ class dev_console { short Top, Bottom; } scroll_region; - struct console_attrs - { - SHORT winTop; - SHORT winBottom; - COORD dwWinSize; - COORD dwBufferSize; - COORD dwCursorPosition; - WORD wAttributes; - int set_cl_x (cltype); - int set_cl_y (cltype); - } info; + + SHORT winTop; + SHORT winBottom; + COORD dwWinSize; + COORD dwBufferSize; + COORD dwCursorPosition; + WORD wAttributes; + COORD dwEnd; COORD dwLastCursorPosition; COORD dwMousePosition; /* scroll-adjusted coord of mouse event */ @@ -1326,8 +1323,12 @@ class dev_console DWORD con_to_str (char *d, int dlen, WCHAR w); DWORD str_to_con (mbtowc_p, const char *, PWCHAR d, const char *s, DWORD sz); void set_color (HANDLE); - bool fillin_info (HANDLE); void set_default_attr (); + int set_cl_x (cltype); + int set_cl_y (cltype); + bool fillin (HANDLE); + bool is_fullscreen (int, int, int, int); + void scroll_window (HANDLE); friend class fhandler_console; }; @@ -1358,7 +1359,7 @@ private: void set_default_attr (); void clear_screen (cltype, cltype, cltype, cltype); - void scroll_screen (int, int, int, int, int, int); + void scroll_buffer (int, int, int, int, int, int); void cursor_set (bool, int, int); void cursor_get (int *, int *); void cursor_rel (int, int); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index caaf5eae2..4718fdf5f 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -43,8 +43,8 @@ details. */ #define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) #define dev_state (shared_console_info->dev_state) -#define srTop (dev_state.info.winTop + dev_state.scroll_region.Top) -#define srBottom ((dev_state.scroll_region.Bottom < 0) ? dev_state.info.winBottom : dev_state.info.winTop + dev_state.scroll_region.Bottom) +#define srTop (dev_state.winTop + dev_state.scroll_region.Top) +#define srBottom ((dev_state.scroll_region.Bottom < 0) ? dev_state.winBottom : dev_state.winTop + dev_state.scroll_region.Bottom) const char *get_nonascii_key (INPUT_RECORD&, char *); @@ -172,7 +172,6 @@ fhandler_console::setup () { if (set_unit ()) { - dev_state.scroll_region.Bottom = -1; dev_state.dwLastCursorPosition.X = -1; dev_state.dwLastCursorPosition.Y = -1; @@ -264,11 +263,11 @@ fhandler_console::set_cursor_maybe () void fhandler_console::send_winch_maybe () { - SHORT y = dev_state.info.dwWinSize.Y; - SHORT x = dev_state.info.dwWinSize.X; - dev_state.fillin_info (get_output_handle ()); + SHORT y = dev_state.dwWinSize.Y; + SHORT x = dev_state.dwWinSize.X; + dev_state.fillin (get_output_handle ()); - if (y != dev_state.info.dwWinSize.Y || x != dev_state.info.dwWinSize.X) + if (y != dev_state.dwWinSize.Y || x != dev_state.dwWinSize.X) { dev_state.scroll_region.Top = 0; dev_state.scroll_region.Bottom = -1; @@ -734,27 +733,31 @@ fhandler_console::set_input_state () } bool -dev_console::fillin_info (HANDLE h) +dev_console::fillin (HANDLE h) { bool ret; CONSOLE_SCREEN_BUFFER_INFO linfo; if ((ret = GetConsoleScreenBufferInfo (h, &linfo))) { - info.winTop = linfo.srWindow.Top; - info.winBottom = linfo.srWindow.Bottom; - info.dwWinSize.Y = 1 + linfo.srWindow.Bottom - linfo.srWindow.Top; - info.dwWinSize.X = 1 + linfo.srWindow.Right - linfo.srWindow.Left; - info.dwBufferSize = linfo.dwSize; - info.dwCursorPosition = linfo.dwCursorPosition; - info.wAttributes = linfo.wAttributes; + winTop = linfo.srWindow.Top; + winBottom = linfo.srWindow.Bottom; + dwWinSize.Y = 1 + linfo.srWindow.Bottom - linfo.srWindow.Top; + dwWinSize.X = 1 + linfo.srWindow.Right - linfo.srWindow.Left; + if (dwBufferSize.Y != linfo.dwSize.Y || dwBufferSize.X != linfo.dwSize.X) + dwEnd.X = dwEnd.Y = 0; + dwBufferSize = linfo.dwSize; + dwCursorPosition = linfo.dwCursorPosition; + if (dwCursorPosition.Y > dwEnd.Y + || (dwCursorPosition.Y >= dwEnd.Y && dwCursorPosition.X > dwEnd.X)) + dwEnd = dwCursorPosition; + wAttributes = linfo.wAttributes; } else { - memset (&info, 0, sizeof info); - info.dwWinSize.Y = 25; - info.dwWinSize.X = 80; - info.winBottom = 24; + dwWinSize.Y = 25; + dwWinSize.X = 80; + winBottom = 24; } return ret; @@ -767,37 +770,28 @@ dev_console::fillin_info (HANDLE h) Negative values represents current screen dimensions */ void -fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn) +fhandler_console::scroll_buffer (int x1, int y1, int x2, int y2, int xn, int yn) { SMALL_RECT sr1, sr2; CHAR_INFO fill; COORD dest; + fill.Char.AsciiChar = ' '; + fill.Attributes = dev_state.current_win32_attr; - dev_state.fillin_info (get_output_handle ()); - sr1.Left = x1 >= 0 ? x1 : dev_state.info.dwWinSize.X - 1; - if (y1 == 0) - sr1.Top = dev_state.info.winTop; - else - sr1.Top = y1 > 0 ? y1 : dev_state.info.winBottom; - sr1.Right = x2 >= 0 ? x2 : dev_state.info.dwWinSize.X - 1; - if (y2 == 0) - sr1.Bottom = dev_state.info.winTop; - else - sr1.Bottom = y2 > 0 ? y2 : dev_state.info.winBottom; + dev_state.fillin (get_output_handle ()); + sr1.Left = x1 >= 0 ? x1 : dev_state.dwWinSize.X - 1; + sr1.Top = y1 >= 0 ? y1 : dev_state.winBottom; + sr1.Right = x2 >= 0 ? x2 : dev_state.dwWinSize.X - 1; + sr1.Bottom = y2 >= 0 ? y2 : dev_state.winBottom; sr2.Top = srTop; sr2.Left = 0; sr2.Bottom = srBottom; - sr2.Right = dev_state.info.dwWinSize.X - 1; + sr2.Right = dev_state.dwWinSize.X - 1; if (sr1.Bottom > sr2.Bottom && sr1.Top <= sr2.Bottom) sr1.Bottom = sr2.Bottom; - dest.X = xn >= 0 ? xn : dev_state.info.dwWinSize.X - 1; - if (yn == 0) - dest.Y = dev_state.info.winTop; - else - dest.Y = yn > 0 ? yn : dev_state.info.winBottom; - fill.Char.AsciiChar = ' '; - fill.Attributes = dev_state.current_win32_attr; - ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, dest, &fill); + dest.X = xn >= 0 ? xn : dev_state.dwWinSize.X - 1; + dest.Y = yn >= 0 ? yn : dev_state.winBottom; + ScrollConsoleScreenBuffer (get_output_handle (), &sr1, NULL, dest, &fill); #if 0 /* CGF: 2014-01-04 Assuming that we don't need this anymore */ /* ScrollConsoleScreenBuffer on Windows 95 is buggy - when scroll distance @@ -860,11 +854,11 @@ fhandler_console::open (int flags, mode_t) } set_output_handle (h); - if (dev_state.fillin_info (get_output_handle ())) + if (dev_state.fillin (get_output_handle ())) { - dev_state.current_win32_attr = dev_state.info.wAttributes; + dev_state.current_win32_attr = dev_state.wAttributes; if (!dev_state.default_color) - dev_state.default_color = dev_state.info.wAttributes; + dev_state.default_color = dev_state.wAttributes; dev_state.set_default_attr (); } @@ -912,13 +906,13 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) case TIOCGWINSZ: int st; - st = dev_state.fillin_info (get_output_handle ()); + st = dev_state.fillin (get_output_handle ()); if (st) { /* *not* the buffer size, the actual screen size... */ /* based on Left Top Right Bottom of srWindow */ - ((struct winsize *) arg)->ws_row = dev_state.info.dwWinSize.Y; - ((struct winsize *) arg)->ws_col = dev_state.info.dwWinSize.X; + ((struct winsize *) arg)->ws_row = dev_state.dwWinSize.Y; + ((struct winsize *) arg)->ws_col = dev_state.dwWinSize.X; syscall_printf ("WINSZ: (row=%d,col=%d)", ((struct winsize *) arg)->ws_row, ((struct winsize *) arg)->ws_col); @@ -1189,7 +1183,7 @@ dev_console::set_default_attr () } int -dev_console::console_attrs::set_cl_x (cltype x) +dev_console::set_cl_x (cltype x) { if (x == cl_disp_beg || x == cl_buf_beg) return 0; @@ -1201,7 +1195,7 @@ dev_console::console_attrs::set_cl_x (cltype x) } int -dev_console::console_attrs::set_cl_y (cltype y) +dev_console::set_cl_y (cltype y) { if (y == cl_buf_beg) return 0; @@ -1213,7 +1207,26 @@ dev_console::console_attrs::set_cl_y (cltype y) return dwBufferSize.Y - 1; return dwCursorPosition.Y; } - + +bool +dev_console::is_fullscreen (int x1, int y1, int x2, int y2) +{ + return !savebuf + && x1 == 0 && x2 == dwWinSize.X - 1 && y1 == winTop && y2 == winBottom + && dwBufferSize.Y > dwWinSize.Y; +} + +void +dev_console::scroll_window (HANDLE h) +{ + SMALL_RECT sr; + sr.Top = sr.Bottom = 1 + dwEnd.Y - winTop; + sr.Left = sr.Right = 0; + SetConsoleWindowInfo (h, FALSE, &sr); + dwEnd.X = 0; + SetConsoleCursorPosition (h, dwEnd); +} + /* * Clear the screen context from x1/y1 to x2/y2 cell. * Negative values represents current screen dimensions @@ -1225,16 +1238,24 @@ fhandler_console::clear_screen (cltype xc1, cltype yc1, cltype xc2, cltype yc2) DWORD done; int num; - dev_state.fillin_info (get_output_handle ()); + dev_state.fillin (get_output_handle ()); - int x1 = dev_state.info.set_cl_x (xc1); - int y1 = dev_state.info.set_cl_y (yc1); - int x2 = dev_state.info.set_cl_x (xc2); - int y2 = dev_state.info.set_cl_y (yc2); + int x1 = dev_state.set_cl_x (xc1); + int y1 = dev_state.set_cl_y (yc1); + int x2 = dev_state.set_cl_x (xc2); + int y2 = dev_state.set_cl_y (yc2); - num = abs (y1 - y2) * dev_state.info.dwBufferSize.X + abs (x1 - x2) + 1; + /* Detect special case - scroll the screen if we have a buffer to + preserve the buffer. */ + if (dev_state.is_fullscreen (x1, y1, x2, y2)) + { + dev_state.scroll_window (get_output_handle ()); + return; + } - if ((y2 * dev_state.info.dwBufferSize.X + x2) > (y1 * dev_state.info.dwBufferSize.X + x1)) + num = abs (y1 - y2) * dev_state.dwBufferSize.X + abs (x1 - x2) + 1; + + if ((y2 * dev_state.dwBufferSize.X + x2) > (y1 * dev_state.dwBufferSize.X + x1)) { tlc.X = x1; tlc.Y = y1; @@ -1260,7 +1281,7 @@ fhandler_console::cursor_set (bool rel_to_top, int x, int y) { COORD pos; - dev_state.fillin_info (get_output_handle ()); + dev_state.fillin (get_output_handle ()); #if 0 /* Setting y to the current winBottom here is the reason that the window isn't scrolled back to the current cursor position like it's done in @@ -1269,17 +1290,17 @@ fhandler_console::cursor_set (bool rel_to_top, int x, int y) output is generated while the user had the window scrolled back. This behaviour is very old, it has no matching ChangeLog entry. Just disable for now but keep the code in for future reference. */ - if (y > dev_state.info.winBottom) - y = dev_state.info.winBottom; + if (y > dev_state.winBottom) + y = dev_state.winBottom; else #endif if (y < 0) y = 0; else if (rel_to_top) - y += dev_state.info.winTop; + y += dev_state.winTop; - if (x > dev_state.info.dwWinSize.X) - x = dev_state.info.dwWinSize.X - 1; + if (x > dev_state.dwWinSize.X) + x = dev_state.dwWinSize.X - 1; else if (x < 0) x = 0; @@ -1291,18 +1312,18 @@ fhandler_console::cursor_set (bool rel_to_top, int x, int y) void fhandler_console::cursor_rel (int x, int y) { - dev_state.fillin_info (get_output_handle ()); - x += dev_state.info.dwCursorPosition.X; - y += dev_state.info.dwCursorPosition.Y; + dev_state.fillin (get_output_handle ()); + x += dev_state.dwCursorPosition.X; + y += dev_state.dwCursorPosition.Y; cursor_set (false, x, y); } void fhandler_console::cursor_get (int *x, int *y) { - dev_state.fillin_info (get_output_handle ()); - *y = dev_state.info.dwCursorPosition.Y; - *x = dev_state.info.dwCursorPosition.X; + dev_state.fillin (get_output_handle ()); + *y = dev_state.dwCursorPosition.Y; + *x = dev_state.dwCursorPosition.X; } /* VT100 line drawing graphics mode maps `abcdefghijklmnopqrstuvwxyz{|}~ to @@ -1474,14 +1495,14 @@ static const char base_chars[256] = void fhandler_console::char_command (char c) { - int x, y; + int x, y, n; char buf[40]; switch (c) { case 'm': /* Set Graphics Rendition */ - for (int i = 0; i <= dev_state.nargs_; i++) - switch (dev_state.args_[i]) + for (int i = 0; i <= dev_state.nargs; i++) + switch (dev_state.args[i]) { case 0: /* normal color */ dev_state.set_default_attr (); @@ -1585,7 +1606,7 @@ fhandler_console::char_command (char c) { CONSOLE_CURSOR_INFO console_cursor_info; GetConsoleCursorInfo (get_output_handle (), & console_cursor_info); - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 0: /* blinking block */ case 1: /* blinking block (default) */ @@ -1599,7 +1620,7 @@ fhandler_console::char_command (char c) SetConsoleCursorInfo (get_output_handle (), & console_cursor_info); break; default: /* use value as percentage */ - console_cursor_info.dwSize = dev_state.args_[0]; + console_cursor_info.dwSize = dev_state.args[0]; SetConsoleCursorInfo (get_output_handle (), & console_cursor_info); break; } @@ -1609,7 +1630,7 @@ fhandler_console::char_command (char c) case 'l': if (!dev_state.saw_question_mark) { - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 4: /* Insert mode */ dev_state.insert_mode = (c == 'h') ? true : false; @@ -1618,7 +1639,7 @@ fhandler_console::char_command (char c) } break; } - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 25: /* Show/Hide Cursor (DECTCEM) */ { @@ -1717,23 +1738,23 @@ fhandler_console::char_command (char c) break; default: /* Ignore */ - syscall_printf ("unknown h/l command: %d", dev_state.args_[0]); + syscall_printf ("unknown h/l command: %d", dev_state.args[0]); break; } break; case 'J': - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 0: /* Clear to end of screen */ clear_screen (cl_curr_pos, cl_curr_pos, cl_disp_end, cl_disp_end); break; case 1: /* Clear from beginning of screen to cursor */ - cursor_get (&x, &y); clear_screen (cl_disp_beg, cl_disp_beg, cl_curr_pos, cl_curr_pos); break; case 2: /* Clear screen */ + cursor_get (&x, &y); clear_screen (cl_disp_beg, cl_disp_beg, cl_disp_end, cl_disp_end); - cursor_set (true, 0, 0); + cursor_set (false, x, y); break; default: goto bad_escape; @@ -1741,19 +1762,19 @@ fhandler_console::char_command (char c) break; case 'A': - cursor_rel (0, -(dev_state.args_[0] ? dev_state.args_[0] : 1)); + cursor_rel (0, -(dev_state.args[0] ?: 1)); break; case 'B': - cursor_rel (0, dev_state.args_[0] ? dev_state.args_[0] : 1); + cursor_rel (0, dev_state.args[0] ?: 1); break; case 'C': - cursor_rel (dev_state.args_[0] ? dev_state.args_[0] : 1, 0); + cursor_rel (dev_state.args[0] ?: 1, 0); break; case 'D': - cursor_rel (-(dev_state.args_[0] ? dev_state.args_[0] : 1),0); + cursor_rel (-(dev_state.args[0] ?: 1),0); break; case 'K': - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 0: /* Clear to end of line */ clear_screen (cl_curr_pos, cl_curr_pos, cl_disp_end, cl_curr_pos); @@ -1770,20 +1791,20 @@ fhandler_console::char_command (char c) break; case 'H': case 'f': - cursor_set (true, (dev_state.args_[1] ? dev_state.args_[1] : 1) - 1, - (dev_state.args_[0] ? dev_state.args_[0] : 1) - 1); + cursor_set (true, (dev_state.args[1] ?: 1) - 1, + (dev_state.args[0] ?: 1) - 1); break; case 'G': /* hpa - position cursor at column n - 1 */ cursor_get (&x, &y); - cursor_set (false, (dev_state.args_[0] ? dev_state.args_[0] - 1 : 0), y); + cursor_set (false, (dev_state.args[0] ? dev_state.args[0] - 1 : 0), y); break; case 'd': /* vpa - position cursor at line n */ cursor_get (&x, &y); - cursor_set (true, x, (dev_state.args_[0] ? dev_state.args_[0] - 1 : 0)); + cursor_set (true, x, (dev_state.args[0] ? dev_state.args[0] - 1 : 0)); break; case 's': /* Save cursor position */ cursor_get (&dev_state.savex, &dev_state.savey); - dev_state.savey -= dev_state.info.winTop; + dev_state.savey -= dev_state.winTop; break; case 'u': /* Restore cursor position */ cursor_set (true, dev_state.savex, dev_state.savey); @@ -1793,39 +1814,39 @@ fhandler_console::char_command (char c) cursor_set (false, 8 * (x / 8 + 1), y); break; case 'L': /* AL - insert blank lines */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; + n = dev_state.args[0] ?: 1; cursor_get (&x, &y); - scroll_screen (0, y, -1, -1, 0, y + dev_state.args_[0]); + scroll_buffer (0, y, -1, -1, 0, y + n); break; case 'M': /* DL - delete lines */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; + n = dev_state.args[0] ?: 1; cursor_get (&x, &y); - scroll_screen (0, y + dev_state.args_[0], -1, -1, 0, y); + scroll_buffer (0, y + dev_state.args[0], -1, -1, 0, y); break; case '@': /* IC - insert chars */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; + n = dev_state.args[0] ?: 1; cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + dev_state.args_[0], y); + scroll_buffer (x, y, -1, y, x + n, y); break; case 'P': /* DC - delete chars */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; + n = dev_state.args[0] ?: 1; cursor_get (&x, &y); - scroll_screen (x + dev_state.args_[0], y, -1, y, x, y); + scroll_buffer (x + n, y, -1, y, x, y); break; case 'S': /* SF - Scroll forward */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; - scroll_screen (0, dev_state.args_[0], -1, -1, 0, 0); + n = dev_state.args[0] ?: 1; + scroll_buffer (0, n, -1, -1, 0, 0); break; case 'T': /* SR - Scroll down */ - dev_state.fillin_info (get_output_handle ()); - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; - scroll_screen (0, 0, -1, -1, 0, dev_state.info.winTop + dev_state.args_[0]); + dev_state.fillin (get_output_handle ()); + n = dev_state.winTop + dev_state.args[0] ?: 1; + scroll_buffer (0, dev_state.winTop, -1, -1, 0, n); break; case 'X': /* ec - erase chars */ - dev_state.args_[0] = dev_state.args_[0] ? dev_state.args_[0] : 1; + n = dev_state.args[0] ?: 1; cursor_get (&x, &y); - scroll_screen (x + dev_state.args_[0], y, -1, y, x, y); - scroll_screen (x, y, -1, y, x + dev_state.args_[0], y); + scroll_buffer (x + n, y, -1, y, x, y); + scroll_buffer (x, y, -1, y, x + n, y); break; case 'Z': /* Back tab */ cursor_get (&x, &y); @@ -1835,10 +1856,10 @@ fhandler_console::char_command (char c) if (dev_state.insert_mode) { cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + dev_state.args_[1], y); + scroll_buffer (x, y, -1, y, x + dev_state.args[1], y); } - while (dev_state.args_[1]--) - WriteFile (get_output_handle (), &dev_state.args_[0], 1, (DWORD *) &x, 0); + while (dev_state.args[1]--) + WriteFile (get_output_handle (), &dev_state.args[0], 1, (DWORD *) &x, 0); break; case 'c': /* u9 - Terminal enquire string */ if (dev_state.saw_greater_than_sign) @@ -1854,12 +1875,12 @@ fhandler_console::char_command (char c) puts_readahead (buf); break; case 'n': - switch (dev_state.args_[0]) + switch (dev_state.args[0]) { case 6: /* u7 - Cursor position request */ cursor_get (&x, &y); - y -= dev_state.info.winTop; - /* x -= dev_state.info.winLeft; // not available yet */ + y -= dev_state.winTop; + /* x -= dev_state.winLeft; // not available yet */ __small_sprintf (buf, "\033[%d;%dR", y + 1, x + 1); puts_readahead (buf); break; @@ -1868,8 +1889,8 @@ fhandler_console::char_command (char c) } break; case 'r': /* Set Scroll region */ - dev_state.scroll_region.Top = dev_state.args_[0] ? dev_state.args_[0] - 1 : 0; - dev_state.scroll_region.Bottom = dev_state.args_[1] ? dev_state.args_[1] - 1 : -1; + dev_state.scroll_region.Top = dev_state.args[0] ? dev_state.args[0] - 1 : 0; + dev_state.scroll_region.Bottom = dev_state.args[1] ? dev_state.args[1] - 1 : -1; cursor_set (true, 0, 0); break; case 'g': /* TAB set/clear */ @@ -2011,7 +2032,7 @@ do_print: { int x, y; cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + buf_len, y); + scroll_buffer (x, y, -1, y, x + buf_len, y); } if (!write_console (write_buf, buf_len, done)) @@ -2041,17 +2062,17 @@ do_print: beep (); break; case ESC: - dev_state.state_ = gotesc; + dev_state.state = gotesc; break; case DWN: cursor_get (&x, &y); if (y >= srBottom) { - if (y >= dev_state.info.winBottom && !dev_state.scroll_region.Top) + if (y >= dev_state.winBottom && !dev_state.scroll_region.Top) WriteConsoleW (get_output_handle (), L"\n", 1, &done, 0); else { - scroll_screen (0, srTop + 1, -1, srBottom, 0, srTop); + scroll_buffer (0, srTop + 1, -1, srBottom, 0, srTop); y--; } } @@ -2123,8 +2144,8 @@ fhandler_console::write (const void *vsrc, size_t len) while (src < end) { - paranoid_printf ("char %0c state is %d", *src, dev_state.state_); - switch (dev_state.state_) + paranoid_printf ("char %0c state is %d", *src, dev_state.state); + switch (dev_state.state) { case normal: src = write_normal (src, end); @@ -2134,33 +2155,33 @@ fhandler_console::write (const void *vsrc, size_t len) case gotesc: if (*src == '[') /* CSI Control Sequence Introducer */ { - dev_state.state_ = gotsquare; + dev_state.state = gotsquare; dev_state.saw_question_mark = false; dev_state.saw_greater_than_sign = false; dev_state.saw_space = false; - for (dev_state.nargs_ = 0; dev_state.nargs_ < MAXARGS; dev_state.nargs_++) - dev_state.args_[dev_state.nargs_] = 0; - dev_state.nargs_ = 0; + for (dev_state.nargs = 0; dev_state.nargs < MAXARGS; dev_state.nargs++) + dev_state.args[dev_state.nargs] = 0; + dev_state.nargs = 0; } else if (*src == ']') /* OSC Operating System Command */ { dev_state.rarg = 0; dev_state.my_title_buf[0] = '\0'; - dev_state.state_ = gotrsquare; + dev_state.state = gotrsquare; } else if (*src == '(') /* Designate G0 character set */ { - dev_state.state_ = gotparen; + dev_state.state = gotparen; } else if (*src == ')') /* Designate G1 character set */ { - dev_state.state_ = gotrparen; + dev_state.state = gotrparen; } else if (*src == 'M') /* Reverse Index (scroll down) */ { - dev_state.fillin_info (get_output_handle ()); - scroll_screen (0, 0, -1, -1, 0, dev_state.info.winTop + 1); - dev_state.state_ = normal; + dev_state.fillin (get_output_handle ()); + scroll_buffer (0, 0, -1, -1, 0, dev_state.winTop + 1); + dev_state.state = normal; } else if (*src == 'c') /* RIS Full Reset */ { @@ -2170,60 +2191,60 @@ fhandler_console::write (const void *vsrc, size_t len) dev_state.iso_2022_G1 = false; cursor_set (false, 0, 0); clear_screen (cl_buf_beg, cl_buf_beg, cl_buf_end, cl_buf_end); - dev_state.state_ = normal; + dev_state.state = normal; } else if (*src == '8') /* DECRC Restore cursor position */ { cursor_set (true, dev_state.savex, dev_state.savey); - dev_state.state_ = normal; + dev_state.state = normal; } else if (*src == '7') /* DECSC Save cursor position */ { cursor_get (&dev_state.savex, &dev_state.savey); - dev_state.savey -= dev_state.info.winTop; - dev_state.state_ = normal; + dev_state.savey -= dev_state.winTop; + dev_state.state = normal; } else if (*src == 'R') /* ? */ - dev_state.state_ = normal; + dev_state.state = normal; else { - dev_state.state_ = normal; + dev_state.state = normal; } src++; break; case gotarg1: if (isdigit (*src)) { - dev_state.args_[dev_state.nargs_] = dev_state.args_[dev_state.nargs_] * 10 + *src - '0'; + dev_state.args[dev_state.nargs] = dev_state.args[dev_state.nargs] * 10 + *src - '0'; src++; } else if (*src == ';') { src++; - dev_state.nargs_++; - if (dev_state.nargs_ >= MAXARGS) - dev_state.nargs_--; + dev_state.nargs++; + if (dev_state.nargs >= MAXARGS) + dev_state.nargs--; } else if (*src == ' ') { src++; dev_state.saw_space = true; - dev_state.state_ = gotcommand; + dev_state.state = gotcommand; } else - dev_state.state_ = gotcommand; + dev_state.state = gotcommand; break; case gotcommand: char_command (*src++); - dev_state.state_ = normal; + dev_state.state = normal; break; case gotrsquare: if (isdigit (*src)) dev_state.rarg = dev_state.rarg * 10 + (*src - '0'); else if (*src == ';' && (dev_state.rarg == 2 || dev_state.rarg == 0)) - dev_state.state_ = gettitle; + dev_state.state = gettitle; else - dev_state.state_ = eattitle; + dev_state.state = eattitle; src++; break; case eattitle: @@ -2232,9 +2253,9 @@ fhandler_console::write (const void *vsrc, size_t len) int n = strlen (dev_state.my_title_buf); if (*src < ' ') { - if (*src == '\007' && dev_state.state_ == gettitle) + if (*src == '\007' && dev_state.state == gettitle) set_console_title (dev_state.my_title_buf); - dev_state.state_ = normal; + dev_state.state = normal; } else if (n < TITLESIZE) { @@ -2247,12 +2268,12 @@ fhandler_console::write (const void *vsrc, size_t len) case gotsquare: if (*src == ';') { - dev_state.state_ = gotarg1; - dev_state.nargs_++; + dev_state.state = gotarg1; + dev_state.nargs++; src++; } else if (isalpha (*src)) - dev_state.state_ = gotcommand; + dev_state.state = gotcommand; else if (*src != '@' && !isalpha (*src) && !isdigit (*src)) { if (*src == '?') @@ -2263,14 +2284,14 @@ fhandler_console::write (const void *vsrc, size_t len) src++; } else - dev_state.state_ = gotarg1; + dev_state.state = gotarg1; break; case gotparen: /* Designate G0 Character Set (ISO 2022) */ if (*src == '0') dev_state.vt100_graphics_mode_G0 = true; else dev_state.vt100_graphics_mode_G0 = false; - dev_state.state_ = normal; + dev_state.state = normal; src++; break; case gotrparen: /* Designate G1 Character Set (ISO 2022) */ @@ -2278,7 +2299,7 @@ fhandler_console::write (const void *vsrc, size_t len) dev_state.vt100_graphics_mode_G1 = true; else dev_state.vt100_graphics_mode_G1 = false; - dev_state.state_ = normal; + dev_state.state = normal; src++; break; } diff --git a/winsup/cygwin/release/1.7.29 b/winsup/cygwin/release/1.7.29 index 3101f681e..66d807be4 100644 --- a/winsup/cygwin/release/1.7.29 +++ b/winsup/cygwin/release/1.7.29 @@ -16,3 +16,6 @@ What changed: Bug Fixes --------- +- Try harder to do the right thing in the presence of console screen buffers, + i.e., never clear the screen buffer unless the user asked for it. Also + fix screen escape sequences which attempted to scroll the screen.