Guard ProgressPane for pseudo-TTYs

Again due to the fact that relying on Console.IsOutputRedirected (as
System.Console does for these APIs) causes bugs when pseudo-TTYs are
used (since the output is not redirected, but the APIs nonetheless can't
be used properly). So we ran into a problem where the value of CursorTop
and Console.BufferHeight were lies, and so we accidentally attempted to
set it numbers below zero. Guard everything.
This commit is contained in:
Andrew Schwartzmeyer committed 2016-07-24 17:13:39 -07:00
1 parent 79daea0132
commit bcfe498ef4
2 files changed
+42 -49

No files matched your search

@@ -1577,7 +1577,8 @@ namespace Microsoft.PowerShell
public override Coordinates CursorPosition public override Coordinates CursorPosition
{ {
get { return new Coordinates(Console.CursorLeft, Console.CursorTop); } get { return new Coordinates(Console.CursorLeft, Console.CursorTop); }
set { Console.SetCursorPosition(value.X, value.Y); } set { Console.SetCursorPosition(value.X < 0 ? 0 : value.X,
value.Y < 0 ? 0 : value.Y); }
} }
/// <summary> /// <summary>
@@ -1796,54 +1797,49 @@ namespace Microsoft.PowerShell
public override void SetBufferContents(Coordinates origin, public override void SetBufferContents(Coordinates origin,
BufferCell[,] contents) BufferCell[,] contents)
{ {
//if there are no contents, there is nothing to set the buffer to //if there are no contents, there is nothing to set the buffer to
if (contents == null) if (contents == null)
{ {
PSTraceSource.NewArgumentNullException("contents"); PSTraceSource.NewArgumentNullException("contents");
} }
//variables to traverse through the buffer
int cursorX = origin.X;
int cursorY = origin.Y;
//if the cursor is on the last line, we need to make more space to print the specified buffer //if the cursor is on the last line, we need to make more space to print the specified buffer
if (cursorY == Console.BufferHeight -1 && cursorX >= Console.BufferWidth) if (origin.Y == BufferSize.Height - 1 && origin.X >= BufferSize.Width)
{ {
//for each row in the buffer, create a new line //for each row in the buffer, create a new line
int rows = contents.GetLength(0); int rows = contents.GetLength(0);
for (int i=0; i < rows; i++) ScrollBuffer(rows);
// for each row in the buffer, move the cursor y up to the beginning of the created blank space
// but not above zero
if (origin.Y >= rows)
{ {
ScrollBuffer(1); origin.Y -= rows;
} }
//for each row in the buffer, move the cursor y up to the beginning of the created blank space
cursorY -= rows;
} }
//iterate through the buffer to set //iterate through the buffer to set
foreach (var charitem in contents) foreach (var charitem in contents)
{ {
//set the cursor to false to prevent cursor flicker //set the cursor to false to prevent cursor flicker
Console.CursorVisible = false; Console.CursorVisible = false;
//if x is exceeding buffer width, reset to the next line
if (cursorX >= Console.BufferWidth)
{
cursorX = 1;
}
//write the character from contents //if x is exceeding buffer width, reset to the next line
if (origin.X >= BufferSize.Width)
{
origin.X = 1;
}
//write the character from contents
Console.Out.Write(charitem.Character); Console.Out.Write(charitem.Character);
//advance the character one position //advance the character one position
cursorX++; origin.X++;
} }
//reset the cursor to the original position //reset the cursor to the original position
Console.SetCursorPosition(cursorX, cursorY); CursorPosition = origin;
//reset the cursor to visible //reset the cursor to visible
Console.CursorVisible = true; Console.CursorVisible = true;
} }
/// <summary> /// <summary>
@@ -102,32 +102,29 @@ namespace Microsoft.PowerShell
location.X = 0; location.X = 0;
location.Y = Math.Min(location.Y + 2, bufSize.Height); location.Y = Math.Min(location.Y + 2, bufSize.Height);
if (System.Management.Automation.Platform.IsWindows) #if UNIX
{ // replace the saved region in the screen buffer with our progress display
// Save off the current contents of the screen buffer in the region that we will occupy location = rawui.CursorPosition;
savedRegion =
rawui.GetBufferContents(
new Rectangle(location.X, location.Y, location.X + cols - 1, location.Y + rows - 1));
}
//Platform is either OSX or Linux //set the cursor position back to the beginning of the region to overwrite write-progress
else //if the cursor is at the bottom, back it up to overwrite the previous write progress
if (location.Y >= rawui.BufferSize.Height - rows)
{ {
// replace the saved region in the screen buffer with our progress display Console.Out.Write('\n');
location.X = rawui.CursorPosition.X; if (location.Y >= rows)
location.Y = rawui.CursorPosition.Y;
//set the cursor position back to the beginning of the region to overwrite write-progress
//if the cursor is at the bottom, back it up to overwrite the previous write progress
if (location.Y >= Console.BufferHeight - rows)
{ {
Console.Out.Write('\n');
location.Y -= rows; location.Y -= rows;
} }
Console.SetCursorPosition(location.X, location.Y);
} }
rawui.CursorPosition = location;
#else
// Save off the current contents of the screen buffer in the region that we will occupy
savedRegion =
rawui.GetBufferContents(
new Rectangle(location.X, location.Y, location.X + cols - 1, location.Y + rows - 1));
#endif
// replace the saved region in the screen buffer with our progress display // replace the saved region in the screen buffer with our progress display
rawui.SetBufferContents(location, tempProgressRegion); rawui.SetBufferContents(location, tempProgressRegion);
} }