Skip to content

Commit

Permalink
Implement XTPUSHSGR, XTPOPSGR
Browse files Browse the repository at this point in the history
This change adds a new pair of methods to ITermDispatch:
PushGraphicsRendition and PopGraphicsRendition, and then plumbs the
change through AdaptDispatch, TerminalDispatch, ITerminalApi and
TerminalApi.

The stack logic is encapsulated in the SgrStack class, to allow it to be
reused between the two APIs (AdaptDispatch and TerminalDispatch).

Like xterm, only ten levels of nesting are supported.

The stack is implemented as a "ring stack": if you push when the stack
is full, the bottom of the stack will be dropped to make room.
  • Loading branch information
jazzdelightsme committed Jul 17, 2020
1 parent 3a91fc0 commit afcf1d4
Show file tree
Hide file tree
Showing 23 changed files with 767 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .github/actions/spell-check/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2368,6 +2368,7 @@ tosign
touchpad
towlower
towupper
TParam
Tpp
Tpqrst
tprivapi
Expand Down Expand Up @@ -2798,6 +2799,8 @@ XSubstantial
xtended
xterm
XTest
XTPUSHSGR
XTPOPSGR
xutr
xvalue
XVIRTUALSCREEN
Expand Down
36 changes: 36 additions & 0 deletions src/buffer/out/TextAttribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,32 @@ bool TextAttribute::IsLegacy() const noexcept
return _foreground.IsLegacy() && _background.IsLegacy();
}

// Routine Description:
// - Makes this TextAttribute's foreground color the same as the other one.
// Arguments:
// - The TextAttribute to copy the foreground color from
// Return Value:
// - <none>
void TextAttribute::SetForegroundFrom(const TextAttribute& other) noexcept
{
_foreground = other._foreground;
WI_ClearAllFlags(_wAttrLegacy, FG_ATTRS);
_wAttrLegacy |= (other._wAttrLegacy & FG_ATTRS);
}

// Routine Description:
// - Makes this TextAttribute's background color the same as the other one.
// Arguments:
// - The TextAttribute to copy the background color from
// Return Value:
// - <none>
void TextAttribute::SetBackgroundFrom(const TextAttribute& other) noexcept
{
_background = other._background;
WI_ClearAllFlags(_wAttrLegacy, BG_ATTRS);
_wAttrLegacy |= (other._wAttrLegacy & BG_ATTRS);
}

// Routine Description:
// - Calculates rgb colors based off of current color table and active modification attributes.
// Arguments:
Expand Down Expand Up @@ -255,6 +281,11 @@ bool TextAttribute::IsOverlined() const noexcept
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL);
}

bool TextAttribute::IsDoublyUnderlined() const noexcept
{
return WI_IsFlagSet(_extendedAttrs, ExtendedAttributes::DoublyUnderlined);
}

bool TextAttribute::IsReverseVideo() const noexcept
{
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO);
Expand Down Expand Up @@ -301,6 +332,11 @@ void TextAttribute::SetOverlined(bool isOverlined) noexcept
WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL, isOverlined);
}

void TextAttribute::SetDoublyUnderlined(bool isDoublyUnderlined) noexcept
{
WI_UpdateFlag(_extendedAttrs, ExtendedAttributes::DoublyUnderlined, isDoublyUnderlined);
}

void TextAttribute::SetReverseVideo(bool isReversed) noexcept
{
WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO, isReversed);
Expand Down
5 changes: 5 additions & 0 deletions src/buffer/out/TextAttribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class TextAttribute final
const COLORREF defaultBgColor,
const bool reverseScreenMode = false) const noexcept;

void SetForegroundFrom(const TextAttribute& other) noexcept;
void SetBackgroundFrom(const TextAttribute& other) noexcept;

bool IsLeadingByte() const noexcept;
bool IsTrailingByte() const noexcept;
bool IsTopHorizontalDisplayed() const noexcept;
Expand Down Expand Up @@ -96,6 +99,7 @@ class TextAttribute final
bool IsCrossedOut() const noexcept;
bool IsUnderlined() const noexcept;
bool IsOverlined() const noexcept;
bool IsDoublyUnderlined() const noexcept;
bool IsReverseVideo() const noexcept;

void SetBold(bool isBold) noexcept;
Expand All @@ -106,6 +110,7 @@ class TextAttribute final
void SetCrossedOut(bool isCrossedOut) noexcept;
void SetUnderlined(bool isUnderlined) noexcept;
void SetOverlined(bool isOverlined) noexcept;
void SetDoublyUnderlined(bool isDoublyUnderlined) noexcept;
void SetReverseVideo(bool isReversed) noexcept;

ExtendedAttributes GetExtendedAttributes() const noexcept;
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ namespace Microsoft::Terminal::Core

virtual bool CopyToClipboard(std::wstring_view content) noexcept = 0;

virtual bool PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options) noexcept = 0;
virtual bool PopGraphicsRendition() noexcept = 0;

protected:
ITerminalApi() = default;
};
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <conattrs.hpp>

#include "../../buffer/out/textBuffer.hpp"
#include "../../types/inc/sgrStack.hpp"
#include "../../renderer/inc/IRenderData.hpp"
#include "../../terminal/parser/StateMachine.hpp"
#include "../../terminal/input/terminalInput.hpp"
Expand Down Expand Up @@ -110,6 +111,9 @@ class Microsoft::Terminal::Core::Terminal final :
bool IsVtInputEnabled() const noexcept override;

bool CopyToClipboard(std::wstring_view content) noexcept override;

bool PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options) noexcept override;
bool PopGraphicsRendition() noexcept override;
#pragma endregion

#pragma region ITerminalInput
Expand Down Expand Up @@ -295,6 +299,8 @@ class Microsoft::Terminal::Core::Terminal final :
COORD _ConvertToBufferCell(const COORD viewportPos) const;
#pragma endregion

Microsoft::Console::VirtualTerminal::SgrStack _sgrStack;

#ifdef UNIT_TESTING
friend class TerminalCoreUnitTests::TerminalBufferTests;
friend class TerminalCoreUnitTests::TerminalApiTest;
Expand Down
28 changes: 28 additions & 0 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,3 +552,31 @@ try
return true;
}
CATCH_LOG_RETURN_FALSE()

// Method Description:
// - Saves the current text attributes to an internal stack.
// Arguments:
// - options, cOptions: if present, specify which portions of the current text attributes
// should be saved. Only a small subset of GraphicsOptions are actually supported;
// others are ignored. If no options are specified, all attributes are stored.
// Return Value:
// - true
bool Terminal::PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options) noexcept
{
_sgrStack.Push(_buffer->GetCurrentAttributes(), options);
return true;
}

// Method Description:
// - Restores text attributes from the internal stack. If only portions of text attributes
// were saved, combines those with the current attributes.
// Arguments:
// - <none>
// Return Value:
// - true
bool Terminal::PopGraphicsRendition() noexcept
{
const TextAttribute current = _buffer->GetCurrentAttributes();
_buffer->SetCurrentAttributes(_sgrStack.Pop(current));
return true;
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc

bool SetGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions> options) noexcept override;

bool PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options) noexcept override;
bool PopGraphicsRendition() noexcept override;

bool CursorPosition(const size_t line,
const size_t column) noexcept override; // CUP

Expand Down
10 changes: 10 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,13 @@ bool TerminalDispatch::SetGraphicsRendition(const gsl::span<const DispatchTypes:
_terminalApi.SetTextAttributes(attr);
return true;
}

bool TerminalDispatch::PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options) noexcept
{
return _terminalApi.PushGraphicsRendition(options);
}

bool TerminalDispatch::PopGraphicsRendition() noexcept
{
return _terminalApi.PopGraphicsRendition();
}
34 changes: 34 additions & 0 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,40 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
BrightBackgroundWhite = 107,
};

// Many of these correspond directly to SGR parameters (the GraphicsOptions enum), but
// these are distinct (notably 10 and 11, which as SGR parameters would select fonts,
// are used here to indicate that the foreground/background colors should be saved).
// From xterm's ctlseqs doc for XTPUSHSGR:
//
// Ps = 1 => Bold.
// Ps = 2 => Faint.
// Ps = 3 => Italicized.
// Ps = 4 => Underlined.
// Ps = 5 => Blink.
// Ps = 7 => Inverse.
// Ps = 8 => Invisible.
// Ps = 9 => Crossed-out characters.
// Ps = 1 0 => Foreground color.
// Ps = 1 1 => Background color.
// Ps = 2 1 => Doubly-underlined.
//
enum class SgrSaveRestoreStackOptions : unsigned int
{
Nothing = 0,
Boldness = 1,
Faintness = 2,
Italics = 3,
Underline = 4,
Blink = 5,
Negative = 7,
Invisible = 8,
CrossedOut = 9,
SaveForegroundColor = 10,
SaveBackgroundColor = 11,
DoublyUnderlined = 21,
Max = DoublyUnderlined
};

enum class AnsiStatusType : unsigned int
{
OS_OperatingStatus = 5,
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 @@ -88,6 +88,9 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch

virtual bool SetGraphicsRendition(const gsl::span<const DispatchTypes::GraphicsOptions> options) = 0; // SGR

virtual bool PushGraphicsRendition(const gsl::span<const DispatchTypes::SgrSaveRestoreStackOptions> options) = 0; // XTPUSHSGR
virtual bool PopGraphicsRendition() = 0; // XTPOPSGR

virtual bool SetPrivateModes(const gsl::span<const DispatchTypes::PrivateModeParams> params) = 0; // DECSET

virtual bool ResetPrivateModes(const gsl::span<const DispatchTypes::PrivateModeParams> params) = 0; // DECRST
Expand Down
5 changes: 5 additions & 0 deletions src/terminal/adapter/adaptDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Author(s):
#include "conGetSet.hpp"
#include "adaptDefaults.hpp"
#include "terminalOutput.hpp"
#include "..\..\types\inc\sgrStack.hpp"

namespace Microsoft::Console::VirtualTerminal
{
Expand Down Expand Up @@ -56,6 +57,8 @@ namespace Microsoft::Console::VirtualTerminal
bool InsertCharacter(const size_t count) override; // ICH
bool DeleteCharacter(const size_t count) override; // DCH
bool SetGraphicsRendition(const gsl::span<const DispatchTypes::GraphicsOptions> options) override; // SGR
bool PushGraphicsRendition(const gsl::span<const DispatchTypes::SgrSaveRestoreStackOptions> options) override; // XTPUSHSGR
bool PopGraphicsRendition() override; // XTPOPSGR
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) override; // DSR, DSR-OS, DSR-CPR
bool DeviceAttributes() override; // DA1
bool SecondaryDeviceAttributes() override; // DA2
Expand Down Expand Up @@ -192,6 +195,8 @@ namespace Microsoft::Console::VirtualTerminal

bool _isDECCOLMAllowed;

SgrStack _sgrStack;

size_t _SetRgbColorsHelper(const gsl::span<const DispatchTypes::GraphicsOptions> options,
TextAttribute& attr,
const bool isForeground) noexcept;
Expand Down
48 changes: 48 additions & 0 deletions src/terminal/adapter/adaptDispatchGraphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ bool AdaptDispatch::SetGraphicsRendition(const gsl::span<const DispatchTypes::Gr
case CrossedOut:
attr.SetCrossedOut(true);
break;
case DoublyUnderlined:
attr.SetDoublyUnderlined(true);
break;
case NotCrossedOut:
attr.SetCrossedOut(false);
break;
Expand Down Expand Up @@ -285,3 +288,48 @@ bool AdaptDispatch::SetGraphicsRendition(const gsl::span<const DispatchTypes::Gr

return success;
}

// Method Description:
// - Saves the current text attributes to an internal stack.
// Arguments:
// - options: if not empty, specify which portions of the current text attributes should
// be saved. Options that are not supported are ignored. If no options are specified,
// all attributes are stored.
// Return Value:
// - True if handled successfully. False otherwise.
bool AdaptDispatch::PushGraphicsRendition(const gsl::span<const ::Microsoft::Console::VirtualTerminal::DispatchTypes::SgrSaveRestoreStackOptions> options)
{
bool success = true;
TextAttribute currentAttributes;

success = _pConApi->PrivateGetTextAttributes(currentAttributes);

if (success)
{
_sgrStack.Push(currentAttributes, options);
}

return success;
}

// Method Description:
// - Restores text attributes from the internal stack. If only portions of text attributes
// were saved, combines those with the current attributes.
// Arguments:
// - <none>
// Return Value:
// - True if handled successfully. False otherwise.
bool AdaptDispatch::PopGraphicsRendition()
{
bool success = true;
TextAttribute currentAttributes;

success = _pConApi->PrivateGetTextAttributes(currentAttributes);

if (success)
{
success = _pConApi->PrivateSetTextAttributes(_sgrStack.Pop(currentAttributes));
}

return success;
}
3 changes: 3 additions & 0 deletions src/terminal/adapter/termDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons

bool SetGraphicsRendition(const gsl::span<const DispatchTypes::GraphicsOptions> /*options*/) noexcept override { return false; } // SGR

bool PushGraphicsRendition(const gsl::span<const DispatchTypes::SgrSaveRestoreStackOptions> /*options*/) noexcept override { return false; } // XTPUSHSGR
bool PopGraphicsRendition() noexcept override { return false; } // XTPOPSGR

bool SetPrivateModes(const gsl::span<const DispatchTypes::PrivateModeParams> /*params*/) noexcept override { return false; } // DECSET

bool ResetPrivateModes(const gsl::span<const DispatchTypes::PrivateModeParams> /*params*/) noexcept override { return false; } // DECRST
Expand Down
3 changes: 3 additions & 0 deletions src/terminal/adapter/ut_adapter/Adapter.UnitTests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
<ProjectReference Include="..\lib\adapter.vcxproj">
<Project>{dcf55140-ef6a-4736-a403-957e4f7430bb}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\buffer\out\lib\bufferout.vcxproj">
<Project>{0cf235bd-2da0-407e-90ee-c467e8bbc714}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
Expand Down
Loading

0 comments on commit afcf1d4

Please sign in to comment.