Skip to content

Commit b2c0b5f

Browse files
Merge pull request #1797 from jquast/jq/bugfix-request-dec-mode
Bugfix DECRQM (Dec Request Mode) response
2 parents e12f0c7 + 6ce2956 commit b2c0b5f

File tree

8 files changed

+140
-153
lines changed

8 files changed

+140
-153
lines changed

.github/actions/spelling/allow/terminal-terms.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,5 @@ cuu
154154
dcl
155155
dcs
156156
fbterm
157+
stty
157158
zellij

metainfo.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
<li>Fixes double line box drawing characters</li>
131131
<li>Adds new arc style for box drawing characters</li>
132132
<li>Adds multiple rendering options for braille characters</li>
133+
<li>Bugfix DECRQM (Dec Request Mode) response (#1797)</li>
133134
</ul>
134135
</description>
135136
</release>

src/vtbackend/Screen.cpp

Lines changed: 11 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,28 +1754,26 @@ void Screen<Cell>::requestAnsiMode(unsigned int mode)
17541754
return ModeResponse::NotRecognized;
17551755
}(mode);
17561756

1757-
auto const code = toAnsiModeNum(static_cast<AnsiMode>(mode));
1758-
1759-
reply("\033[{};{}$y", code, static_cast<unsigned>(modeResponse));
1757+
reply("\033[{};{}$y", mode, static_cast<unsigned>(modeResponse));
17601758
}
17611759

17621760
template <CellConcept Cell>
17631761
void Screen<Cell>::requestDECMode(unsigned int mode)
17641762
{
1765-
auto const modeResponse = [&](auto mode) -> ModeResponse {
1766-
if (isValidDECMode(mode))
1763+
auto const modeResponse = [this, mode]() -> ModeResponse {
1764+
auto const modeEnum = fromDECModeNum(mode);
1765+
if (modeEnum.has_value())
17671766
{
1768-
if (_terminal->isModeEnabled(static_cast<DECMode>(mode)))
1767+
auto const modeEnum = fromDECModeNum(mode);
1768+
if (_terminal->isModeEnabled(modeEnum.value()))
17691769
return ModeResponse::Set;
17701770
else
17711771
return ModeResponse::Reset;
17721772
}
17731773
return ModeResponse::NotRecognized;
1774-
}(mode);
1775-
1776-
auto const code = toDECModeNum(static_cast<DECMode>(mode));
1774+
}();
17771775

1778-
reply("\033[?{};{}$y", code, static_cast<unsigned>(modeResponse));
1776+
reply("\033[?{};{}$y", mode, static_cast<unsigned>(modeResponse));
17791777
}
17801778

17811779
template <CellConcept Cell>
@@ -2391,67 +2389,9 @@ namespace impl
23912389
}
23922390
}
23932391

2394-
optional<DECMode> toDECMode(unsigned value)
2395-
{
2396-
switch (value)
2397-
{
2398-
case 1: return DECMode::UseApplicationCursorKeys;
2399-
case 2: return DECMode::DesignateCharsetUSASCII;
2400-
case 3: return DECMode::Columns132;
2401-
case 4: return DECMode::SmoothScroll;
2402-
case 5: return DECMode::ReverseVideo;
2403-
case 6: return DECMode::Origin;
2404-
case 7: return DECMode::AutoWrap;
2405-
// TODO: Ps = 8 -> Auto-repeat Keys (DECARM), VT100.
2406-
case 9: return DECMode::MouseProtocolX10;
2407-
case 10: return DECMode::ShowToolbar;
2408-
case 12: return DECMode::BlinkingCursor;
2409-
case 19: return DECMode::PrinterExtend;
2410-
case 25: return DECMode::VisibleCursor;
2411-
case 30: return DECMode::ShowScrollbar;
2412-
// TODO: Ps = 3 5 -> Enable font-shifting functions (rxvt).
2413-
// IGNORE? Ps = 3 8 -> Enter Tektronix Mode (DECTEK), VT240, xterm.
2414-
// TODO: Ps = 4 0 -> Allow 80 -> 132 Mode, xterm.
2415-
case 40: return DECMode::AllowColumns80to132;
2416-
// IGNORE: Ps = 4 1 -> more(1) fix (see curses resource).
2417-
// TODO: Ps = 4 2 -> Enable National Replacement Character sets (DECNRCM), VT220.
2418-
// TODO: Ps = 4 4 -> Turn On Margin Bell, xterm.
2419-
// TODO: Ps = 4 5 -> Reverse-wraparound Mode, xterm.
2420-
case 46: return DECMode::DebugLogging;
2421-
case 47: return DECMode::UseAlternateScreen;
2422-
// TODO: Ps = 6 6 -> Application keypad (DECNKM), VT320.
2423-
// TODO: Ps = 6 7 -> Backarrow key sends backspace (DECBKM), VT340, VT420. This sets the
2424-
// backarrowKey resource to "true".
2425-
case 69: return DECMode::LeftRightMargin;
2426-
case 80: return DECMode::NoSixelScrolling;
2427-
case 1000: return DECMode::MouseProtocolNormalTracking;
2428-
case 1001: return DECMode::MouseProtocolHighlightTracking;
2429-
case 1002: return DECMode::MouseProtocolButtonTracking;
2430-
case 1003: return DECMode::MouseProtocolAnyEventTracking;
2431-
case 1004: return DECMode::FocusTracking;
2432-
case 1005: return DECMode::MouseExtended;
2433-
case 1006: return DECMode::MouseSGR;
2434-
case 1007: return DECMode::MouseAlternateScroll;
2435-
case 1015: return DECMode::MouseURXVT;
2436-
case 1016: return DECMode::MouseSGRPixels;
2437-
case 1047: return DECMode::UseAlternateScreen;
2438-
case 1048: return DECMode::SaveCursor;
2439-
case 1049: return DECMode::ExtendedAltScreen;
2440-
case 2004: return DECMode::BracketedPaste;
2441-
case 2026: return DECMode::BatchedRendering;
2442-
case 2027: return DECMode::Unicode;
2443-
case 2028: return DECMode::TextReflow;
2444-
case 2029: return DECMode::MousePassiveTracking;
2445-
case 2030: return DECMode::ReportGridCellSelection;
2446-
case 2031: return DECMode::ReportColorPaletteUpdated;
2447-
case 8452: return DECMode::SixelCursorNextToGraphic;
2448-
default: return nullopt;
2449-
}
2450-
}
2451-
24522392
ApplyResult setModeDEC(Sequence const& seq, size_t modeIndex, bool enable, Terminal& term)
24532393
{
2454-
if (auto const modeOpt = toDECMode(seq.param(modeIndex)); modeOpt.has_value())
2394+
if (auto const modeOpt = fromDECModeNum(seq.param(modeIndex)); modeOpt.has_value())
24552395
{
24562396
term.setMode(modeOpt.value(), enable);
24572397
return ApplyResult::Ok;
@@ -3033,7 +2973,7 @@ namespace impl
30332973
{
30342974
vector<DECMode> modes;
30352975
for (size_t i = 0; i < seq.parameterCount(); ++i)
3036-
if (optional<DECMode> mode = toDECMode(seq.param(i)); mode.has_value())
2976+
if (optional<DECMode> mode = fromDECModeNum(seq.param(i)); mode.has_value())
30372977
modes.push_back(mode.value());
30382978
terminal.saveModes(modes);
30392979
return ApplyResult::Ok;
@@ -3043,7 +2983,7 @@ namespace impl
30432983
{
30442984
vector<DECMode> modes;
30452985
for (size_t i = 0; i < seq.parameterCount(); ++i)
3046-
if (optional<DECMode> mode = toDECMode(seq.param(i)); mode.has_value())
2986+
if (optional<DECMode> mode = fromDECModeNum(seq.param(i)); mode.has_value())
30472987
modes.push_back(mode.value());
30482988
terminal.restoreModes(modes);
30492989
return ApplyResult::Ok;

src/vtbackend/Screen_test.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,10 +1456,10 @@ TEST_CASE("DeleteCharacters", "[screen]")
14561456

14571457
SECTION("outside margin")
14581458
{
1459-
mock.terminal.setMode(DECMode::LeftRightMargin, true);
1460-
mock.terminal.setLeftRightMargin(ColumnOffset(1), ColumnOffset(3));
1461-
screen.moveCursorTo(LineOffset(0), ColumnOffset(0));
1462-
screen.deleteCharacters(ColumnCount(1));
1459+
mock.writeToScreen(DECSM(toDECModeNum(DECMode::LeftRightMargin)));
1460+
mock.writeToScreen(DECSLRM(2, 4));
1461+
mock.writeToScreen(CUP(1, 1));
1462+
mock.writeToScreen(DCH(1));
14631463
REQUIRE("12345\n67890\n" == screen.renderMainPageText());
14641464
}
14651465

@@ -2603,54 +2603,54 @@ TEST_CASE("ReportExtendedCursorPosition", "[screen]")
26032603
TEST_CASE("RequestMode", "[screen]")
26042604
{
26052605
auto mock = MockTerm { PageSize { LineCount(5), ColumnCount(5) } };
2606-
auto& screen = mock.terminal.primaryScreen();
2606+
2607+
constexpr auto AnsiInsertModeNum = toAnsiModeNum(AnsiMode::Insert);
26072608

26082609
SECTION("ANSI modes: enabled")
26092610
{
2610-
mock.terminal.setMode(AnsiMode::Insert, true); // IRM
2611-
screen.requestAnsiMode((unsigned) AnsiMode::Insert);
2611+
mock.writeToScreen(SM(AnsiInsertModeNum));
2612+
mock.writeToScreen(DECRQM_ANSI(AnsiInsertModeNum));
26122613
REQUIRE(e(mock.terminal.peekInput())
26132614
== e(std::format("\033[{};1$y", toAnsiModeNum(AnsiMode::Insert))));
26142615
}
26152616

26162617
SECTION("ANSI modes: disabled")
26172618
{
2618-
mock.terminal.setMode(AnsiMode::Insert, false); // IRM
2619-
screen.requestAnsiMode((unsigned) AnsiMode::Insert);
2620-
REQUIRE(e(mock.terminal.peekInput())
2621-
== e(std::format("\033[{};2$y", toAnsiModeNum(AnsiMode::Insert))));
2619+
mock.writeToScreen(RM(AnsiInsertModeNum));
2620+
mock.writeToScreen(DECRQM_ANSI(AnsiInsertModeNum));
2621+
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[{};2$y", AnsiInsertModeNum)));
26222622
}
26232623

26242624
SECTION("ANSI modes: unknown")
26252625
{
2626-
auto const m = static_cast<AnsiMode>(1234);
2627-
mock.terminal.setMode(m, true); // DECOM
2628-
screen.requestAnsiMode((unsigned) m);
2629-
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[{};0$y", toAnsiModeNum(m))));
2626+
auto const m = 1234u;
2627+
mock.writeToScreen(SM(m));
2628+
mock.writeToScreen(DECRQM_ANSI(m));
2629+
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[{};0$y", m)));
26302630
}
26312631

2632+
constexpr auto DecOriginModeNum = toDECModeNum(DECMode::Origin);
2633+
26322634
SECTION("DEC modes: enabled")
26332635
{
2634-
mock.terminal.setMode(DECMode::Origin, true); // DECOM
2635-
screen.requestDECMode((int) DECMode::Origin);
2636-
REQUIRE(e(mock.terminal.peekInput())
2637-
== e(std::format("\033[?{};1$y", toDECModeNum(DECMode::Origin))));
2636+
mock.writeToScreen(DECSM(DecOriginModeNum));
2637+
mock.writeToScreen(DECRQM(DecOriginModeNum));
2638+
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[?{};1$y", DecOriginModeNum)));
26382639
}
26392640

26402641
SECTION("DEC modes: disabled")
26412642
{
2642-
mock.terminal.setMode(DECMode::Origin, false); // DECOM
2643-
screen.requestDECMode((int) DECMode::Origin);
2644-
REQUIRE(e(mock.terminal.peekInput())
2645-
== e(std::format("\033[?{};2$y", toDECModeNum(DECMode::Origin))));
2643+
mock.writeToScreen(DECRM(DecOriginModeNum));
2644+
mock.writeToScreen(DECRQM(DecOriginModeNum));
2645+
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[?{};2$y", DecOriginModeNum)));
26462646
}
26472647

26482648
SECTION("DEC modes: unknown")
26492649
{
2650-
auto const m = static_cast<DECMode>(1234);
2651-
mock.terminal.setMode(m, true); // DECOM
2652-
screen.requestDECMode(static_cast<unsigned>(m));
2653-
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[?{};0$y", toDECModeNum(m))));
2650+
auto const m = std::numeric_limits<uint16_t>::max();
2651+
mock.writeToScreen(DECSM(m));
2652+
mock.writeToScreen(DECRQM(m));
2653+
REQUIRE(e(mock.terminal.peekInput()) == e(std::format("\033[?{};0$y", m)));
26542654
}
26552655
}
26562656

src/vtbackend/Terminal.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,12 +1622,6 @@ void Terminal::setMode(AnsiMode mode, bool enable)
16221622
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
16231623
void Terminal::setMode(DECMode mode, bool enable)
16241624
{
1625-
if (!isValidDECMode(static_cast<unsigned int>(mode)))
1626-
{
1627-
errorLog()("Attempt to {} invalid DEC mode: {}", mode, enable ? "set" : "reset");
1628-
return;
1629-
}
1630-
16311625
if (_modes.frozen(mode))
16321626
{
16331627
if (_modes.enabled(mode) != enable)

src/vtbackend/Terminal.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,11 @@ class Modes
8585

8686
[[nodiscard]] bool frozen(DECMode mode) const noexcept
8787
{
88-
assert(isValidDECMode(static_cast<unsigned int>(mode)));
8988
return _decFrozen.test(static_cast<size_t>(mode));
9089
}
9190

9291
void freeze(DECMode mode)
9392
{
94-
assert(isValidDECMode(static_cast<unsigned int>(mode)));
95-
9693
if (mode == DECMode::BatchedRendering)
9794
{
9895
errorLog()("Attempt to freeze batched rendering. Ignoring.");
@@ -105,7 +102,6 @@ class Modes
105102

106103
void unfreeze(DECMode mode)
107104
{
108-
assert(isValidDECMode(static_cast<unsigned int>(mode)));
109105
_decFrozen.set(static_cast<size_t>(mode), false);
110106
terminalLog()("Unfreezing permanently-{} DEC mode {}.", mode, enabled(mode));
111107
}

src/vtbackend/primitives.h

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <cstdint>
88
#include <limits>
9+
#include <optional>
910
#include <ostream>
1011
#include <string>
1112
#include <variant>
@@ -742,7 +743,7 @@ constexpr bool isValidAnsiMode(unsigned int mode) noexcept
742743
std::string to_string(AnsiMode mode);
743744
std::string to_string(DECMode mode);
744745

745-
constexpr unsigned toDECModeNum(DECMode m)
746+
constexpr unsigned toDECModeNum(DECMode m) noexcept
746747
{
747748
switch (m)
748749
{
@@ -789,53 +790,66 @@ constexpr unsigned toDECModeNum(DECMode m)
789790
return static_cast<unsigned>(m);
790791
}
791792

792-
constexpr bool isValidDECMode(unsigned int mode) noexcept
793+
constexpr std::optional<DECMode> fromDECModeNum(unsigned int modeNum) noexcept
793794
{
794-
switch (static_cast<DECMode>(mode))
795+
switch (modeNum)
795796
{
796-
case DECMode::UseApplicationCursorKeys:
797-
case DECMode::DesignateCharsetUSASCII:
798-
case DECMode::Columns132:
799-
case DECMode::SmoothScroll:
800-
case DECMode::ReverseVideo:
801-
case DECMode::MouseProtocolX10:
802-
case DECMode::MouseProtocolNormalTracking:
803-
case DECMode::MouseProtocolHighlightTracking:
804-
case DECMode::MouseProtocolButtonTracking:
805-
case DECMode::MouseProtocolAnyEventTracking:
806-
case DECMode::SaveCursor:
807-
case DECMode::ExtendedAltScreen:
808-
case DECMode::Origin:
809-
case DECMode::AutoWrap:
810-
case DECMode::PrinterExtend:
811-
case DECMode::LeftRightMargin:
812-
case DECMode::ShowToolbar:
813-
case DECMode::BlinkingCursor:
814-
case DECMode::VisibleCursor:
815-
case DECMode::ShowScrollbar:
816-
case DECMode::AllowColumns80to132:
817-
case DECMode::DebugLogging:
818-
case DECMode::UseAlternateScreen:
819-
case DECMode::BracketedPaste:
820-
case DECMode::FocusTracking:
821-
case DECMode::NoSixelScrolling:
822-
case DECMode::UsePrivateColorRegisters:
823-
case DECMode::MouseExtended:
824-
case DECMode::MouseSGR:
825-
case DECMode::MouseURXVT:
826-
case DECMode::MouseSGRPixels:
827-
case DECMode::MouseAlternateScroll:
828-
case DECMode::MousePassiveTracking:
829-
case DECMode::ReportGridCellSelection:
830-
case DECMode::ReportColorPaletteUpdated:
831-
case DECMode::BatchedRendering:
832-
case DECMode::Unicode:
833-
case DECMode::TextReflow:
834-
case DECMode::SixelCursorNextToGraphic:
835-
//.
836-
return true;
797+
case 1: return DECMode::UseApplicationCursorKeys;
798+
case 2: return DECMode::DesignateCharsetUSASCII;
799+
case 3: return DECMode::Columns132;
800+
case 4: return DECMode::SmoothScroll;
801+
case 5: return DECMode::ReverseVideo;
802+
case 6: return DECMode::Origin;
803+
case 7: return DECMode::AutoWrap;
804+
// TODO: Ps = 8 -> Auto-repeat Keys (DECARM), VT100.
805+
case 9: return DECMode::MouseProtocolX10;
806+
case 10: return DECMode::ShowToolbar;
807+
case 12: return DECMode::BlinkingCursor;
808+
case 19: return DECMode::PrinterExtend;
809+
case 25: return DECMode::VisibleCursor;
810+
case 30: return DECMode::ShowScrollbar;
811+
// TODO: Ps = 3 5 -> Enable font-shifting functions (rxvt).
812+
// IGNORE? Ps = 3 8 -> Enter Tektronix Mode (DECTEK), VT240, xterm.
813+
case 40: return DECMode::AllowColumns80to132;
814+
// IGNORE: Ps = 4 1 -> more(1) fix (see curses resource).
815+
// TODO: Ps = 4 2 -> Enable National Replacement Character sets (DECNRCM), VT220.
816+
// TODO: Ps = 4 4 -> Turn On Margin Bell, xterm.
817+
// TODO: Ps = 4 5 -> Reverse-wraparound Mode, xterm.
818+
case 46: return DECMode::DebugLogging;
819+
case 47: return DECMode::UseAlternateScreen;
820+
// TODO: Ps = 6 6 -> Application keypad (DECNKM), VT320.
821+
// TODO: Ps = 6 7 -> Backarrow key sends backspace (DECBKM), VT340, VT420. This sets the
822+
// backarrowKey resource to "true".
823+
case 69: return DECMode::LeftRightMargin;
824+
case 80: return DECMode::NoSixelScrolling;
825+
case 1000: return DECMode::MouseProtocolNormalTracking;
826+
case 1001: return DECMode::MouseProtocolHighlightTracking;
827+
case 1002: return DECMode::MouseProtocolButtonTracking;
828+
case 1003: return DECMode::MouseProtocolAnyEventTracking;
829+
case 1004: return DECMode::FocusTracking;
830+
case 1005: return DECMode::MouseExtended;
831+
case 1006: return DECMode::MouseSGR;
832+
case 1007: return DECMode::MouseAlternateScroll;
833+
case 1015: return DECMode::MouseURXVT;
834+
case 1016: return DECMode::MouseSGRPixels;
835+
case 1048: return DECMode::SaveCursor;
836+
case 1049: return DECMode::ExtendedAltScreen;
837+
case 1070: return DECMode::UsePrivateColorRegisters;
838+
case 2004: return DECMode::BracketedPaste;
839+
case 2026: return DECMode::BatchedRendering;
840+
case 2027: return DECMode::Unicode;
841+
case 2028: return DECMode::TextReflow;
842+
case 2029: return DECMode::MousePassiveTracking;
843+
case 2030: return DECMode::ReportGridCellSelection;
844+
case 2031: return DECMode::ReportColorPaletteUpdated;
845+
case 8452: return DECMode::SixelCursorNextToGraphic;
846+
default: return std::nullopt;
837847
}
838-
return false;
848+
}
849+
850+
constexpr bool isValidDECMode(unsigned int mode) noexcept
851+
{
852+
return fromDECModeNum(mode).has_value();
839853
}
840854

841855
constexpr DynamicColorName getChangeDynamicColorCommand(unsigned value)

0 commit comments

Comments
 (0)