Skip to content

Commit

Permalink
Support VT100 DECOM Origin Mode (#1331)
Browse files Browse the repository at this point in the history
* Add support for origin mode (DECOM).
* Added a state machine unit test for the origin mode.
* Prevent the cursor position moving below the bottom margin of the scrolling region if the origin mode is relative.
* Only adjust the relative cursor position for origin mode if the scrolling region is actually set.
* Add some screenbuffer unit tests for the origin mode.
* Enhance the soft reset screenbuffer tests to verify the origin mode is reset.
* Move the origin mode flag constructor assignments into the intializer list.
  • Loading branch information
j4james authored and miniksa committed Jul 2, 2019
1 parent 5dbcd4c commit fe7fd33
Show file tree
Hide file tree
Showing 7 changed files with 4,048 additions and 3,866 deletions.
86 changes: 86 additions & 0 deletions src/host/ut_host/ScreenBufferTests.cpp
Expand Up @@ -163,6 +163,8 @@ class ScreenBufferTests

TEST_METHOD(ScrollUpInMargins);
TEST_METHOD(ScrollDownInMargins);

TEST_METHOD(SetOriginMode);
};

void ScreenBufferTests::SingleAlternateBufferCreationTest()
Expand Down Expand Up @@ -1143,6 +1145,22 @@ void ScreenBufferTests::VtSoftResetCursorPosition()
seq = L"\x1b[!p";
stateMachine.ProcessString(&seq[0], seq.length());
VERIFY_ARE_EQUAL(COORD({ 1, 1 }), cursor.GetPosition());

Log::Comment(
L"Set the origin mode, some margins, and move the cursor to 2,2.\n"
L"The position should be relative to the top-left of the margin area.");
stateMachine.ProcessString(L"\x1b[?6h");
stateMachine.ProcessString(L"\x1b[5;10r");
stateMachine.ProcessString(L"\x1b[2;2H");
VERIFY_ARE_EQUAL(COORD({ 1, 5 }), cursor.GetPosition());

Log::Comment(
L"Execute a soft reset, reapply the margins, and move the cursor to 2,2.\n"
L"The position should now be relative to the top-left of the screen.");
stateMachine.ProcessString(L"\x1b[!p");
stateMachine.ProcessString(L"\x1b[5;10r");
stateMachine.ProcessString(L"\x1b[2;2H");
VERIFY_ARE_EQUAL(COORD({ 1, 1 }), cursor.GetPosition());
}

void ScreenBufferTests::VtScrollMarginsNewlineColor()
Expand Down Expand Up @@ -3201,3 +3219,71 @@ void ScreenBufferTests::ScrollDownInMargins()
VERIFY_ARE_EQUAL(L"B", iter5->Chars());
}
}

void ScreenBufferTests::SetOriginMode()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
auto& stateMachine = si.GetStateMachine();
auto& cursor = si.GetTextBuffer().GetCursor();

const auto view = Viewport::FromDimensions({ 0, 0 }, { 80, 25 });
si.SetViewport(view, true);

// Testing the default state (absolute cursor addressing)
Log::Comment(L"By default, setting a margin moves the cursor to the top-left of the screen.");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[6;20r");
VERIFY_ARE_EQUAL(COORD({ 0, 0 }), cursor.GetPosition());
Log::Comment(L"Cursor addressing is relative to the top-left of the screen.");
stateMachine.ProcessString(L"\x1B[13;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 12 }), cursor.GetPosition());
Log::Comment(L"The cursor can be moved below the bottom margin.");
stateMachine.ProcessString(L"\x1B[23;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 22 }), cursor.GetPosition());

// Testing the effects of DECOM being set (relative cursor addressing)
Log::Comment(L"Setting DECOM moves the cursor to the top-left of the margin area.");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[?6h");
VERIFY_ARE_EQUAL(COORD({ 0, 5 }), cursor.GetPosition());
Log::Comment(L"Setting a margin moves the cursor to the top-left of the margin area.");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[6;20r");
VERIFY_ARE_EQUAL(COORD({ 0, 5 }), cursor.GetPosition());
Log::Comment(L"Cursor addressing is relative to the top-left of the margin area.");
stateMachine.ProcessString(L"\x1B[8;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 12 }), cursor.GetPosition());
Log::Comment(L"The cursor cannot be moved below the bottom margin.");
stateMachine.ProcessString(L"\x1B[100;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 19 }), cursor.GetPosition());

// Testing the effects of DECOM being reset (absolute cursor addressing)
Log::Comment(L"Resetting DECOM moves the cursor to the top-left of the screen.");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[?6l");
VERIFY_ARE_EQUAL(COORD({ 0, 0 }), cursor.GetPosition());
Log::Comment(L"Setting a margin moves the cursor to the top-left of the screen.");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[6;20r");
VERIFY_ARE_EQUAL(COORD({ 0, 0 }), cursor.GetPosition());
Log::Comment(L"Cursor addressing is relative to the top-left of the screen.");
stateMachine.ProcessString(L"\x1B[13;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 12 }), cursor.GetPosition());
Log::Comment(L"The cursor can be moved below the bottom margin.");
stateMachine.ProcessString(L"\x1B[23;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 22 }), cursor.GetPosition());

// Testing the effects of DECOM being set with no margins
Log::Comment(L"With no margins, setting DECOM moves the cursor to the top-left of the screen.");
stateMachine.ProcessString(L"\x1B[r");
cursor.SetPosition({ 40, 12 });
stateMachine.ProcessString(L"\x1B[?6h");
VERIFY_ARE_EQUAL(COORD({ 0, 0 }), cursor.GetPosition());
Log::Comment(L"Cursor addressing is still relative to the top-left of the screen.");
stateMachine.ProcessString(L"\x1B[13;41H");
VERIFY_ARE_EQUAL(COORD({ 40, 12 }), cursor.GetPosition());

// Reset DECOM so we don't affect future tests
stateMachine.ProcessString(L"\x1B[?6l");
}
1 change: 1 addition & 0 deletions src/terminal/adapter/DispatchTypes.hpp
Expand Up @@ -75,6 +75,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
{
DECCKM_CursorKeysMode = 1,
DECCOLM_SetNumberOfColumns = 3,
DECOM_OriginMode = 6,
ATT610_StartCursorBlink = 12,
DECTCEM_TextCursorEnableMode = 25,
XTERM_EnableDECCOLMSupport = 40,
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Expand Up @@ -49,6 +49,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
virtual bool SetCursorKeysMode(const bool fApplicationMode) = 0; // DECCKM
virtual bool SetKeypadMode(const bool fApplicationMode) = 0; // DECKPAM, DECKPNM
virtual bool EnableCursorBlinking(const bool fEnable) = 0; // ATT610
virtual bool SetOriginMode(const bool fRelativeMode) = 0; // DECOM
virtual bool SetTopBottomScrollingMargins(const SHORT sTopMargin, const SHORT sBottomMargin) = 0; // DECSTBM
virtual bool ReverseLineFeed() = 0; // RI
virtual bool SetWindowTitle(std::wstring_view title) = 0; // OscWindowTitle
Expand Down

0 comments on commit fe7fd33

Please sign in to comment.