Skip to content

Commit 9fd6037

Browse files
committed
PRE-MERGE #15084 Add support for horizontal margin sequences
2 parents 89385e4 + 1e641c4 commit 9fd6037

13 files changed

+1025
-351
lines changed

.github/actions/spelling/expect/alphabet.txt

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ABCDEFGHIJ
99
abcdefghijk
1010
ABCDEFGHIJKLMNO
1111
abcdefghijklmnop
12+
ABCDEFGHIJKLMNOPQRS
1213
ABCDEFGHIJKLMNOPQRST
1314
ABCG
1415
ABE
@@ -21,9 +22,12 @@ BBGGRR
2122
efg
2223
EFG
2324
EFGh
25+
KLMNOQQQQQQQQQQ
2426
QQQQQQQQQQABCDEFGHIJ
27+
QQQQQQQQQQABCDEFGHIJKLMNOPQRS
2528
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
2629
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
30+
QQQQQQQQQQABCDEFGHIJPQRST
2731
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
2832
qrstuvwxyz
2933
qwerty

src/host/ut_host/ScreenBufferTests.cpp

+646-259
Large diffs are not rendered by default.

src/terminal/adapter/DispatchTypes.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
430430
XTERM_EnableDECCOLMSupport = DECPrivateMode(40),
431431
DECNKM_NumericKeypadMode = DECPrivateMode(66),
432432
DECBKM_BackarrowKeyMode = DECPrivateMode(67),
433+
DECLRMM_LeftRightMarginMode = DECPrivateMode(69),
433434
VT200_MOUSE_MODE = DECPrivateMode(1000),
434435
BUTTON_EVENT_MOUSE_MODE = DECPrivateMode(1002),
435436
ANY_EVENT_MOUSE_MODE = DECPrivateMode(1003),

src/terminal/adapter/ITermDispatch.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
5454
virtual bool SetKeypadMode(const bool applicationMode) = 0; // DECKPAM, DECKPNM
5555
virtual bool SetAnsiMode(const bool ansiMode) = 0; // DECANM
5656
virtual bool SetTopBottomScrollingMargins(const VTInt topMargin, const VTInt bottomMargin) = 0; // DECSTBM
57+
virtual bool SetLeftRightScrollingMargins(const VTInt leftMargin, const VTInt rightMargin) = 0; // DECSLRM
5758
virtual bool WarningBell() = 0; // BEL
5859
virtual bool CarriageReturn() = 0; // CR
5960
virtual bool LineFeed(const DispatchTypes::LineFeedType lineFeedType) = 0; // IND, NEL, LF, FF, VT

src/terminal/adapter/adaptDispatch.cpp

+329-74
Large diffs are not rendered by default.

src/terminal/adapter/adaptDispatch.hpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ namespace Microsoft::Console::VirtualTerminal
9090
bool SetAnsiMode(const bool ansiMode) override; // DECANM
9191
bool SetTopBottomScrollingMargins(const VTInt topMargin,
9292
const VTInt bottomMargin) override; // DECSTBM
93+
bool SetLeftRightScrollingMargins(const VTInt leftMargin,
94+
const VTInt rightMargin) override; // DECSLRM
9395
bool WarningBell() override; // BEL
9496
bool CarriageReturn() override; // CR
9597
bool LineFeed(const DispatchTypes::LineFeedType lineFeedType) override; // IND, NEL, LF, FF, VT
@@ -163,6 +165,7 @@ namespace Microsoft::Console::VirtualTerminal
163165
Origin,
164166
Column,
165167
AllowDECCOLM,
168+
AllowDECSLRM,
166169
RectangularChangeExtent
167170
};
168171
enum class ScrollDirection
@@ -201,6 +204,7 @@ namespace Microsoft::Console::VirtualTerminal
201204

202205
void _WriteToBuffer(const std::wstring_view string);
203206
std::pair<int, int> _GetVerticalMargins(const til::rect& viewport, const bool absolute) noexcept;
207+
std::pair<int, int> _GetHorizontalMargins(const til::CoordType bufferWidth) noexcept;
204208
bool _CursorMovePosition(const Offset rowOffset, const Offset colOffset, const bool clampInMargins);
205209
void _ApplyCursorMovementFlags(Cursor& cursor) noexcept;
206210
void _FillRect(TextBuffer& textBuffer, const til::rect& fillRect, const wchar_t fillChar, const TextAttribute fillAttrs);
@@ -217,7 +221,12 @@ namespace Microsoft::Console::VirtualTerminal
217221
void _ScrollMovement(const VTInt delta);
218222

219223
void _DoSetTopBottomScrollingMargins(const VTInt topMargin,
220-
const VTInt bottomMargin);
224+
const VTInt bottomMargin,
225+
const bool homeCursor = false);
226+
void _DoSetLeftRightScrollingMargins(const VTInt leftMargin,
227+
const VTInt rightMargin,
228+
const bool homeCursor = false);
229+
221230
void _DoLineFeed(TextBuffer& textBuffer, const bool withReturn, const bool wrapForced);
222231

223232
void _OperatingStatus() const;
@@ -239,6 +248,7 @@ namespace Microsoft::Console::VirtualTerminal
239248

240249
void _ReportSGRSetting() const;
241250
void _ReportDECSTBMSetting();
251+
void _ReportDECSLRMSetting();
242252
void _ReportDECSCASetting() const;
243253
void _ReportDECSACESetting() const;
244254
void _ReportDECACSetting(const VTInt itemNumber) const;

src/terminal/adapter/termDispatch.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons
4747
bool SetKeypadMode(const bool /*applicationMode*/) override { return false; } // DECKPAM, DECKPNM
4848
bool SetAnsiMode(const bool /*ansiMode*/) override { return false; } // DECANM
4949
bool SetTopBottomScrollingMargins(const VTInt /*topMargin*/, const VTInt /*bottomMargin*/) override { return false; } // DECSTBM
50+
bool SetLeftRightScrollingMargins(const VTInt /*leftMargin*/, const VTInt /*rightMargin*/) override { return false; } // DECSLRM
5051
bool WarningBell() override { return false; } // BEL
5152
bool CarriageReturn() override { return false; } // CR
5253
bool LineFeed(const DispatchTypes::LineFeedType /*lineFeedType*/) override { return false; } // IND, NEL, LF, FF, VT

src/terminal/adapter/ut_adapter/adapterTest.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,22 @@ class AdapterTest
16291629
requestSetting(L"r");
16301630
_testGetSet->ValidateInputEvent(L"\033P1$r1;25r\033\\");
16311631

1632+
Log::Comment(L"Requesting DECSLRM margins (5 to 10).");
1633+
_testGetSet->PrepData();
1634+
// We need to enable DECLRMM for horizontal margins to work.
1635+
_pDispatch->SetMode(DispatchTypes::DECLRMM_LeftRightMarginMode);
1636+
_pDispatch->SetLeftRightScrollingMargins(5, 10);
1637+
requestSetting(L"s");
1638+
_testGetSet->ValidateInputEvent(L"\033P1$r5;10s\033\\");
1639+
1640+
Log::Comment(L"Requesting DECSLRM margins (full width).");
1641+
_testGetSet->PrepData();
1642+
_pDispatch->SetLeftRightScrollingMargins(0, 0);
1643+
requestSetting(L"s");
1644+
_testGetSet->ValidateInputEvent(L"\033P1$r1;100s\033\\");
1645+
// Reset DECLRMM once we're done with horizontal margin testing.
1646+
_pDispatch->ResetMode(DispatchTypes::DECLRMM_LeftRightMarginMode);
1647+
16321648
Log::Comment(L"Requesting SGR attributes (default).");
16331649
_testGetSet->PrepData();
16341650
TextAttribute attribute = {};
@@ -1763,7 +1779,7 @@ class AdapterTest
17631779
// and DECRQM would not then be applicable.
17641780

17651781
BEGIN_TEST_METHOD_PROPERTIES()
1766-
TEST_METHOD_PROPERTY(L"Data:modeNumber", L"{1, 3, 5, 6, 8, 12, 25, 40, 66, 67, 1000, 1002, 1003, 1004, 1005, 1006, 1007, 1049, 9001}")
1782+
TEST_METHOD_PROPERTY(L"Data:modeNumber", L"{1, 3, 5, 6, 8, 12, 25, 40, 66, 67, 69, 1000, 1002, 1003, 1004, 1005, 1006, 1007, 1049, 9001}")
17671783
END_TEST_METHOD_PROPERTIES()
17681784

17691785
VTInt modeNumber;

src/terminal/parser/OutputStateMachineEngine.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,15 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParamete
491491
success = _dispatch->CursorPosition(parameters.at(0), parameters.at(1));
492492
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUP);
493493
break;
494-
case CsiActionCodes::DECSTBM_SetScrollingRegion:
494+
case CsiActionCodes::DECSTBM_SetTopBottomMargins:
495495
success = _dispatch->SetTopBottomScrollingMargins(parameters.at(0).value_or(0), parameters.at(1).value_or(0));
496496
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSTBM);
497497
break;
498+
case CsiActionCodes::DECSLRM_SetLeftRightMargins:
499+
// Note that this can also be ANSISYSSC, depending on the state of DECLRMM.
500+
success = _dispatch->SetLeftRightScrollingMargins(parameters.at(0).value_or(0), parameters.at(1).value_or(0));
501+
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSTBM);
502+
break;
498503
case CsiActionCodes::ICH_InsertCharacter:
499504
success = _dispatch->InsertCharacter(parameters.at(0));
500505
TermTelemetry::Instance().Log(TermTelemetry::Codes::ICH);
@@ -588,12 +593,8 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParamete
588593
success = _dispatch->ScrollDown(parameters.at(0));
589594
TermTelemetry::Instance().Log(TermTelemetry::Codes::SD);
590595
break;
591-
case CsiActionCodes::ANSISYSSC_CursorSave:
592-
success = parameters.empty() && _dispatch->CursorSaveState();
593-
TermTelemetry::Instance().Log(TermTelemetry::Codes::ANSISYSSC);
594-
break;
595596
case CsiActionCodes::ANSISYSRC_CursorRestore:
596-
success = parameters.empty() && _dispatch->CursorRestoreState();
597+
success = _dispatch->CursorRestoreState();
597598
TermTelemetry::Instance().Log(TermTelemetry::Codes::ANSISYSRC);
598599
break;
599600
case CsiActionCodes::IL_InsertLine:

src/terminal/parser/OutputStateMachineEngine.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ namespace Microsoft::Console::VirtualTerminal
137137
SGR_SetGraphicsRendition = VTID("m"),
138138
DSR_DeviceStatusReport = VTID("n"),
139139
DSR_PrivateDeviceStatusReport = VTID("?n"),
140-
DECSTBM_SetScrollingRegion = VTID("r"),
141-
ANSISYSSC_CursorSave = VTID("s"), // NOTE: Overlaps with DECLRMM/DECSLRM. Fix when/if implemented.
140+
DECSTBM_SetTopBottomMargins = VTID("r"),
141+
DECSLRM_SetLeftRightMargins = VTID("s"),
142142
DTTERM_WindowManipulation = VTID("t"), // NOTE: Overlaps with DECSLPP. Fix when/if implemented.
143143
ANSISYSRC_CursorRestore = VTID("u"),
144144
DECREQTPARM_RequestTerminalParameters = VTID("x"),

src/terminal/parser/telemetry.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ void TermTelemetry::WriteFinalTraceLog() const
241241
TraceLoggingUInt32(_uiTimesUsed[DL], "DL"),
242242
TraceLoggingUInt32(_uiTimesUsed[SU], "SU"),
243243
TraceLoggingUInt32(_uiTimesUsed[SD], "SD"),
244-
TraceLoggingUInt32(_uiTimesUsed[ANSISYSSC], "ANSISYSSC"),
245244
TraceLoggingUInt32(_uiTimesUsed[ANSISYSRC], "ANSISYSRC"),
246245
TraceLoggingUInt32(_uiTimesUsed[DECSTBM], "DECSTBM"),
246+
TraceLoggingUInt32(_uiTimesUsed[DECSLRM], "DECSLRM"),
247247
TraceLoggingUInt32(_uiTimesUsed[NEL], "NEL"),
248248
TraceLoggingUInt32(_uiTimesUsed[IND], "IND"),
249249
TraceLoggingUInt32(_uiTimesUsed[RI], "RI"),

src/terminal/parser/telemetry.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ namespace Microsoft::Console::VirtualTerminal
6666
DCH,
6767
SU,
6868
SD,
69-
ANSISYSSC,
7069
ANSISYSRC,
7170
IL,
7271
DL,
7372
DECSTBM,
73+
DECSLRM,
7474
NEL,
7575
IND,
7676
RI,

src/terminal/parser/ut_parser/OutputEngineTest.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -1657,12 +1657,10 @@ class StateMachineExternalTest final
16571657

16581658
pDispatch->ClearState();
16591659

1660-
mach.ProcessCharacter(AsciiChars::ESC);
1661-
mach.ProcessCharacter(L'[');
1662-
mach.ProcessCharacter(L's');
1663-
VERIFY_IS_TRUE(pDispatch->_cursorSave);
1664-
1665-
pDispatch->ClearState();
1660+
// Note that CSI s is dispatched as SetLeftRightScrollingMargins rather
1661+
// than CursorSaveState, so we don't test that here. The CursorSaveState
1662+
// will only be triggered by this sequence (in AdaptDispatch) when the
1663+
// Left-Right-Margin mode (DECLRMM) is disabled.
16661664

16671665
mach.ProcessCharacter(AsciiChars::ESC);
16681666
mach.ProcessCharacter(L'[');

0 commit comments

Comments
 (0)