Add support for the DSR-OS operating status report (#5300)
This adds support for the VT escape sequence that requests the terminal's operating status. There is no attempt to actually verify the status of the app, though. We always return a response indicating a good operating condition (the same as most terminal emulators). ## PR Checklist * [x] CLA signed. * [x] Tests added/passed ## Detailed Description of the Pull Request / Additional comments This required an update to the `OutputStateMachineEngine` to accept the `DSR-OS` type, since it only dispatches types that it recognises (I think that's unnecessary, but that's an issue for another day). The actual processing of the request is handled in the `AdaptDispatch` class, where it simply responds with a hard coded sequence (`CSI 0 n`), indicating a good operating condition. ## Validation Steps Performed I've added unit tests to confirm that the request is dispatched correctly, and the appropriate response is returned. I've also manually confirmed that the test of the _Device Status Report_ in _Vttest_ is now succeeding. Closes #5052
This commit is contained in:
parent
7936605cc9
commit
2d09dfd48b
|
@ -75,6 +75,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
|
|||
|
||||
enum class AnsiStatusType : unsigned int
|
||||
{
|
||||
OS_OperatingStatus = 5,
|
||||
CPR_CursorPositionReport = 6,
|
||||
};
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
|
||||
virtual bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> params) = 0; // DECRST
|
||||
|
||||
virtual bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) = 0; // DSR, DSR-CPR
|
||||
virtual bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) = 0; // DSR, DSR-OS, DSR-CPR
|
||||
virtual bool DeviceAttributes() = 0; // DA1
|
||||
|
||||
virtual bool DesignateCharset(const wchar_t wchCharset) = 0; // SCS
|
||||
|
|
|
@ -685,6 +685,9 @@ bool AdaptDispatch::DeviceStatusReport(const DispatchTypes::AnsiStatusType statu
|
|||
|
||||
switch (statusType)
|
||||
{
|
||||
case DispatchTypes::AnsiStatusType::OS_OperatingStatus:
|
||||
success = _OperatingStatus();
|
||||
break;
|
||||
case DispatchTypes::AnsiStatusType::CPR_CursorPositionReport:
|
||||
success = _CursorPositionReport();
|
||||
break;
|
||||
|
@ -706,6 +709,18 @@ bool AdaptDispatch::DeviceAttributes()
|
|||
return _WriteResponse(L"\x1b[?1;0c");
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DSR-OS - Reports the operating status back to the input channel
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool AdaptDispatch::_OperatingStatus() const
|
||||
{
|
||||
// We always report a good operating condition.
|
||||
return _WriteResponse(L"\x1b[0n");
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DSR-CPR - Reports the current cursor position within the viewport back to the input channel
|
||||
// Arguments:
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
bool InsertCharacter(const size_t count) override; // ICH
|
||||
bool DeleteCharacter(const size_t count) override; // DCH
|
||||
bool SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> options) override; // SGR
|
||||
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) override; // DSR, DSR-CPR
|
||||
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) override; // DSR, DSR-OS, DSR-CPR
|
||||
bool DeviceAttributes() override; // DA1
|
||||
bool ScrollUp(const size_t distance) override; // SU
|
||||
bool ScrollDown(const size_t distance) override; // SD
|
||||
|
@ -145,6 +145,7 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
|
||||
bool _DoSetTopBottomScrollingMargins(const size_t topMargin,
|
||||
const size_t bottomMargin);
|
||||
bool _OperatingStatus() const;
|
||||
bool _CursorPositionReport() const;
|
||||
|
||||
bool _WriteResponse(const std::wstring_view reply) const;
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
|
||||
bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> /*params*/) noexcept override { return false; } // DECRST
|
||||
|
||||
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) noexcept override { return false; } // DSR, DSR-CPR
|
||||
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) noexcept override { return false; } // DSR, DSR-OS, DSR-CPR
|
||||
bool DeviceAttributes() noexcept override { return false; } // DA1
|
||||
|
||||
bool DesignateCharset(const wchar_t /*wchCharset*/) noexcept override { return false; } // SCS
|
||||
|
|
|
@ -1778,6 +1778,17 @@ public:
|
|||
VERIFY_IS_FALSE(_pDispatch.get()->DeviceStatusReport((DispatchTypes::AnsiStatusType)-1));
|
||||
}
|
||||
|
||||
TEST_METHOD(DeviceStatus_OperatingStatusTests)
|
||||
{
|
||||
Log::Comment(L"Starting test...");
|
||||
|
||||
Log::Comment(L"Test 1: Verify good operating condition.");
|
||||
_testGetSet->PrepData();
|
||||
VERIFY_IS_TRUE(_pDispatch.get()->DeviceStatusReport(DispatchTypes::AnsiStatusType::OS_OperatingStatus));
|
||||
|
||||
_testGetSet->ValidateInputEvent(L"\x1b[0n");
|
||||
}
|
||||
|
||||
TEST_METHOD(DeviceStatus_CursorPositionReportTests)
|
||||
{
|
||||
Log::Comment(L"Starting test...");
|
||||
|
|
|
@ -1113,6 +1113,10 @@ bool OutputStateMachineEngine::_GetDeviceStatusOperation(const std::basic_string
|
|||
switch (param)
|
||||
{
|
||||
// This looks kinda silly, but I want the parser to reject (success = false) any status types we haven't put here.
|
||||
case (unsigned short)DispatchTypes::AnsiStatusType::OS_OperatingStatus:
|
||||
statusType = DispatchTypes::AnsiStatusType::OS_OperatingStatus;
|
||||
success = true;
|
||||
break;
|
||||
case (unsigned short)DispatchTypes::AnsiStatusType::CPR_CursorPositionReport:
|
||||
statusType = DispatchTypes::AnsiStatusType::CPR_CursorPositionReport;
|
||||
success = true;
|
||||
|
|
|
@ -1745,7 +1745,18 @@ class StateMachineExternalTest final
|
|||
|
||||
pDispatch->ClearState();
|
||||
|
||||
Log::Comment(L"Test 2: Check CSR (cursor position command) case 6. Should succeed.");
|
||||
Log::Comment(L"Test 2: Check OS (operating status) case 5. Should succeed.");
|
||||
mach.ProcessCharacter(AsciiChars::ESC);
|
||||
mach.ProcessCharacter(L'[');
|
||||
mach.ProcessCharacter(L'5');
|
||||
mach.ProcessCharacter(L'n');
|
||||
|
||||
VERIFY_IS_TRUE(pDispatch->_deviceStatusReport);
|
||||
VERIFY_ARE_EQUAL(DispatchTypes::AnsiStatusType::OS_OperatingStatus, pDispatch->_statusReportType);
|
||||
|
||||
pDispatch->ClearState();
|
||||
|
||||
Log::Comment(L"Test 3: Check CPR (cursor position report) case 6. Should succeed.");
|
||||
mach.ProcessCharacter(AsciiChars::ESC);
|
||||
mach.ProcessCharacter(L'[');
|
||||
mach.ProcessCharacter(L'6');
|
||||
|
@ -1756,7 +1767,7 @@ class StateMachineExternalTest final
|
|||
|
||||
pDispatch->ClearState();
|
||||
|
||||
Log::Comment(L"Test 3: Check unimplemented case 1. Should fail.");
|
||||
Log::Comment(L"Test 4: Check unimplemented case 1. Should fail.");
|
||||
mach.ProcessCharacter(AsciiChars::ESC);
|
||||
mach.ProcessCharacter(L'[');
|
||||
mach.ProcessCharacter(L'1');
|
||||
|
|
Loading…
Reference in a new issue