Skip to content

Commit

Permalink
Add support for the Presentation State reports (#14998)
Browse files Browse the repository at this point in the history
This PR introduces two new sequences, `DECRQPSR` and `DECRSPS`, which
provide a way for applications to query and restore the presentation
state reports. This includes the tab stop report (`DECTABSR`) and the
cursor information report (`DECCIR`). 

One part of the cursor information report contains the character set
designations and mapped G-sets. But we weren't tracking that data in a
way that could easily be reported, so I needed to do some refactoring in
the `TerminalOutput` class to make that accessible.

Other than that, the rest was fairly straightforward. It was just a
matter of packaging up all the information into the correct format for
the returned `DCS` string, and in the case of the restore operations,
parsing the incoming data and applying the new state. 

## Validation Steps Performed

Thanks to @al20878, we were able to test these operations on a real
VT525, and I've manually verified that our implementation matches that
behavior. I've also added some unit tests covering both reports.

Closes #14984
  • Loading branch information
j4james authored Mar 23, 2023
1 parent 7a2e4f8 commit 0f7d1f4
Show file tree
Hide file tree
Showing 13 changed files with 661 additions and 24 deletions.
7 changes: 7 additions & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ aabbcc
ABANDONFONT
abbcc
ABCDEFGHIJKLMNOPQRSTUVWXY
ABCF
abgr
abi
ABORTIFHUNG
Expand Down Expand Up @@ -407,6 +408,7 @@ DECAUPSS
DECAWM
DECBKM
DECCARA
DECCIR
DECCKM
DECCKSR
DECCOLM
Expand Down Expand Up @@ -438,8 +440,10 @@ DECRLM
DECRPM
DECRQCRA
DECRQM
DECRQPSR
DECRQSS
DECRQTSR
DECRSPS
decrst
DECSACE
DECSASD
Expand All @@ -460,6 +464,7 @@ DECSTBM
DECSTGLT
DECSTR
DECSWL
DECTABSR
DECTCEM
DECXCPR
DEFAPP
Expand Down Expand Up @@ -809,6 +814,8 @@ hkl
HKLM
hlocal
hlsl
HMB
HMK
hmod
hmodule
hmon
Expand Down
36 changes: 27 additions & 9 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ namespace Microsoft::Console::VirtualTerminal
{
using VTInt = int32_t;

class VTID
union VTID
{
public:
VTID() = default;

template<size_t Length>
constexpr VTID(const char (&s)[Length]) :
_value{ _FromString(s) }
{
}

constexpr VTID(const uint64_t value) :
_value{ value }
_value{ value & 0x00FFFFFFFFFFFFFF }
{
}

Expand All @@ -26,6 +28,11 @@ namespace Microsoft::Console::VirtualTerminal
return _value;
}

constexpr const std::string_view ToString() const
{
return &_string[0];
}

constexpr char operator[](const size_t offset) const
{
return SubSequence(offset)._value & 0xFF;
Expand All @@ -40,7 +47,7 @@ namespace Microsoft::Console::VirtualTerminal
template<size_t Length>
static constexpr uint64_t _FromString(const char (&s)[Length])
{
static_assert(Length - 1 <= sizeof(_value));
static_assert(Length <= sizeof(_value));
uint64_t value = 0;
for (auto i = Length - 1; i-- > 0;)
{
Expand All @@ -49,7 +56,12 @@ namespace Microsoft::Console::VirtualTerminal
return value;
}

uint64_t _value;
// In order for the _string to hold the correct representation of the
// ID stored in _value, we must be on a little endian architecture.
static_assert(std::endian::native == std::endian::little);

uint64_t _value = 0;
char _string[sizeof(_value)];
};

class VTIDBuilder
Expand All @@ -63,13 +75,13 @@ namespace Microsoft::Console::VirtualTerminal

void AddIntermediate(const wchar_t intermediateChar) noexcept
{
if (_idShift + CHAR_BIT >= sizeof(_idAccumulator) * CHAR_BIT)
if (_idShift + CHAR_BIT * 2 >= sizeof(_idAccumulator) * CHAR_BIT)
{
// If there is not enough space in the accumulator to add
// the intermediate and still have room left for the final,
// then we reset the accumulator to zero. This will result
// in an id with all zero intermediates, which shouldn't
// match anything.
// the intermediate and still have room left for the final
// and null terminator, then we reset the accumulator to zero.
// This will result in an id with all zero intermediates,
// which shouldn't match anything.
_idAccumulator = 0;
}
else
Expand Down Expand Up @@ -539,6 +551,12 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
ColorTableReport = 2
};

enum class PresentationReportFormat : VTInt
{
CursorInformationReport = 1,
TabulationStopReport = 2
};

constexpr VTInt s_sDECCOLMSetColumns = 132;
constexpr VTInt s_sDECCOLMResetColumns = 80;

Expand Down
3 changes: 3 additions & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch

virtual StringHandler RequestSetting() = 0; // DECRQSS

virtual bool RequestPresentationStateReport(const DispatchTypes::PresentationReportFormat format) = 0; // DECRQPSR
virtual StringHandler RestorePresentationState(const DispatchTypes::PresentationReportFormat format) = 0; // DECRSPS

virtual bool PlaySounds(const VTParameters parameters) = 0; // DECPS
};
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() = default;
Expand Down
Loading

0 comments on commit 0f7d1f4

Please sign in to comment.