diff --git a/src/host/getset.cpp b/src/host/getset.cpp index e55ba97c8f1..c8d81f92670 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -404,13 +404,6 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept { // jiggle the handle screenInfo.GetStateMachine().ResetState(); - screenInfo.ClearTabStops(); - } - // if we're moving from VT off->on - else if (WI_IsFlagSet(dwNewMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) && - WI_IsFlagClear(dwOldMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - { - screenInfo.SetDefaultVtTabStops(); } gci.SetVirtTermLevel(WI_IsFlagSet(dwNewMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? 1 : 0); @@ -1522,99 +1515,6 @@ void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo) screenInfo.GetActiveBuffer().UseMainScreenBuffer(); } -// Routine Description: -// - A private API call for setting a VT tab stop in the cursor's current column. -// Parameters: -// -// Return value: -// - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. -[[nodiscard]] NTSTATUS DoSrvPrivateHorizontalTabSet() -{ - CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - SCREEN_INFORMATION& _screenBuffer = gci.GetActiveOutputBuffer().GetActiveBuffer(); - - const COORD cursorPos = _screenBuffer.GetTextBuffer().GetCursor().GetPosition(); - try - { - _screenBuffer.AddTabStop(cursorPos.X); - } - catch (...) - { - return NTSTATUS_FROM_HRESULT(wil::ResultFromCaughtException()); - } - return STATUS_SUCCESS; -} - -// Routine Description: -// - A private helper for executing a number of tabs. -// Parameters: -// sNumTabs - The number of tabs to execute -// fForward - whether to tab forward or backwards -// Return value: -// - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. -[[nodiscard]] NTSTATUS DoPrivateTabHelper(const SHORT sNumTabs, _In_ bool fForward) -{ - CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - SCREEN_INFORMATION& _screenBuffer = gci.GetActiveOutputBuffer().GetActiveBuffer(); - COORD cursorPos = _screenBuffer.GetTextBuffer().GetCursor().GetPosition(); - - FAIL_FAST_IF(!(sNumTabs >= 0)); - for (SHORT sTabsExecuted = 0; sTabsExecuted < sNumTabs; sTabsExecuted++) - { - cursorPos = (fForward) ? _screenBuffer.GetForwardTab(cursorPos) : _screenBuffer.GetReverseTab(cursorPos); - } - - return AdjustCursorPosition(_screenBuffer, cursorPos, TRUE, nullptr); -} - -// Routine Description: -// - A private API call for performing a forwards tab. This will take the -// cursor to the tab stop following its current location. If there are no -// more tabs in this row, it will take it to the right side of the window. -// If it's already in the last column of the row, it will move it to the next line. -// Parameters: -// - sNumTabs - The number of tabs to perform. -// Return value: -// - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. -[[nodiscard]] NTSTATUS DoSrvPrivateForwardTab(const SHORT sNumTabs) -{ - return DoPrivateTabHelper(sNumTabs, true); -} - -// Routine Description: -// - A private API call for performing a backwards tab. This will take the -// cursor to the tab stop previous to its current location. It will not reverse line feed. -// Parameters: -// - sNumTabs - The number of tabs to perform. -// Return value: -// - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. -[[nodiscard]] NTSTATUS DoSrvPrivateBackwardsTab(const SHORT sNumTabs) -{ - return DoPrivateTabHelper(sNumTabs, false); -} - -// Routine Description: -// - A private API call for clearing the VT tabs that have been set. -// Parameters: -// - fClearAll - If false, only clears the tab in the current column (if it exists) -// otherwise clears all set tabs. (and reverts to legacy 8-char tabs behavior.) -// Return value: -// - None -void DoSrvPrivateTabClear(const bool fClearAll) -{ - CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - SCREEN_INFORMATION& screenBuffer = gci.GetActiveOutputBuffer().GetActiveBuffer(); - if (fClearAll) - { - screenBuffer.ClearTabStops(); - } - else - { - const COORD cursorPos = screenBuffer.GetTextBuffer().GetCursor().GetPosition(); - screenBuffer.ClearTabStop(cursorPos.X); - } -} - // Routine Description: // - A private API call for enabling VT200 style mouse mode. // Parameters: @@ -2080,13 +1980,6 @@ void DoSrvIsConsolePty(bool& isPty) isPty = gci.IsInVtIoMode(); } -// Routine Description: -// - a private API call for setting the default tab stops in the active screen buffer. -void DoSrvPrivateSetDefaultTabStops() -{ - ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetActiveBuffer().SetDefaultVtTabStops(); -} - // Routine Description: // - internal logic for adding or removing lines in the active screen buffer // this also moves the cursor to the left margin, which is expected behavior for IL and DL diff --git a/src/host/getset.h b/src/host/getset.h index 3106c0af300..f84eee084db 100644 --- a/src/host/getset.h +++ b/src/host/getset.h @@ -42,11 +42,6 @@ void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool [[nodiscard]] NTSTATUS DoSrvPrivateUseAlternateScreenBuffer(SCREEN_INFORMATION& screenInfo); void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo); -[[nodiscard]] NTSTATUS DoSrvPrivateHorizontalTabSet(); -[[nodiscard]] NTSTATUS DoSrvPrivateForwardTab(const SHORT sNumTabs); -[[nodiscard]] NTSTATUS DoSrvPrivateBackwardsTab(const SHORT sNumTabs); -void DoSrvPrivateTabClear(const bool fClearAll); - void DoSrvPrivateEnableVT200MouseMode(const bool fEnable); void DoSrvPrivateEnableUTF8ExtendedMouseMode(const bool fEnable); void DoSrvPrivateEnableSGRExtendedMouseMode(const bool fEnable); @@ -84,7 +79,6 @@ void DoSrvGetConsoleOutputCodePage(unsigned int& codepage); void DoSrvIsConsolePty(bool& isPty); -void DoSrvPrivateSetDefaultTabStops(); void DoSrvPrivateDeleteLines(const size_t count); void DoSrvPrivateInsertLines(const size_t count); diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index dfac1d27f46..2b50c5ce24b 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -491,80 +491,6 @@ bool ConhostInternalGetSet::PrivateUseMainScreenBuffer() return true; } -// - Connects the PrivateHorizontalTabSet call directly into our Driver Message servicing call inside Conhost.exe -// PrivateHorizontalTabSet is an internal-only "API" call that the vt commands can execute, -// but it is not represented as a function call on out public API surface. -// Arguments: -// -// Return Value: -// - true if successful (see PrivateHorizontalTabSet). false otherwise. -bool ConhostInternalGetSet::PrivateHorizontalTabSet() -{ - return NT_SUCCESS(DoSrvPrivateHorizontalTabSet()); -} - -// Routine Description: -// - Connects the PrivateForwardTab call directly into our Driver Message servicing call inside Conhost.exe -// PrivateForwardTab is an internal-only "API" call that the vt commands can execute, -// but it is not represented as a function call on out public API surface. -// Arguments: -// - sNumTabs - the number of tabs to execute -// Return Value: -// - true if successful (see PrivateForwardTab). false otherwise. -bool ConhostInternalGetSet::PrivateForwardTab(const size_t numTabs) -{ - SHORT tabs; - if (FAILED(SizeTToShort(numTabs, &tabs))) - { - return false; - } - - return NT_SUCCESS(DoSrvPrivateForwardTab(tabs)); -} - -// Routine Description: -// - Connects the PrivateBackwardsTab call directly into our Driver Message servicing call inside Conhost.exe -// PrivateBackwardsTab is an internal-only "API" call that the vt commands can execute, -// but it is not represented as a function call on out public API surface. -// Arguments: -// - numTabs - the number of tabs to execute -// Return Value: -// - true if successful (see PrivateBackwardsTab). false otherwise. -bool ConhostInternalGetSet::PrivateBackwardsTab(const size_t numTabs) -{ - SHORT tabs; - if (FAILED(SizeTToShort(numTabs, &tabs))) - { - return false; - } - - return NT_SUCCESS(DoSrvPrivateBackwardsTab(tabs)); -} - -// Routine Description: -// - Connects the PrivateTabClear call directly into our Driver Message servicing call inside Conhost.exe -// PrivateTabClear is an internal-only "API" call that the vt commands can execute, -// but it is not represented as a function call on out public API surface. -// Arguments: -// - clearAll - set to true to enable blinking, false to disable -// Return Value: -// - true if successful (see PrivateTabClear). false otherwise. -bool ConhostInternalGetSet::PrivateTabClear(const bool clearAll) -{ - DoSrvPrivateTabClear(clearAll); - return true; -} - -// Routine Description: -// - Connects the PrivateSetDefaultTabStops call directly into the private api point -// Return Value: -// - true -bool ConhostInternalGetSet::PrivateSetDefaultTabStops() -{ - DoSrvPrivateSetDefaultTabStops(); - return true; -} - // Routine Description: // - Connects the PrivateEnableVT200MouseMode call directly into our Driver Message servicing call inside Conhost.exe // PrivateEnableVT200MouseMode is an internal-only "API" call that the vt commands can execute, diff --git a/src/host/outputStream.hpp b/src/host/outputStream.hpp index 7544041213a..ea900d83bd1 100644 --- a/src/host/outputStream.hpp +++ b/src/host/outputStream.hpp @@ -113,12 +113,6 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal:: bool PrivateUseMainScreenBuffer() override; - bool PrivateHorizontalTabSet(); - bool PrivateForwardTab(const size_t numTabs) override; - bool PrivateBackwardsTab(const size_t numTabs) override; - bool PrivateTabClear(const bool clearAll) override; - bool PrivateSetDefaultTabStops() override; - bool PrivateEnableVT200MouseMode(const bool enabled) override; bool PrivateEnableUTF8ExtendedMouseMode(const bool enabled) override; bool PrivateEnableSGRExtendedMouseMode(const bool enabled) override; diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index ba1de0e99e0..18942c5a27c 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -55,7 +55,6 @@ SCREEN_INFORMATION::SCREEN_INFORMATION( _rcAltSavedClientOld{ 0 }, _fAltWindowChanged{ false }, _PopupAttributes{ popupAttributes }, - _tabStops{}, _virtualBottom{ 0 }, _renderTarget{ *this }, _currentFont{ fontInfo }, @@ -127,16 +126,6 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION() const NTSTATUS status = pScreen->_InitializeOutputStateMachine(); - if (pScreen->_IsInVTMode()) - { - // microsoft/terminal#411: If VT mode is enabled, lets construct the - // VT tab stops. Without this line, if a user has - // VirtualTerminalLevel set, then - // SetConsoleMode(ENABLE_VIRTUAL_TERMINAL_PROCESSING) won't set our - // tab stops, because we're never going from vt off -> on - pScreen->SetDefaultVtTabStops(); - } - if (NT_SUCCESS(status)) { *ppScreen = pScreen; @@ -1839,9 +1828,6 @@ const SCREEN_INFORMATION& SCREEN_INFORMATION::GetMainBuffer() const // Set up the new buffers references to our current state machine, dispatcher, getset, etc. createdBuffer->_stateMachine = _stateMachine; - - // Setup the alt buffer's tabs stops with the default tab stop settings - createdBuffer->SetDefaultVtTabStops(); } return Status; } @@ -1964,130 +1950,6 @@ bool SCREEN_INFORMATION::_IsInVTMode() const return WI_IsFlagSet(OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING); } -// Routine Description: -// - Sets a VT tab stop in the column sColumn. If there is already a tab there, it does nothing. -// Parameters: -// - sColumn: the column to add a tab stop to. -// Return value: -// - none -// Note: may throw exception on allocation error -void SCREEN_INFORMATION::AddTabStop(const SHORT sColumn) -{ - if (std::find(_tabStops.begin(), _tabStops.end(), sColumn) == _tabStops.end()) - { - _tabStops.push_back(sColumn); - _tabStops.sort(); - } -} - -// Routine Description: -// - Clears all of the VT tabs that have been set. This also deletes them. -// Parameters: -// -// Return value: -// -void SCREEN_INFORMATION::ClearTabStops() noexcept -{ - _tabStops.clear(); -} - -// Routine Description: -// - Clears the VT tab in the column sColumn (if one has been set). Also deletes it from the heap. -// Parameters: -// - sColumn - The column to clear the tab stop for. -// Return value: -// -void SCREEN_INFORMATION::ClearTabStop(const SHORT sColumn) noexcept -{ - _tabStops.remove(sColumn); -} - -// Routine Description: -// - Places the location that a forwards tab would take cCurrCursorPos to into pcNewCursorPos -// Parameters: -// - cCurrCursorPos - The initial cursor location -// Return value: -// - -COORD SCREEN_INFORMATION::GetForwardTab(const COORD cCurrCursorPos) const noexcept -{ - COORD cNewCursorPos = cCurrCursorPos; - SHORT sWidth = GetBufferSize().RightInclusive(); - if (_tabStops.empty() || cCurrCursorPos.X >= _tabStops.back()) - { - cNewCursorPos.X = sWidth; - } - else - { - // search for next tab stop - for (auto it = _tabStops.cbegin(); it != _tabStops.cend(); ++it) - { - if (*it > cCurrCursorPos.X) - { - // make sure we don't exceed the width of the buffer - cNewCursorPos.X = std::min(*it, sWidth); - break; - } - } - } - return cNewCursorPos; -} - -// Routine Description: -// - Places the location that a backwards tab would take cCurrCursorPos to into pcNewCursorPos -// Parameters: -// - cCurrCursorPos - The initial cursor location -// Return value: -// - -COORD SCREEN_INFORMATION::GetReverseTab(const COORD cCurrCursorPos) const noexcept -{ - COORD cNewCursorPos = cCurrCursorPos; - // if we're at 0, or there are NO tabs, or the first tab is farther right than where we are - if (cCurrCursorPos.X == 0 || _tabStops.empty() || _tabStops.front() >= cCurrCursorPos.X) - { - cNewCursorPos.X = 0; - } - else - { - for (auto it = _tabStops.crbegin(); it != _tabStops.crend(); ++it) - { - if (*it < cCurrCursorPos.X) - { - cNewCursorPos.X = *it; - break; - } - } - } - return cNewCursorPos; -} - -// Routine Description: -// - Returns true if any VT-style tab stops have been set (with AddTabStop) -// Parameters: -// -// Return value: -// - true if any VT-style tab stops have been set -bool SCREEN_INFORMATION::AreTabsSet() const noexcept -{ - return !_tabStops.empty(); -} - -// Routine Description: -// - adds default tab stops for vt mode -void SCREEN_INFORMATION::SetDefaultVtTabStops() -{ - _tabStops.clear(); - const int width = GetBufferSize().RightInclusive(); - FAIL_FAST_IF(width < 0); - for (int pos = 0; pos <= width; pos += TAB_SIZE) - { - _tabStops.push_back(gsl::narrow(pos)); - } - if (_tabStops.back() != width) - { - _tabStops.push_back(gsl::narrow(width)); - } -} - // Routine Description: // - Returns the value of the attributes // Parameters: diff --git a/src/host/screenInfo.hpp b/src/host/screenInfo.hpp index 4750aa4857c..0f6f6f958b3 100644 --- a/src/host/screenInfo.hpp +++ b/src/host/screenInfo.hpp @@ -213,14 +213,6 @@ class SCREEN_INFORMATION : public ConsoleObjectHeader, public Microsoft::Console SCREEN_INFORMATION& GetActiveBuffer(); const SCREEN_INFORMATION& GetActiveBuffer() const; - void AddTabStop(const SHORT sColumn); - void ClearTabStops() noexcept; - void ClearTabStop(const SHORT sColumn) noexcept; - COORD GetForwardTab(const COORD cCurrCursorPos) const noexcept; - COORD GetReverseTab(const COORD cCurrCursorPos) const noexcept; - bool AreTabsSet() const noexcept; - void SetDefaultVtTabStops(); - TextAttribute GetAttributes() const; const TextAttribute* const GetPopupAttributes() const; @@ -296,8 +288,6 @@ class SCREEN_INFORMATION : public ConsoleObjectHeader, public Microsoft::Console RECT _rcAltSavedClientOld; bool _fAltWindowChanged; - std::list _tabStops; - TextAttribute _PopupAttributes; FontInfo _currentFont; diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 956dfc0af8c..eb475258ce0 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -69,6 +69,9 @@ class ScreenBufferTests // Make sure a test hasn't left us in the alt buffer on accident VERIFY_IS_FALSE(currentBuffer._IsAltBuffer()); VERIFY_SUCCEEDED(currentBuffer.SetViewportOrigin(true, { 0, 0 }, true)); + // Make sure the viewport always starts off at the default size. + auto defaultSize = COORD{ CommonState::s_csWindowWidth, CommonState::s_csWindowHeight }; + currentBuffer.SetViewport(Viewport::FromDimensions(defaultSize), true); VERIFY_ARE_EQUAL(COORD({ 0, 0 }), currentBuffer.GetTextBuffer().GetCursor().GetPosition()); return true; @@ -89,9 +92,9 @@ class ScreenBufferTests TEST_METHOD(TestReverseLineFeed); - TEST_METHOD(TestAddTabStop); + TEST_METHOD(TestResetClearTabStops); - TEST_METHOD(TestClearTabStops); + TEST_METHOD(TestAddTabStop); TEST_METHOD(TestClearTabStop); @@ -99,9 +102,7 @@ class ScreenBufferTests TEST_METHOD(TestGetReverseTab); - TEST_METHOD(TestAreTabsSet); - - TEST_METHOD(TestAltBufferDefaultTabStops); + TEST_METHOD(TestAltBufferTabStops); TEST_METHOD(EraseAllTests); @@ -194,8 +195,6 @@ class ScreenBufferTests TEST_METHOD(ClearAlternateBuffer); - TEST_METHOD(InitializeTabStopsInVTMode); - TEST_METHOD(TestExtendedTextAttributes); TEST_METHOD(TestExtendedTextAttributesWithColors); @@ -417,147 +416,229 @@ void ScreenBufferTests::TestReverseLineFeed() VERIFY_ARE_EQUAL(c.Y, 6); } +void _SetTabStops(SCREEN_INFORMATION& screenInfo, std::list columns, bool replace) +{ + auto& stateMachine = screenInfo.GetStateMachine(); + auto& cursor = screenInfo.GetTextBuffer().GetCursor(); + const auto clearTabStops = L"\033[3g"; + const auto addTabStop = L"\033H"; + + if (replace) + { + stateMachine.ProcessString(clearTabStops); + } + + for (auto column : columns) + { + cursor.SetXPosition(column); + stateMachine.ProcessString(addTabStop); + } +} + +std::list _GetTabStops(SCREEN_INFORMATION& screenInfo) +{ + std::list columns; + + const auto lastColumn = screenInfo.GetBufferSize().RightInclusive(); + auto& stateMachine = screenInfo.GetStateMachine(); + auto& cursor = screenInfo.GetTextBuffer().GetCursor(); + + cursor.SetPosition({ 0, 0 }); + for (;;) + { + stateMachine.ProcessCharacter(L'\t'); + auto column = cursor.GetPosition().X; + if (column >= lastColumn) + { + break; + } + columns.push_back(column); + } + + return columns; +} + +void ScreenBufferTests::TestResetClearTabStops() +{ + // Reset the screen buffer to test the defaults. + m_state->CleanupGlobalScreenBuffer(); + m_state->PrepareGlobalScreenBuffer(); + + CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer(); + auto& stateMachine = screenInfo.GetStateMachine(); + + const auto clearTabStops = L"\033[3g"; + const auto resetToInitialState = L"\033c"; + + Log::Comment(L"Default tabs every 8 columns."); + std::list expectedStops{ 8, 16, 24, 32, 40, 48, 56, 64, 72 }; + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); + + Log::Comment(L"Clear all tabs."); + stateMachine.ProcessString(clearTabStops); + expectedStops = {}; + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); + + Log::Comment(L"RIS resets tabs to defaults."); + stateMachine.ProcessString(resetToInitialState); + expectedStops = { 8, 16, 24, 32, 40, 48, 56, 64, 72 }; + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); +} + void ScreenBufferTests::TestAddTabStop() { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer(); - screenInfo.ClearTabStops(); - auto scopeExit = wil::scope_exit([&]() { screenInfo.ClearTabStops(); }); + auto& stateMachine = screenInfo.GetStateMachine(); + auto& cursor = screenInfo.GetTextBuffer().GetCursor(); + + const auto clearTabStops = L"\033[3g"; + const auto addTabStop = L"\033H"; + + Log::Comment(L"Clear all tabs."); + stateMachine.ProcessString(clearTabStops); + std::list expectedStops{}; + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); - std::list expectedStops{ 12 }; Log::Comment(L"Add tab to empty list."); - screenInfo.AddTabStop(12); - VERIFY_ARE_EQUAL(expectedStops, screenInfo._tabStops); + cursor.SetXPosition(12); + stateMachine.ProcessString(addTabStop); + expectedStops.push_back(12); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); Log::Comment(L"Add tab to head of existing list."); - screenInfo.AddTabStop(4); + cursor.SetXPosition(4); + stateMachine.ProcessString(addTabStop); expectedStops.push_front(4); - VERIFY_ARE_EQUAL(expectedStops, screenInfo._tabStops); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); Log::Comment(L"Add tab to tail of existing list."); - screenInfo.AddTabStop(30); + cursor.SetXPosition(30); + stateMachine.ProcessString(addTabStop); expectedStops.push_back(30); - VERIFY_ARE_EQUAL(expectedStops, screenInfo._tabStops); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); Log::Comment(L"Add tab to middle of existing list."); - screenInfo.AddTabStop(24); + cursor.SetXPosition(24); + stateMachine.ProcessString(addTabStop); expectedStops.push_back(24); expectedStops.sort(); - VERIFY_ARE_EQUAL(expectedStops, screenInfo._tabStops); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); Log::Comment(L"Add tab that duplicates an item in the existing list."); - screenInfo.AddTabStop(24); - VERIFY_ARE_EQUAL(expectedStops, screenInfo._tabStops); + cursor.SetXPosition(24); + stateMachine.ProcessString(addTabStop); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(screenInfo)); } -void ScreenBufferTests::TestClearTabStops() +void ScreenBufferTests::TestClearTabStop() { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer(); + auto& stateMachine = screenInfo.GetStateMachine(); + auto& cursor = screenInfo.GetTextBuffer().GetCursor(); - Log::Comment(L"Clear nonexistent tab stops."); - { - screenInfo.ClearTabStops(); - VERIFY_IS_TRUE(screenInfo._tabStops.empty()); - } + const auto clearTabStops = L"\033[3g"; + const auto clearTabStop = L"\033[0g"; + const auto addTabStop = L"\033H"; - Log::Comment(L"Clear handful of tab stops."); + Log::Comment(L"Start with all tabs cleared."); { - for (auto x : { 3, 6, 13, 2, 25 }) - { - screenInfo.AddTabStop(gsl::narrow(x)); - } - VERIFY_IS_FALSE(screenInfo._tabStops.empty()); - screenInfo.ClearTabStops(); - VERIFY_IS_TRUE(screenInfo._tabStops.empty()); - } -} + stateMachine.ProcessString(clearTabStops); -void ScreenBufferTests::TestClearTabStop() -{ - CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer(); + VERIFY_IS_TRUE(_GetTabStops(screenInfo).empty()); + } Log::Comment(L"Try to clear nonexistent list."); { - screenInfo.ClearTabStop(0); + cursor.SetXPosition(0); + stateMachine.ProcessString(clearTabStop); - VERIFY_IS_TRUE(screenInfo._tabStops.empty(), L"List should remain empty"); + VERIFY_IS_TRUE(_GetTabStops(screenInfo).empty(), L"List should remain empty"); } Log::Comment(L"Allocate 1 list item and clear it."); { - screenInfo._tabStops.push_back(0); - screenInfo.ClearTabStop(0); + cursor.SetXPosition(0); + stateMachine.ProcessString(addTabStop); + stateMachine.ProcessString(clearTabStop); - VERIFY_IS_TRUE(screenInfo._tabStops.empty()); + VERIFY_IS_TRUE(_GetTabStops(screenInfo).empty()); } Log::Comment(L"Allocate 1 list item and clear nonexistent."); { - screenInfo._tabStops.push_back(0); + cursor.SetXPosition(1); + stateMachine.ProcessString(addTabStop); Log::Comment(L"Free greater"); - screenInfo.ClearTabStop(1); - VERIFY_IS_FALSE(screenInfo._tabStops.empty()); + cursor.SetXPosition(2); + stateMachine.ProcessString(clearTabStop); + VERIFY_IS_FALSE(_GetTabStops(screenInfo).empty()); Log::Comment(L"Free less than"); - screenInfo.ClearTabStop(-1); - VERIFY_IS_FALSE(screenInfo._tabStops.empty()); + cursor.SetXPosition(0); + stateMachine.ProcessString(clearTabStop); + VERIFY_IS_FALSE(_GetTabStops(screenInfo).empty()); // clear all tab stops - screenInfo._tabStops.clear(); + stateMachine.ProcessString(clearTabStops); } Log::Comment(L"Allocate many (5) list items and clear head."); { std::list inputData = { 3, 5, 6, 10, 15, 17 }; - screenInfo._tabStops = inputData; - screenInfo.ClearTabStop(inputData.front()); + _SetTabStops(screenInfo, inputData, false); + cursor.SetXPosition(inputData.front()); + stateMachine.ProcessString(clearTabStop); inputData.pop_front(); - VERIFY_ARE_EQUAL(inputData, screenInfo._tabStops); + VERIFY_ARE_EQUAL(inputData, _GetTabStops(screenInfo)); // clear all tab stops - screenInfo._tabStops.clear(); + stateMachine.ProcessString(clearTabStops); } Log::Comment(L"Allocate many (5) list items and clear middle."); { std::list inputData = { 3, 5, 6, 10, 15, 17 }; - screenInfo._tabStops = inputData; - screenInfo.ClearTabStop(*std::next(inputData.begin())); + _SetTabStops(screenInfo, inputData, false); + cursor.SetXPosition(*std::next(inputData.begin())); + stateMachine.ProcessString(clearTabStop); inputData.erase(std::next(inputData.begin())); - VERIFY_ARE_EQUAL(inputData, screenInfo._tabStops); + VERIFY_ARE_EQUAL(inputData, _GetTabStops(screenInfo)); // clear all tab stops - screenInfo._tabStops.clear(); + stateMachine.ProcessString(clearTabStops); } Log::Comment(L"Allocate many (5) list items and clear tail."); { std::list inputData = { 3, 5, 6, 10, 15, 17 }; - screenInfo._tabStops = inputData; - screenInfo.ClearTabStop(inputData.back()); + _SetTabStops(screenInfo, inputData, false); + cursor.SetXPosition(inputData.back()); + stateMachine.ProcessString(clearTabStop); inputData.pop_back(); - VERIFY_ARE_EQUAL(inputData, screenInfo._tabStops); + VERIFY_ARE_EQUAL(inputData, _GetTabStops(screenInfo)); // clear all tab stops - screenInfo._tabStops.clear(); + stateMachine.ProcessString(clearTabStops); } Log::Comment(L"Allocate many (5) list items and clear nonexistent item."); { std::list inputData = { 3, 5, 6, 10, 15, 17 }; - screenInfo._tabStops = inputData; - screenInfo.ClearTabStop(9000); + _SetTabStops(screenInfo, inputData, false); + cursor.SetXPosition(0); + stateMachine.ProcessString(clearTabStop); - VERIFY_ARE_EQUAL(inputData, screenInfo._tabStops); + VERIFY_ARE_EQUAL(inputData, _GetTabStops(screenInfo)); // clear all tab stops - screenInfo._tabStops.clear(); + stateMachine.ProcessString(clearTabStops); } } @@ -565,23 +646,25 @@ void ScreenBufferTests::TestGetForwardTab() { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); SCREEN_INFORMATION& si = gci.GetActiveOutputBuffer(); + auto& stateMachine = si.GetStateMachine(); + auto& cursor = si.GetTextBuffer().GetCursor(); + + const auto nextForwardTab = L"\033[I"; std::list inputData = { 3, 5, 6, 10, 15, 17 }; - si._tabStops = inputData; + _SetTabStops(si, inputData, true); const COORD coordScreenBufferSize = si.GetBufferSize().Dimensions(); - COORD coordCursor; - coordCursor.Y = coordScreenBufferSize.Y / 2; // in the middle of the buffer, it doesn't make a difference. Log::Comment(L"Find next tab from before front."); { - coordCursor.X = 0; + cursor.SetXPosition(0); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = inputData.front(); - COORD const coordCursorResult = si.GetForwardTab(coordCursor); + stateMachine.ProcessString(nextForwardTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor advanced to first tab stop from sample list."); @@ -589,13 +672,13 @@ void ScreenBufferTests::TestGetForwardTab() Log::Comment(L"Find next tab from in the middle."); { - coordCursor.X = 6; + cursor.SetXPosition(6); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = *std::next(inputData.begin(), 3); - COORD const coordCursorResult = si.GetForwardTab(coordCursor); + stateMachine.ProcessString(nextForwardTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor advanced to middle tab stop from sample list."); @@ -603,13 +686,13 @@ void ScreenBufferTests::TestGetForwardTab() Log::Comment(L"Find next tab from end."); { - coordCursor.X = 30; + cursor.SetXPosition(30); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = coordScreenBufferSize.X - 1; - COORD const coordCursorResult = si.GetForwardTab(coordCursor); + stateMachine.ProcessString(nextForwardTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor advanced to end of screen buffer."); @@ -617,41 +700,39 @@ void ScreenBufferTests::TestGetForwardTab() Log::Comment(L"Find next tab from rightmost column."); { - coordCursor.X = coordScreenBufferSize.X - 1; + cursor.SetXPosition(coordScreenBufferSize.X - 1); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); - COORD const coordCursorResult = si.GetForwardTab(coordCursor); + stateMachine.ProcessString(nextForwardTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor remains in rightmost column."); } - - si._tabStops.clear(); } void ScreenBufferTests::TestGetReverseTab() { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); SCREEN_INFORMATION& si = gci.GetActiveOutputBuffer(); + auto& stateMachine = si.GetStateMachine(); + auto& cursor = si.GetTextBuffer().GetCursor(); - std::list inputData = { 3, 5, 6, 10, 15, 17 }; - si._tabStops = inputData; + const auto nextReverseTab = L"\033[Z"; - COORD coordCursor; - // in the middle of the buffer, it doesn't make a difference. - coordCursor.Y = si.GetBufferSize().Height() / 2; + std::list inputData = { 3, 5, 6, 10, 15, 17 }; + _SetTabStops(si, inputData, true); Log::Comment(L"Find previous tab from before front."); { - coordCursor.X = 1; + cursor.SetXPosition(1); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = 0; - COORD const coordCursorResult = si.GetReverseTab(coordCursor); + stateMachine.ProcessString(nextReverseTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor adjusted to beginning of the buffer when it started before sample list."); @@ -659,13 +740,13 @@ void ScreenBufferTests::TestGetReverseTab() Log::Comment(L"Find previous tab from in the middle."); { - coordCursor.X = 6; + cursor.SetXPosition(6); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = *std::next(inputData.begin()); - COORD const coordCursorResult = si.GetReverseTab(coordCursor); + stateMachine.ProcessString(nextReverseTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor adjusted back one tab spot from middle of sample list."); @@ -673,34 +754,20 @@ void ScreenBufferTests::TestGetReverseTab() Log::Comment(L"Find next tab from end."); { - coordCursor.X = 30; + cursor.SetXPosition(30); - COORD coordCursorExpected; - coordCursorExpected = coordCursor; + COORD coordCursorExpected = cursor.GetPosition(); coordCursorExpected.X = inputData.back(); - COORD const coordCursorResult = si.GetReverseTab(coordCursor); + stateMachine.ProcessString(nextReverseTab); + COORD const coordCursorResult = cursor.GetPosition(); VERIFY_ARE_EQUAL(coordCursorExpected, coordCursorResult, L"Cursor adjusted to last item in the sample list from position beyond end."); } - - si._tabStops.clear(); -} - -void ScreenBufferTests::TestAreTabsSet() -{ - CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - SCREEN_INFORMATION& si = gci.GetActiveOutputBuffer(); - - si._tabStops.clear(); - VERIFY_IS_FALSE(si.AreTabsSet()); - - si.AddTabStop(1); - VERIFY_IS_TRUE(si.AreTabsSet()); } -void ScreenBufferTests::TestAltBufferDefaultTabStops() +void ScreenBufferTests::TestAltBufferTabStops() { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); gci.LockConsole(); // Lock must be taken to swap buffers. @@ -711,8 +778,10 @@ void ScreenBufferTests::TestAltBufferDefaultTabStops() WI_SetFlag(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING); VERIFY_IS_TRUE(WI_IsFlagSet(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)); - mainBuffer.SetDefaultVtTabStops(); - VERIFY_IS_TRUE(mainBuffer.AreTabsSet()); + Log::Comment(L"Add an initial set of tab in the main buffer."); + std::list expectedStops = { 3, 5, 6, 10, 15, 17 }; + _SetTabStops(mainBuffer, expectedStops, true); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(mainBuffer)); VERIFY_SUCCEEDED(mainBuffer.UseAlternateScreenBuffer()); SCREEN_INFORMATION& altBuffer = gci.GetActiveOutputBuffer(); @@ -724,39 +793,19 @@ void ScreenBufferTests::TestAltBufferDefaultTabStops() WI_SetFlag(altBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING); VERIFY_IS_TRUE(WI_IsFlagSet(altBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)); - VERIFY_IS_TRUE(altBuffer.AreTabsSet()); - VERIFY_IS_TRUE(altBuffer._tabStops.size() > 3); - const COORD origin{ 0, 0 }; - auto& cursor = altBuffer.GetTextBuffer().GetCursor(); - cursor.SetPosition(origin); - auto& stateMachine = altBuffer.GetStateMachine(); + Log::Comment(L"Make sure the tabs are still set in the alt buffer."); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(altBuffer)); - Log::Comment(NoThrowString().Format( - L"Tab a few times - make sure the cursor is where we expect.")); - - stateMachine.ProcessString(L"\t"); - COORD expected{ 8, 0 }; - VERIFY_ARE_EQUAL(expected, cursor.GetPosition()); - - stateMachine.ProcessString(L"\t"); - expected = { 16, 0 }; - VERIFY_ARE_EQUAL(expected, cursor.GetPosition()); - - stateMachine.ProcessString(L"\n"); - expected = { 0, 1 }; - VERIFY_ARE_EQUAL(expected, cursor.GetPosition()); - - altBuffer.ClearTabStops(); - VERIFY_IS_FALSE(altBuffer.AreTabsSet()); - stateMachine.ProcessString(L"\t"); - expected = { altBuffer.GetBufferSize().Width() - 1, 1 }; - - VERIFY_ARE_EQUAL(expected, cursor.GetPosition()); + Log::Comment(L"Add a new set of tabs in the alt buffer."); + expectedStops = { 4, 8, 12, 16 }; + _SetTabStops(altBuffer, expectedStops, true); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(altBuffer)); + Log::Comment(L"Make sure the tabs are still set in the main buffer."); useMain.release(); altBuffer.UseMainScreenBuffer(); - VERIFY_IS_TRUE(mainBuffer.AreTabsSet()); + VERIFY_ARE_EQUAL(expectedStops, _GetTabStops(mainBuffer)); } void ScreenBufferTests::EraseAllTests() @@ -4938,34 +4987,6 @@ void ScreenBufferTests::ClearAlternateBuffer() VerifyText(siMain.GetTextBuffer()); } -void ScreenBufferTests::InitializeTabStopsInVTMode() -{ - // This is a test for microsoft/terminal#411. Refer to that issue for more - // context. - - // Run this test in isolation - Let's not pollute the VT level for other - // tests, or go blowing away other test's buffers - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method") - END_TEST_METHOD_PROPERTIES() - - auto& g = ServiceLocator::LocateGlobals(); - auto& gci = g.getConsoleInformation(); - - VERIFY_IS_FALSE(gci.GetActiveOutputBuffer().AreTabsSet()); - - // Enable VT mode before we construct the buffer. This emulates setting the - // VirtualTerminalLevel reg key before launching the console. - gci.SetVirtTermLevel(1); - - // Clean up the old buffer, and re-create it. This new buffer will be - // created as if the VT mode was always on. - m_state->CleanupGlobalScreenBuffer(); - m_state->PrepareGlobalScreenBuffer(); - - VERIFY_IS_TRUE(gci.GetActiveOutputBuffer().AreTabsSet()); -} - void ScreenBufferTests::TestExtendedTextAttributes() { // This is a test for microsoft/terminal#2554. Refer to that issue for more diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index de859d96634..6c8bfba7cb0 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -1362,7 +1362,18 @@ bool AdaptDispatch::UseMainScreenBuffer() // True if handled successfully. False otherwise. bool AdaptDispatch::HorizontalTabSet() { - return _pConApi->PrivateHorizontalTabSet(); + CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 }; + csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + const bool success = _pConApi->GetConsoleScreenBufferInfoEx(csbiex); + if (success) + { + const auto width = csbiex.dwSize.X; + const auto column = csbiex.dwCursorPosition.X; + + _InitTabStopsForWidth(width); + _tabStopColumns.at(column) = true; + } + return success; } //Routine Description: @@ -1376,7 +1387,29 @@ bool AdaptDispatch::HorizontalTabSet() // True if handled successfully. False otherwise. bool AdaptDispatch::ForwardTab(const size_t numTabs) { - return _pConApi->PrivateForwardTab(numTabs); + CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 }; + csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + bool success = _pConApi->GetConsoleScreenBufferInfoEx(csbiex); + if (success) + { + const auto width = csbiex.dwSize.X; + const auto row = csbiex.dwCursorPosition.Y; + auto column = csbiex.dwCursorPosition.X; + auto tabsPerformed = 0u; + + _InitTabStopsForWidth(width); + while (column + 1 < width && tabsPerformed < numTabs) + { + column++; + if (til::at(_tabStopColumns, column)) + { + tabsPerformed++; + } + } + + success = _pConApi->SetConsoleCursorPosition({ column, row }); + } + return success; } //Routine Description: @@ -1388,7 +1421,29 @@ bool AdaptDispatch::ForwardTab(const size_t numTabs) // True if handled successfully. False otherwise. bool AdaptDispatch::BackwardsTab(const size_t numTabs) { - return _pConApi->PrivateBackwardsTab(numTabs); + CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 }; + csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + bool success = _pConApi->GetConsoleScreenBufferInfoEx(csbiex); + if (success) + { + const auto width = csbiex.dwSize.X; + const auto row = csbiex.dwCursorPosition.Y; + auto column = csbiex.dwCursorPosition.X; + auto tabsPerformed = 0u; + + _InitTabStopsForWidth(width); + while (column > 0 && tabsPerformed < numTabs) + { + column--; + if (til::at(_tabStopColumns, column)) + { + tabsPerformed++; + } + } + + success = _pConApi->SetConsoleCursorPosition({ column, row }); + } + return success; } //Routine Description: @@ -1405,15 +1460,91 @@ bool AdaptDispatch::TabClear(const size_t clearType) switch (clearType) { case DispatchTypes::TabClearType::ClearCurrentColumn: - success = _pConApi->PrivateTabClear(false); + success = _ClearSingleTabStop(); break; case DispatchTypes::TabClearType::ClearAllColumns: - success = _pConApi->PrivateTabClear(true); + success = _ClearAllTabStops(); break; } return success; } +// Routine Description: +// - Clears the tab stop in the cursor's current column, if there is one. +// Arguments: +// - +// Return value: +// - True if handled successfully. False otherwise. +bool AdaptDispatch::_ClearSingleTabStop() +{ + CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 }; + csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + const bool success = _pConApi->GetConsoleScreenBufferInfoEx(csbiex); + if (success) + { + const auto width = csbiex.dwSize.X; + const auto column = csbiex.dwCursorPosition.X; + + _InitTabStopsForWidth(width); + _tabStopColumns.at(column) = false; + } + return success; +} + +// Routine Description: +// - Clears all tab stops and resets the _initDefaultTabStops flag to indicate +// that they shouldn't be reinitialized at the default positions. +// Arguments: +// - +// Return value: +// - True if handled successfully. False otherwise. +bool AdaptDispatch::_ClearAllTabStops() noexcept +{ + _tabStopColumns.clear(); + _initDefaultTabStops = false; + return true; +} + +// Routine Description: +// - Clears all tab stops and sets the _initDefaultTabStops flag to indicate +// that the default positions should be reinitialized when needed. +// Arguments: +// - +// Return value: +// - +void AdaptDispatch::_ResetTabStops() noexcept +{ + _tabStopColumns.clear(); + _initDefaultTabStops = true; +} + +// Routine Description: +// - Resizes the _tabStopColumns table so it's large enough to support the +// current screen width, initializing tab stops every 8 columns in the +// newly allocated space, iff the _initDefaultTabStops flag is set. +// Arguments: +// - width - the width of the screen buffer that we need to accomodate +// Return value: +// - +void AdaptDispatch::_InitTabStopsForWidth(const size_t width) +{ + const auto initialWidth = _tabStopColumns.size(); + if (width > initialWidth) + { + _tabStopColumns.resize(width); + if (_initDefaultTabStops) + { + for (auto column = 8u; column < _tabStopColumns.size(); column += 8) + { + if (column >= initialWidth) + { + til::at(_tabStopColumns, column) = true; + } + } + } + } +} + //Routine Description: // Designate Charset - Sets the active charset to be the one mapped to wch. // See DispatchTypes::VTCharacterSets for a list of supported charsets. @@ -1559,7 +1690,7 @@ bool AdaptDispatch::HardReset() } // delete all current tab stops and reapply - _pConApi->PrivateSetDefaultTabStops(); + _ResetTabStops(); // GH#2715 - If all this succeeded, but we're in a conpty, return `false` to // make the state machine propagate this RIS sequence to the connected diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index aa67e373180..259c14940f5 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -152,6 +152,14 @@ namespace Microsoft::Console::VirtualTerminal bool _PrivateModeParamsHelper(const DispatchTypes::PrivateModeParams param, const bool enable); bool _DoDECCOLMHelper(const size_t columns); + bool _ClearSingleTabStop(); + bool _ClearAllTabStops() noexcept; + void _ResetTabStops() noexcept; + void _InitTabStopsForWidth(const size_t width); + + std::vector _tabStopColumns; + bool _initDefaultTabStops = true; + std::unique_ptr _pConApi; std::unique_ptr _pDefaults; TerminalOutput _termOutput; diff --git a/src/terminal/adapter/conGetSet.hpp b/src/terminal/adapter/conGetSet.hpp index 6516db3881a..229bb74bf59 100644 --- a/src/terminal/adapter/conGetSet.hpp +++ b/src/terminal/adapter/conGetSet.hpp @@ -74,11 +74,6 @@ namespace Microsoft::Console::VirtualTerminal virtual bool SetConsoleTitleW(const std::wstring_view title) = 0; virtual bool PrivateUseAlternateScreenBuffer() = 0; virtual bool PrivateUseMainScreenBuffer() = 0; - virtual bool PrivateHorizontalTabSet() = 0; - virtual bool PrivateForwardTab(const size_t numTabs) = 0; - virtual bool PrivateBackwardsTab(const size_t numTabs) = 0; - virtual bool PrivateTabClear(const bool clearAll) = 0; - virtual bool PrivateSetDefaultTabStops() = 0; virtual bool PrivateEnableVT200MouseMode(const bool enabled) = 0; virtual bool PrivateEnableUTF8ExtendedMouseMode(const bool enabled) = 0; diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index 761cdfe53b1..a513dd41908 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -445,49 +445,6 @@ class TestGetSet final : public ConGetSet return true; } - bool PrivateHorizontalTabSet() override - { - Log::Comment(L"PrivateHorizontalTabSet MOCK called..."); - // We made it through the adapter, woo! Return true. - return TRUE; - } - - bool PrivateForwardTab(const size_t numTabs) override - { - Log::Comment(L"PrivateForwardTab MOCK called..."); - if (_privateForwardTabResult) - { - VERIFY_ARE_EQUAL(_expectedNumTabs, numTabs); - } - return TRUE; - } - - bool PrivateBackwardsTab(const size_t numTabs) override - { - Log::Comment(L"PrivateBackwardsTab MOCK called..."); - if (_privateBackwardsTabResult) - { - VERIFY_ARE_EQUAL(_expectedNumTabs, numTabs); - } - return TRUE; - } - - bool PrivateTabClear(const bool clearAll) override - { - Log::Comment(L"PrivateTabClear MOCK called..."); - if (_privateTabClearResult) - { - VERIFY_ARE_EQUAL(_expectedClearAll, clearAll); - } - return TRUE; - } - - bool PrivateSetDefaultTabStops() override - { - Log::Comment(L"PrivateSetDefaultTabStops MOCK called..."); - return TRUE; - } - bool PrivateEnableVT200MouseMode(const bool enabled) override { Log::Comment(L"PrivateEnableVT200MouseMode MOCK called..."); @@ -924,12 +881,6 @@ class TestGetSet final : public ConGetSet bool _setConsoleTitleWResult = false; std::wstring_view _expectedWindowTitle{}; - bool _privateHorizontalTabSetResult = false; - bool _privateForwardTabResult = false; - bool _privateBackwardsTabResult = false; - size_t _expectedNumTabs = 0; - bool _privateTabClearResult = false; - bool _expectedClearAll = false; bool _expectedMouseEnabled = false; bool _expectedAlternateScrollEnabled = false; bool _privateEnableVT200MouseModeResult = false; @@ -2051,29 +2002,6 @@ class AdapterTest VERIFY_IS_TRUE(_pDispatch.get()->LineFeed(DispatchTypes::LineFeedType::DependsOnMode)); } - TEST_METHOD(TabSetClearTests) - { - Log::Comment(L"Starting test..."); - - _testGetSet->_privateHorizontalTabSetResult = TRUE; - VERIFY_IS_TRUE(_pDispatch.get()->HorizontalTabSet()); - - _testGetSet->_expectedNumTabs = 16; - - _testGetSet->_privateForwardTabResult = TRUE; - VERIFY_IS_TRUE(_pDispatch.get()->ForwardTab(16)); - - _testGetSet->_privateBackwardsTabResult = TRUE; - VERIFY_IS_TRUE(_pDispatch.get()->BackwardsTab(16)); - - _testGetSet->_privateTabClearResult = TRUE; - _testGetSet->_expectedClearAll = true; - VERIFY_IS_TRUE(_pDispatch.get()->TabClear(DispatchTypes::TabClearType::ClearAllColumns)); - - _testGetSet->_expectedClearAll = false; - VERIFY_IS_TRUE(_pDispatch.get()->TabClear(DispatchTypes::TabClearType::ClearCurrentColumn)); - } - TEST_METHOD(SetConsoleTitleTest) { Log::Comment(L"Starting test...");