Bugfix: CLS should clear current active buffer (#2729)
CLS calls two functions: - `SetConsoleCursorPositionImpl()` - `ScrollConsoleScreenBufferWImpl()` Both of these were not checking which buffer to apply to (main vs active buffer). Now we get the active buffer and apply the changes to that one. Also, we forgot to switch out of the alt buffer in the previous test. Added that in. Closes #1189.
This commit is contained in:
parent
b693fd484a
commit
3d35e396b2
|
@ -632,7 +632,9 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
|
||||
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
|
||||
const COORD coordScreenBufferSize = context.GetBufferSize().Dimensions();
|
||||
auto& buffer = context.GetActiveBuffer();
|
||||
|
||||
const COORD coordScreenBufferSize = buffer.GetBufferSize().Dimensions();
|
||||
// clang-format off
|
||||
RETURN_HR_IF(E_INVALIDARG, (position.X >= coordScreenBufferSize.X ||
|
||||
position.Y >= coordScreenBufferSize.Y ||
|
||||
|
@ -643,7 +645,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
// MSFT: 15813316 - Try to use this SetCursorPosition call to inherit the cursor position.
|
||||
RETURN_IF_FAILED(gci.GetVtIo()->SetCursorPosition(position));
|
||||
|
||||
RETURN_IF_NTSTATUS_FAILED(context.SetCursorPosition(position, true));
|
||||
RETURN_IF_NTSTATUS_FAILED(buffer.SetCursorPosition(position, true));
|
||||
|
||||
LOG_IF_FAILED(ConsoleImeResizeCompStrView());
|
||||
|
||||
|
@ -651,7 +653,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
WindowOrigin.X = 0;
|
||||
WindowOrigin.Y = 0;
|
||||
{
|
||||
const SMALL_RECT currentViewport = context.GetViewport().ToInclusive();
|
||||
const SMALL_RECT currentViewport = buffer.GetViewport().ToInclusive();
|
||||
if (currentViewport.Left > position.X)
|
||||
{
|
||||
WindowOrigin.X = position.X - currentViewport.Left;
|
||||
|
@ -671,7 +673,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
}
|
||||
}
|
||||
|
||||
RETURN_IF_NTSTATUS_FAILED(context.SetViewportOrigin(false, WindowOrigin, true));
|
||||
RETURN_IF_NTSTATUS_FAILED(buffer.SetViewportOrigin(false, WindowOrigin, true));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -820,6 +822,8 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
|
||||
auto& buffer = context.GetActiveBuffer();
|
||||
|
||||
TextAttribute useThisAttr(fillAttribute);
|
||||
|
||||
// Here we're being a little clever - similar to FillConsoleOutputAttributeImpl
|
||||
|
@ -835,10 +839,11 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
// this scenario is highly unlikely, and we can reasonably do this
|
||||
// on their behalf.
|
||||
// see MSFT:19853701
|
||||
if (context.InVTMode())
|
||||
|
||||
if (buffer.InVTMode())
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
const auto currentAttributes = context.GetAttributes();
|
||||
const auto currentAttributes = buffer.GetAttributes();
|
||||
const auto bufferLegacy = gci.GenerateLegacyAttributes(currentAttributes);
|
||||
if (bufferLegacy == fillAttribute)
|
||||
{
|
||||
|
@ -846,7 +851,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
|||
}
|
||||
}
|
||||
|
||||
ScrollRegion(context, source, clip, target, fillCharacter, useThisAttr);
|
||||
ScrollRegion(buffer, source, clip, target, fillCharacter, useThisAttr);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -178,6 +178,8 @@ class ScreenBufferTests
|
|||
TEST_METHOD(HardResetBuffer);
|
||||
|
||||
TEST_METHOD(RestoreDownAltBufferWithTerminalScrolling);
|
||||
|
||||
TEST_METHOD(ClearAlternateBuffer);
|
||||
};
|
||||
|
||||
void ScreenBufferTests::SingleAlternateBufferCreationTest()
|
||||
|
@ -4219,6 +4221,8 @@ void ScreenBufferTests::RestoreDownAltBufferWithTerminalScrolling()
|
|||
VERIFY_ARE_EQUAL(0, altBuffer._viewport.Top());
|
||||
VERIFY_ARE_EQUAL(altBuffer._viewport.BottomInclusive(), altBuffer._virtualBottom);
|
||||
|
||||
auto useMain = wil::scope_exit([&] { altBuffer.UseMainScreenBuffer(); });
|
||||
|
||||
const COORD originalSize = originalView.Dimensions();
|
||||
const COORD doubledSize = { originalSize.X * 2, originalSize.Y * 2 };
|
||||
|
||||
|
@ -4255,3 +4259,91 @@ void ScreenBufferTests::RestoreDownAltBufferWithTerminalScrolling()
|
|||
VERIFY_ARE_EQUAL(altBuffer._viewport.BottomInclusive(), altBuffer._virtualBottom);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenBufferTests::ClearAlternateBuffer()
|
||||
{
|
||||
// This is a test for microsoft/terminal#1189. Refer to that issue for more
|
||||
// context
|
||||
|
||||
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
|
||||
auto& siMain = gci.GetActiveOutputBuffer();
|
||||
auto WriteText = [&](TextBuffer& tbi) {
|
||||
// Write text to buffer
|
||||
auto& stateMachine = siMain.GetStateMachine();
|
||||
auto& cursor = tbi.GetCursor();
|
||||
stateMachine.ProcessString(L"foo\nfoo");
|
||||
VERIFY_ARE_EQUAL(cursor.GetPosition().X, 3);
|
||||
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 1);
|
||||
};
|
||||
|
||||
auto VerifyText = [&](TextBuffer& tbi) {
|
||||
// Verify written text in buffer
|
||||
{
|
||||
auto iter00 = tbi.GetCellDataAt({ 0, 0 });
|
||||
auto iter10 = tbi.GetCellDataAt({ 1, 0 });
|
||||
auto iter20 = tbi.GetCellDataAt({ 2, 0 });
|
||||
auto iter30 = tbi.GetCellDataAt({ 3, 0 });
|
||||
auto iter01 = tbi.GetCellDataAt({ 0, 1 });
|
||||
auto iter02 = tbi.GetCellDataAt({ 1, 1 });
|
||||
auto iter03 = tbi.GetCellDataAt({ 2, 1 });
|
||||
VERIFY_ARE_EQUAL(L"f", iter00->Chars());
|
||||
VERIFY_ARE_EQUAL(L"o", iter10->Chars());
|
||||
VERIFY_ARE_EQUAL(L"o", iter20->Chars());
|
||||
VERIFY_ARE_EQUAL(L"\x20", iter30->Chars());
|
||||
VERIFY_ARE_EQUAL(L"f", iter01->Chars());
|
||||
VERIFY_ARE_EQUAL(L"o", iter02->Chars());
|
||||
VERIFY_ARE_EQUAL(L"o", iter03->Chars());
|
||||
}
|
||||
};
|
||||
|
||||
WriteText(siMain.GetTextBuffer());
|
||||
VerifyText(siMain.GetTextBuffer());
|
||||
|
||||
Log::Comment(L"Create an alternate buffer");
|
||||
if (VERIFY_IS_TRUE(NT_SUCCESS(siMain.UseAlternateScreenBuffer())))
|
||||
{
|
||||
VERIFY_IS_NOT_NULL(siMain._psiAlternateBuffer);
|
||||
auto& altBuffer = *siMain._psiAlternateBuffer;
|
||||
VERIFY_ARE_EQUAL(0, altBuffer._viewport.Top());
|
||||
VERIFY_ARE_EQUAL(altBuffer._viewport.BottomInclusive(), altBuffer._virtualBottom);
|
||||
|
||||
auto useMain = wil::scope_exit([&] { altBuffer.UseMainScreenBuffer(); });
|
||||
|
||||
WriteText(altBuffer.GetTextBuffer());
|
||||
VerifyText(altBuffer.GetTextBuffer());
|
||||
|
||||
#pragma region Test ScrollConsoleScreenBufferWImpl()
|
||||
// Clear text of alt buffer (same params as in CMD)
|
||||
VERIFY_SUCCEEDED(g.api.ScrollConsoleScreenBufferWImpl(siMain,
|
||||
{ 0, 0, 120, 9001 },
|
||||
{ 0, -9001 },
|
||||
std::nullopt,
|
||||
L' ',
|
||||
7));
|
||||
|
||||
// Verify text is now gone
|
||||
VERIFY_ARE_EQUAL(L" ", altBuffer.GetTextBuffer().GetCellDataAt({ 0, 0 })->Chars());
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Test SetConsoleCursorPositionImpl()
|
||||
// Reset cursor position as we do with CLS command (same params as in CMD)
|
||||
VERIFY_SUCCEEDED(g.api.SetConsoleCursorPositionImpl(siMain, { 0 }));
|
||||
|
||||
// Verify state of alt buffer
|
||||
auto& altBufferCursor = altBuffer.GetTextBuffer().GetCursor();
|
||||
VERIFY_ARE_EQUAL(altBufferCursor.GetPosition().X, 0);
|
||||
VERIFY_ARE_EQUAL(altBufferCursor.GetPosition().Y, 0);
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
// Verify state of main buffer is untouched
|
||||
auto& cursor = siMain.GetTextBuffer().GetCursor();
|
||||
VERIFY_ARE_EQUAL(cursor.GetPosition().X, 3);
|
||||
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 1);
|
||||
|
||||
VerifyText(siMain.GetTextBuffer());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue