Implementing Write-Progress using SetBufferContents

This commit is contained in:
Alex Jordan
2016-07-19 21:07:06 -07:00
parent 4c9a44de8b
commit d9ac6d6401
2 changed files with 111 additions and 8 deletions
@@ -1711,7 +1711,44 @@ namespace Microsoft.PowerShell
}
}
/// <summary>
public void ScrollBuffer(int lines)
{
for (int i=0; i<lines; ++i)
{
Console.Out.Write('\n');
}
}
internal struct COORD
{
internal short X;
internal short Y;
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", X, Y);
}
}
internal struct SMALL_RECT
{
internal short Left;
internal short Top;
internal short Right;
internal short Bottom;
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", Left, Top, Right, Bottom);
}
}
/// <summary>
/// This API returns a rectangular region of the screen buffer. In
/// this example this functionality is not needed so the method throws
/// a NotImplementException exception.
@@ -1760,7 +1797,54 @@ namespace Microsoft.PowerShell
public override void SetBufferContents(Coordinates origin,
BufferCell[,] contents)
{
throw new NotImplementedException("The method or operation is not implemented.");
//if there are no contents, there is nothing to set the buffer to
if (contents == null)
{
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 (cursorY == Console.BufferHeight -1 && cursorX >= Console.BufferWidth)
{
//for each row in the buffer, create a new line
int rows = contents.GetLength(0);
for (int i=0; i < rows; i++)
{
ScrollBuffer(1);
}
//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
foreach (var charitem in contents)
{
//set the cursor to false to prevent cursor flicker
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
Console.Out.Write(charitem.Character);
//advance the character one position
cursorX++;
}
//reset the cursor to the original position
Console.SetCursorPosition(cursorX, cursorY);
//reset the cursor to visible
Console.CursorVisible = true;
}
/// <summary>
@@ -102,14 +102,33 @@ namespace Microsoft.PowerShell
location.X = 0;
location.Y = Math.Min(location.Y + 2, bufSize.Height);
// 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));
if (System.Management.Automation.Platform.IsWindows)
{
// 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));
}
//Platform is either OSX or Linux
else
{
// replace the saved region in the screen buffer with our progress display
location.X = rawui.CursorPosition.X;
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;
}
Console.SetCursorPosition(location.X, location.Y);
}
// replace the saved region in the screen buffer with our progress display
rawui.SetBufferContents(location, tempProgressRegion);
}
}