diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 6ae7a458582..93c3870c933 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -443,6 +443,7 @@ DECSLPP DECSLRM DECSMKR DECSR +DECST DECSTBM DECSTGLT DECSTR diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 985fcadf343..d6687e19bd6 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -604,6 +604,16 @@ void ScreenBufferTests::TestResetClearTabStops() stateMachine.ProcessString(resetToInitialState); expectedStops = { 8, 16, 24, 32, 40, 48, 56, 64, 72 }; VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); + + Log::Comment(L"DECST8C with 5 parameter resets tabs to defaults."); + stateMachine.ProcessString(clearTabStops); + stateMachine.ProcessString(L"\033[?5W"); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); + + Log::Comment(L"DECST8C with omitted parameter resets tabs to defaults."); + stateMachine.ProcessString(clearTabStops); + stateMachine.ProcessString(L"\033[?W"); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); } void ScreenBufferTests::TestAddTabStop() diff --git a/src/terminal/adapter/DispatchTypes.hpp b/src/terminal/adapter/DispatchTypes.hpp index 612f82c093f..254bde75c21 100644 --- a/src/terminal/adapter/DispatchTypes.hpp +++ b/src/terminal/adapter/DispatchTypes.hpp @@ -558,6 +558,11 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes ClearAllColumns = 3 }; + enum TabSetType : VTInt + { + SetEvery8Columns = 5 + }; + enum WindowManipulationType : VTInt { Invalid = 0, diff --git a/src/terminal/adapter/ITermDispatch.hpp b/src/terminal/adapter/ITermDispatch.hpp index 9221ea3cb4f..1b847d32ba0 100644 --- a/src/terminal/adapter/ITermDispatch.hpp +++ b/src/terminal/adapter/ITermDispatch.hpp @@ -68,6 +68,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch virtual bool ForwardTab(const VTInt numTabs) = 0; // CHT, HT virtual bool BackwardsTab(const VTInt numTabs) = 0; // CBT virtual bool TabClear(const DispatchTypes::TabClearType clearType) = 0; // TBC + virtual bool TabSet(const VTParameter setType) = 0; // DECST8C virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) = 0; // OSCColorTable virtual bool SetDefaultForeground(const DWORD color) = 0; // OSCDefaultForeground virtual bool SetDefaultBackground(const DWORD color) = 0; // OSCDefaultBackground diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index 31edacae21d..4f2dfc41387 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -2793,16 +2793,23 @@ void AdaptDispatch::_ClearAllTabStops() noexcept } // Routine Description: -// - Clears all tab stops and sets the _initDefaultTabStops flag to indicate +// - DECST8C - If the parameter is SetEvery8Columns or is omitted, then this +// clears all tab stops and sets the _initDefaultTabStops flag to indicate // that the default positions should be reinitialized when needed. // Arguments: -// - +// - setType - only SetEvery8Columns is supported // Return value: -// - -void AdaptDispatch::_ResetTabStops() noexcept +// - True if handled successfully. False otherwise. +bool AdaptDispatch::TabSet(const VTParameter setType) noexcept { - _tabStopColumns.clear(); - _initDefaultTabStops = true; + constexpr auto SetEvery8Columns = DispatchTypes::TabSetType::SetEvery8Columns; + if (setType.value_or(SetEvery8Columns) == SetEvery8Columns) + { + _tabStopColumns.clear(); + _initDefaultTabStops = true; + return true; + } + return false; } // Routine Description: @@ -3076,7 +3083,7 @@ bool AdaptDispatch::HardReset() _api.GetTextBuffer().GetCursor().SetBlinkingAllowed(true); // Delete all current tab stops and reapply - _ResetTabStops(); + TabSet(DispatchTypes::TabSetType::SetEvery8Columns); // Clear the soft font in the renderer and delete the font buffer. _renderer.UpdateSoftFont({}, {}, false); diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index 4b145f1b8ca..3154a390d36 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -105,6 +105,7 @@ namespace Microsoft::Console::VirtualTerminal bool ForwardTab(const VTInt numTabs) override; // CHT, HT bool BackwardsTab(const VTInt numTabs) override; // CBT bool TabClear(const DispatchTypes::TabClearType clearType) override; // TBC + bool TabSet(const VTParameter setType) noexcept override; // DECST8C bool DesignateCodingSystem(const VTID codingSystem) override; // DOCS bool Designate94Charset(const VTInt gsetNumber, const VTID charset) override; // SCS bool Designate96Charset(const VTInt gsetNumber, const VTID charset) override; // SCS @@ -251,7 +252,6 @@ namespace Microsoft::Console::VirtualTerminal void _ClearSingleTabStop(); void _ClearAllTabStops() noexcept; - void _ResetTabStops() noexcept; void _InitTabStopsForWidth(const VTInt width); StringHandler _RestoreColorTable(); @@ -271,7 +271,7 @@ namespace Microsoft::Console::VirtualTerminal StringHandler _CreateDrcsPassthroughHandler(const DispatchTypes::DrcsCharsetSize charsetSize); StringHandler _CreatePassthroughHandler(); - std::vector _tabStopColumns; + std::vector _tabStopColumns; bool _initDefaultTabStops = true; ITerminalApi& _api; diff --git a/src/terminal/adapter/termDispatch.hpp b/src/terminal/adapter/termDispatch.hpp index 4f11ae8bb93..122b48820bb 100644 --- a/src/terminal/adapter/termDispatch.hpp +++ b/src/terminal/adapter/termDispatch.hpp @@ -61,6 +61,7 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons bool ForwardTab(const VTInt /*numTabs*/) override { return false; } // CHT, HT bool BackwardsTab(const VTInt /*numTabs*/) override { return false; } // CBT bool TabClear(const DispatchTypes::TabClearType /*clearType*/) override { return false; } // TBC + bool TabSet(const VTParameter /*setType*/) override { return false; } // DECST8C bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*color*/) override { return false; } // OSCColorTable bool SetDefaultForeground(const DWORD /*color*/) override { return false; } // OSCDefaultForeground bool SetDefaultBackground(const DWORD /*color*/) override { return false; } // OSCDefaultBackground diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index 68a45916df4..58e02c351cb 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -566,6 +566,11 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParamete return _dispatch->TabClear(clearType); }); break; + case CsiActionCodes::DECST8C_SetTabEvery8Columns: + success = parameters.for_each([&](const auto setType) { + return _dispatch->TabSet(setType); + }); + break; case CsiActionCodes::ECH_EraseCharacters: success = _dispatch->EraseCharacters(parameters.at(0)); break; diff --git a/src/terminal/parser/OutputStateMachineEngine.hpp b/src/terminal/parser/OutputStateMachineEngine.hpp index 8f3f72b9cb6..32105133bf3 100644 --- a/src/terminal/parser/OutputStateMachineEngine.hpp +++ b/src/terminal/parser/OutputStateMachineEngine.hpp @@ -121,6 +121,7 @@ namespace Microsoft::Console::VirtualTerminal DCH_DeleteCharacter = VTID("P"), SU_ScrollUp = VTID("S"), SD_ScrollDown = VTID("T"), + DECST8C_SetTabEvery8Columns = VTID("?W"), ECH_EraseCharacters = VTID("X"), CBT_CursorBackTab = VTID("Z"), HPA_HorizontalPositionAbsolute = VTID("`"),