Skip to content

Commit

Permalink
Add support for the DECST8C escape sequence (#16534)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request

This PR adds support for the `DECST8C` escape sequence, which resets the
tab stops to every 8 columns.

## Detailed Description of the Pull Request / Additional comments

This is actually a private parameter variant of the ANSI `CTC` sequence
(Cursor Tabulation Control), which accepts a selective parameter which
specifies the type of tab operation to be performed. But the DEC variant
only defines a single parameter value (5), which resets all tab stops.
It also considers an omitted parameter to be the equivalent of 5, so we
support that too.

## Validation Steps Performed

I've extended the existing tab stop tests in `ScreenBufferTests` with
some basic coverage of this sequence.

I've also manually verified that the `DECTABSR` script in #14984 now
passes the `DECST8C` portion of the test.

## PR Checklist
- [x] Closes #16533
- [x] Tests added/passed

(cherry picked from commit f589888)
Service-Card-Id: 91631721
Service-Version: 1.19
  • Loading branch information
j4james authored and DHowett committed Jan 25, 2024
1 parent bc452c6 commit ba6f1e9
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 9 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ DECSLPP
DECSLRM
DECSMKR
DECSR
DECST
DECSTBM
DECSTGLT
DECSTR
Expand Down
10 changes: 10 additions & 0 deletions src/host/ut_host/ScreenBufferTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
5 changes: 5 additions & 0 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,11 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
ClearAllColumns = 3
};

enum TabSetType : VTInt
{
SetEvery8Columns = 5
};

enum WindowManipulationType : VTInt
{
Invalid = 0,
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 14 additions & 7 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2822,16 +2822,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:
// - <none>
// - setType - only SetEvery8Columns is supported
// Return value:
// - <none>
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:
Expand Down Expand Up @@ -3105,7 +3112,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);
Expand Down
4 changes: 2 additions & 2 deletions src/terminal/adapter/adaptDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -251,7 +252,6 @@ namespace Microsoft::Console::VirtualTerminal

void _ClearSingleTabStop();
void _ClearAllTabStops() noexcept;
void _ResetTabStops() noexcept;
void _InitTabStopsForWidth(const VTInt width);

StringHandler _RestoreColorTable();
Expand All @@ -271,7 +271,7 @@ namespace Microsoft::Console::VirtualTerminal
StringHandler _CreateDrcsPassthroughHandler(const DispatchTypes::DrcsCharsetSize charsetSize);
StringHandler _CreatePassthroughHandler();

std::vector<bool> _tabStopColumns;
std::vector<uint8_t> _tabStopColumns;
bool _initDefaultTabStops = true;

ITerminalApi& _api;
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/termDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/terminal/parser/OutputStateMachineEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/terminal/parser/OutputStateMachineEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("`"),
Expand Down

0 comments on commit ba6f1e9

Please sign in to comment.