* fhandler.h: Update copyright.

(cltype): New enum.
(dev_console::console_attrs): Define struct name.
(dev_console::console_attrs::set_cl_x): New function.
(dev_console::console_attrs::set_cl_y): New function.
(fhandler_console::clear_screen): Redefine input params.
* fhandler_console.cc: Update copyright.  Throughout, reflect change in
arguments to fhandler_console::clear_screeen.
(fhandler_console::mouse_aware): Simplify logic slightly.
(fhandler_console::scroll_screen): Remove hopefully obsolete win95 code.
(dev_console::console_attrs::set_cl_x): New function.
(dev_console::console_attrs::set_cl_y): New function.
(fhandler_console::clear_screen): Redefine input params.  Calculate position
based on enum value.
(region_split): Change arguments.  Simplify.
(ReadConsoleOutputWrapper): Remove coord argument since we now always use 0, 0.
Send extra arguments to region_split.
This commit is contained in:
Christopher Faylor 2014-01-04 23:58:32 +00:00
parent 1affdef86f
commit 36383c6f6e
5 changed files with 2214 additions and 2185 deletions

File diff suppressed because it is too large Load Diff

2078
winsup/cygwin/ChangeLog-2013 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* fhandler.h /* fhandler.h
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -1246,6 +1246,13 @@ enum ansi_intensity
#define gotrparen 9 #define gotrparen 9
#define MAXARGS 10 #define MAXARGS 10
enum cltype
{
cl_curr_pos = 1,
cl_disp_beg,
cl_disp_end
};
class dev_console class dev_console
{ {
WORD default_color, underline_color, dim_color; WORD default_color, underline_color, dim_color;
@ -1286,7 +1293,7 @@ class dev_console
{ {
short Top, Bottom; short Top, Bottom;
} scroll_region; } scroll_region;
struct struct console_attrs
{ {
SHORT winTop; SHORT winTop;
SHORT winBottom; SHORT winBottom;
@ -1294,6 +1301,8 @@ class dev_console
COORD dwBufferSize; COORD dwBufferSize;
COORD dwCursorPosition; COORD dwCursorPosition;
WORD wAttributes; WORD wAttributes;
int set_cl_x (cltype);
int set_cl_y (cltype);
} info; } info;
COORD dwLastCursorPosition; COORD dwLastCursorPosition;
@ -1346,7 +1355,7 @@ private:
/* Output calls */ /* Output calls */
void set_default_attr (); void set_default_attr ();
void clear_screen (int, int, int, int); void clear_screen (cltype, cltype, cltype, cltype);
void scroll_screen (int, int, int, int, int, int); void scroll_screen (int, int, int, int, int, int);
void cursor_set (bool, int, int); void cursor_set (bool, int, int);
void cursor_get (int *, int *); void cursor_get (int *, int *);

View File

@ -1,7 +1,7 @@
/* fhandler_console.cc /* fhandler_console.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -294,16 +294,12 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& mouse_event)
/* Adjust mouse position by window scroll buffer offset /* Adjust mouse position by window scroll buffer offset
and remember adjusted position in state for use by read() */ and remember adjusted position in state for use by read() */
CONSOLE_SCREEN_BUFFER_INFO now; CONSOLE_SCREEN_BUFFER_INFO now;
if (GetConsoleScreenBufferInfo (get_output_handle (), &now)) if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
{ /* Cannot adjust position by window scroll buffer offset */
dev_state.dwMousePosition.X = mouse_event.dwMousePosition.X - now.srWindow.Left; return 0;
dev_state.dwMousePosition.Y = mouse_event.dwMousePosition.Y - now.srWindow.Top;
} dev_state.dwMousePosition.X = mouse_event.dwMousePosition.X - now.srWindow.Left;
else dev_state.dwMousePosition.Y = mouse_event.dwMousePosition.Y - now.srWindow.Top;
{
/* Cannot adjust position by window scroll buffer offset */
return 0;
}
return ((mouse_event.dwEventFlags == 0 || mouse_event.dwEventFlags == DOUBLE_CLICK) return ((mouse_event.dwEventFlags == 0 || mouse_event.dwEventFlags == DOUBLE_CLICK)
&& mouse_event.dwButtonState != dev_state.dwLastButtonState) && mouse_event.dwButtonState != dev_state.dwLastButtonState)
@ -315,71 +311,6 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& mouse_event)
|| dev_state.use_mouse >= 3)); || dev_state.use_mouse >= 3));
} }
/* The following three functions were adapted (i.e., mildly modified) from
http://stackoverflow.com/questions/14699043/replacement-to-systemcolor */
/* Split a rectangular region into two smaller rectangles based on the
largest dimension. */
static void
region_split (SHORT width, SHORT height, COORD coord,
const SMALL_RECT& region, COORD& coord_a,
SMALL_RECT& region_a, COORD& coord_b,
SMALL_RECT& region_b)
{
coord_a = coord_b = coord;
region_a = region_b = region;
if (height >= width)
{
SHORT half = height / 2;
coord_b.Y += half;
region_b.Top += half;
region_a.Bottom = region_b.Top - 1;
}
else
{
SHORT half = width / 2;
coord_b.X += half;
region_b.Left += half;
region_a.Right = region_b.Left - 1;
}
}
/* Utility function to figure out the distance between two points. */
static SHORT
delta (SHORT first, SHORT second)
{
return (second >= first) ? (second - first + 1) : 0;
}
/* Subdivide the ReadConsoleInput operation into smaller and smaller chunks as
needed until it succeeds in reading the entire screen buffer. */
static BOOL
ReadConsoleOutputWrapper (HANDLE h, PCHAR_INFO buf,
COORD bufsiz, COORD coord,
SMALL_RECT& region)
{
SHORT width = delta (region.Left, region.Right);
SHORT height = delta (region.Top, region.Bottom);
if ((width == 0) || (height == 0))
return TRUE;
BOOL success = ReadConsoleOutputW (h, buf, bufsiz, coord, &region);
if (success)
/* it worked */;
else if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY && (width * height) > 1)
{
COORD coord_a, coord_b;
SMALL_RECT region_a, region_b;
region_split (width, height, coord, region, coord_a, region_a,
coord_b, region_b);
success = ReadConsoleOutputWrapper (h, buf, bufsiz, coord_a, region_a)
&& ReadConsoleOutputWrapper (h, buf, bufsiz, coord_b, region_b);
}
return success;
}
void __reg3 void __reg3
fhandler_console::read (void *pv, size_t& buflen) fhandler_console::read (void *pv, size_t& buflen)
{ {
@ -870,6 +801,7 @@ fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn)
fill.Attributes = dev_state.current_win32_attr; fill.Attributes = dev_state.current_win32_attr;
ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, dest, &fill); ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, 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 /* ScrollConsoleScreenBuffer on Windows 95 is buggy - when scroll distance
* is more than half of screen, filling doesn't work as expected */ * is more than half of screen, filling doesn't work as expected */
@ -879,6 +811,7 @@ fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn)
clear_screen (0, 1 + dest.Y + sr1.Bottom - sr1.Top, sr2.Right, sr2.Bottom); clear_screen (0, 1 + dest.Y + sr1.Bottom - sr1.Top, sr2.Right, sr2.Bottom);
else /* reverse scroll */ else /* reverse scroll */
clear_screen (0, sr1.Top, sr2.Right, dest.Y - 1); clear_screen (0, sr1.Top, sr2.Right, dest.Y - 1);
#endif
} }
int int
@ -1257,12 +1190,32 @@ dev_console::set_default_attr ()
set_color (NULL); set_color (NULL);
} }
int
dev_console::console_attrs::set_cl_x (cltype x)
{
if (x == cl_disp_beg)
return 0;
if (x == cl_disp_end)
return dwWinSize.X - 1;
return dwCursorPosition.X;
}
int
dev_console::console_attrs::set_cl_y (cltype y)
{
if (y == cl_disp_end)
return winBottom;
if (y == cl_disp_beg)
return winTop;
return dwCursorPosition.Y;
}
/* /*
* Clear the screen context from x1/y1 to x2/y2 cell. * Clear the screen context from x1/y1 to x2/y2 cell.
* Negative values represents current screen dimensions * Negative values represents current screen dimensions
*/ */
void void
fhandler_console::clear_screen (int x1, int y1, int x2, int y2) fhandler_console::clear_screen (cltype xc1, cltype yc1, cltype xc2, cltype yc2)
{ {
COORD tlc; COORD tlc;
DWORD done; DWORD done;
@ -1270,14 +1223,10 @@ fhandler_console::clear_screen (int x1, int y1, int x2, int y2)
dev_state.fillin_info (get_output_handle ()); dev_state.fillin_info (get_output_handle ());
if (x1 < 0) int x1 = dev_state.info.set_cl_x (xc1);
x1 = dev_state.info.dwWinSize.X - 1; int y1 = dev_state.info.set_cl_y (yc1);
if (y1 < 0) int x2 = dev_state.info.set_cl_x (xc2);
y1 = dev_state.info.winBottom; int y2 = dev_state.info.set_cl_y (yc2);
if (x2 < 0)
x2 = dev_state.info.dwWinSize.X - 1;
if (y2 < 0)
y2 = dev_state.info.winBottom;
num = abs (y1 - y2) * dev_state.info.dwBufferSize.X + abs (x1 - x2) + 1; num = abs (y1 - y2) * dev_state.info.dwBufferSize.X + abs (x1 - x2) + 1;
@ -1412,6 +1361,60 @@ bool fhandler_console::write_console (PWCHAR buf, DWORD len, DWORD& done)
return true; return true;
} }
/* The following three functions were adapted (i.e., mildly modified) from
http://stackoverflow.com/questions/14699043/replacement-to-systemcolor */
/* Split a rectangular region into two smaller rectangles based on the
largest dimension. */
static void
region_split (PCHAR_INFO& buf, COORD& bufsiz, SMALL_RECT& region,
PCHAR_INFO& buf_b, COORD& bufsiz_b, SMALL_RECT& region_b)
{
region_b = region;
bufsiz_b = bufsiz;
SHORT half = (1 + region.Bottom - region.Top) / 2;
region_b.Top += half;
region.Bottom = (bufsiz.Y = region_b.Top) - 1;
buf_b = buf + (half * (1 + region.Right));
bufsiz_b.Y = region_b.Bottom - region_b.Top;
}
/* Utility function to figure out the distance between two points. */
static SHORT
delta (SHORT first, SHORT second)
{
return (second >= first) ? (second - first + 1) : 0;
}
/* Subdivide the ReadConsoleInput operation into smaller and smaller chunks as
needed until it succeeds in reading the entire screen buffer. */
static BOOL
ReadConsoleOutputWrapper (HANDLE h, PCHAR_INFO buf, COORD bufsiz,
SMALL_RECT& region)
{
COORD coord = {};
SHORT width = delta (region.Left, region.Right);
SHORT height = delta (region.Top, region.Bottom);
if ((width == 0) || (height == 0))
return TRUE;
BOOL success = ReadConsoleOutputW (h, buf, bufsiz, coord, &region);
if (success)
/* it worked */;
else if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY && (width * height) > 1)
{
PCHAR_INFO buf_b;
COORD bufsiz_b;
SMALL_RECT region_b;
region_split (buf, bufsiz, region, buf_b, bufsiz_b, region_b);
success = ReadConsoleOutputWrapper (h, buf, bufsiz, region)
&& ReadConsoleOutputWrapper (h, buf_b, bufsiz_b, region_b);
}
return success;
}
#define BAK 1 #define BAK 1
#define ESC 2 #define ESC 2
#define NOR 0 #define NOR 0
@ -1628,13 +1631,13 @@ fhandler_console::char_command (char c)
if (c == 'h') /* save */ if (c == 'h') /* save */
{ {
CONSOLE_SCREEN_BUFFER_INFO now; CONSOLE_SCREEN_BUFFER_INFO now;
COORD cob = { 0, 0 };
if (!GetConsoleScreenBufferInfo (get_output_handle (), &now)) if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
break; break;
dev_state.savebufsiz.X = now.srWindow.Right - now.srWindow.Left + 1; /* Assume starting from 0/0 */
dev_state.savebufsiz.Y = now.srWindow.Bottom - now.srWindow.Top + 1; dev_state.savebufsiz.X = 1 + now.srWindow.Right;
dev_state.savebufsiz.Y = 1 + now.srWindow.Bottom;
if (dev_state.savebuf) if (dev_state.savebuf)
cfree (dev_state.savebuf); cfree (dev_state.savebuf);
@ -1643,7 +1646,7 @@ fhandler_console::char_command (char c)
BOOL res = ReadConsoleOutputWrapper (get_output_handle (), BOOL res = ReadConsoleOutputWrapper (get_output_handle (),
dev_state.savebuf, dev_state.savebuf,
dev_state.savebufsiz, cob, dev_state.savebufsiz,
now.srWindow); now.srWindow);
if (!res) if (!res)
debug_printf ("ReadConsoleOutputWrapper failed, %E"); debug_printf ("ReadConsoleOutputWrapper failed, %E");
@ -1718,16 +1721,15 @@ fhandler_console::char_command (char c)
switch (dev_state.args_[0]) switch (dev_state.args_[0])
{ {
case 0: /* Clear to end of screen */ case 0: /* Clear to end of screen */
cursor_get (&x, &y); clear_screen (cl_curr_pos, cl_curr_pos, cl_disp_end, cl_disp_end);
clear_screen (x, y, -1, -1);
break; break;
case 1: /* Clear from beginning of screen to cursor */ case 1: /* Clear from beginning of screen to cursor */
cursor_get (&x, &y); cursor_get (&x, &y);
clear_screen (0, 0, x, y); clear_screen (cl_disp_beg, cl_disp_beg, cl_curr_pos, cl_curr_pos);
break; break;
case 2: /* Clear screen */ case 2: /* Clear screen */
clear_screen (0, 0, -1, -1); clear_screen (cl_disp_beg, cl_disp_beg, cl_disp_end, cl_disp_end);
cursor_set (true, 0,0); cursor_set (true, 0, 0);
break; break;
default: default:
goto bad_escape; goto bad_escape;
@ -1750,16 +1752,13 @@ fhandler_console::char_command (char c)
switch (dev_state.args_[0]) switch (dev_state.args_[0])
{ {
case 0: /* Clear to end of line */ case 0: /* Clear to end of line */
cursor_get (&x, &y); clear_screen (cl_curr_pos, cl_curr_pos, cl_disp_end, cl_curr_pos);
clear_screen (x, y, -1, y);
break; break;
case 2: /* Clear line */ case 2: /* Clear line */
cursor_get (&x, &y); clear_screen (cl_disp_beg, cl_curr_pos, cl_disp_end, cl_curr_pos);
clear_screen (0, y, -1, y);
break; break;
case 1: /* Clear from bol to cursor */ case 1: /* Clear from bol to cursor */
cursor_get (&x, &y); clear_screen (cl_disp_beg, cl_curr_pos, cl_curr_pos, cl_curr_pos);
clear_screen (0, y, x, y);
break; break;
default: default:
goto bad_escape; goto bad_escape;
@ -2165,7 +2164,7 @@ fhandler_console::write (const void *vsrc, size_t len)
dev_state.vt100_graphics_mode_G0 = false; dev_state.vt100_graphics_mode_G0 = false;
dev_state.vt100_graphics_mode_G1 = false; dev_state.vt100_graphics_mode_G1 = false;
dev_state.iso_2022_G1 = false; dev_state.iso_2022_G1 = false;
clear_screen (0, 0, -1, -1); clear_screen (cl_disp_beg, cl_disp_beg, cl_disp_end, cl_disp_end);
cursor_set (true, 0, 0); cursor_set (true, 0, 0);
dev_state.state_ = normal; dev_state.state_ = normal;
} }
@ -2208,9 +2207,7 @@ fhandler_console::write (const void *vsrc, size_t len)
dev_state.state_ = gotcommand; dev_state.state_ = gotcommand;
} }
else else
{ dev_state.state_ = gotcommand;
dev_state.state_ = gotcommand;
}
break; break;
case gotcommand: case gotcommand:
char_command (*src++); char_command (*src++);

View File

@ -29,3 +29,6 @@ Bug Fixes
- The console buffer should no longer be cleared when the resolution of the - The console buffer should no longer be cleared when the resolution of the
console exceeds some magic threshold. console exceeds some magic threshold.
Fixes: http://cygwin.com/ml/cygwin/2013-12/threads.html#00406 Fixes: http://cygwin.com/ml/cygwin/2013-12/threads.html#00406
- Fix inadvertent clearing of entire console buffer on clear screen.
See: http://cygwin.com/ml/cygwin/2014-01/msg00011.html