Skip to content

Commit

Permalink
Expose current TextAttributes from the underlying console API
Browse files Browse the repository at this point in the history
The XTPUSHSGR / XTPOPSGR control sequences require saving a [stack of]
text attributes, and not just the legacy attributes, but full RGB
colors, etc. This commit makes those attributes available.
  • Loading branch information
jazzdelightsme committed Sep 13, 2019
1 parent 1fccbc5 commit df23e7c
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/buffer/out/textBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ const Cursor& TextBuffer::GetCursor() const noexcept
return _currentAttributes;
}

void TextBuffer::SetCurrentAttributes(const TextAttribute currentAttributes) noexcept
void TextBuffer::SetCurrentAttributes(const TextAttribute& currentAttributes) noexcept
{
_currentAttributes = currentAttributes;
}
Expand Down
2 changes: 1 addition & 1 deletion src/buffer/out/textBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class TextBuffer final

[[nodiscard]] TextAttribute GetCurrentAttributes() const noexcept;

void SetCurrentAttributes(const TextAttribute currentAttributes) noexcept;
void SetCurrentAttributes(const TextAttribute& currentAttributes) noexcept;

void Reset();

Expand Down
36 changes: 35 additions & 1 deletion src/host/getset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,13 @@ void DoSrvPrivateSetLegacyAttributes(SCREEN_INFORMATION& screenInfo,
buffer.SetAttributes(NewAttributes);
}

void DoSrvPrivateSetAttributes(SCREEN_INFORMATION& screenInfo,
const TextAttribute& Attributes)
{
auto& buffer = screenInfo.GetActiveBuffer();
buffer.SetAttributes(Attributes);
}

void DoSrvPrivateSetDefaultAttributes(SCREEN_INFORMATION& screenInfo,
const bool fForeground,
const bool fBackground)
Expand Down Expand Up @@ -1643,7 +1650,7 @@ void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
// - pwAttributes - Pointer to space that will receive color attributes data
// Return Value:
// - STATUS_SUCCESS if we succeeded or STATUS_INVALID_PARAMETER for bad params (nullptr).
[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferAttributes(_In_ const SCREEN_INFORMATION& screenInfo, _Out_ WORD* const pwAttributes)
[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferLegacyAttributes(_In_ const SCREEN_INFORMATION& screenInfo, _Out_ WORD* const pwAttributes)
{
NTSTATUS Status = STATUS_SUCCESS;

Expand All @@ -1660,6 +1667,33 @@ void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
return Status;
}

// Routine Description:
// - A private API call to get only the default text attributes of the screen buffer.
// - This is used as a performance optimization by the VT adapter in SGR-related code (Set Graphics Rendition)
// instead of calling for this information through the public API GetConsoleScreenBufferInfoEx which returns
// a lot of extra unnecessary data and takes a lot of extra processing time.
// Parameters
// - screenInfo - The screen buffer to retrieve default text attributes information from
// - pwAttributes - Pointer to space that will receive text attributes data
// Return Value:
// - STATUS_SUCCESS if we succeeded or STATUS_INVALID_PARAMETER for bad params (nullptr).
[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferAttributes(_In_ const SCREEN_INFORMATION& screenInfo, _Out_ TextAttribute* const pAttributes)
{
NTSTATUS Status = STATUS_SUCCESS;

if (pAttributes == nullptr)
{
Status = STATUS_INVALID_PARAMETER;
}

if (NT_SUCCESS(Status))
{
*pAttributes = screenInfo.GetActiveBuffer().GetAttributes();
}

return Status;
}

// Routine Description:
// - A private API call for forcing the renderer to repaint the screen. If the
// input screen buffer is not the active one, then just do nothing. We only
Expand Down
10 changes: 8 additions & 2 deletions src/host/getset.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Revision History:

#pragma once
#include "../inc/conattrs.hpp"
#include "../buffer/out/TextAttribute.hpp"
class SCREEN_INFORMATION;

void DoSrvPrivateSetLegacyAttributes(SCREEN_INFORMATION& screenInfo,
Expand All @@ -24,6 +25,9 @@ void DoSrvPrivateSetLegacyAttributes(SCREEN_INFORMATION& screenInfo,
const bool fBackground,
const bool fMeta);

void DoSrvPrivateSetAttributes(SCREEN_INFORMATION& screenInfo,
const TextAttribute& Attributes);

void DoSrvPrivateSetDefaultAttributes(SCREEN_INFORMATION& screenInfo, const bool fForeground, const bool fBackground);

[[nodiscard]] NTSTATUS DoSrvPrivateSetCursorKeysMode(_In_ bool fApplicationMode);
Expand Down Expand Up @@ -67,8 +71,10 @@ void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor);

[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferAttributes(const SCREEN_INFORMATION& screenInfo,
_Out_ WORD* const pwAttributes);
[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferLegacyAttributes(const SCREEN_INFORMATION& screenInfo,
_Out_ WORD* const pwAttributes);
[[nodiscard]] NTSTATUS DoSrvPrivateGetConsoleScreenBufferAttributes(_In_ const SCREEN_INFORMATION& screenInfo,
_Out_ TextAttribute* const pAttributes);

void DoSrvPrivateRefreshWindow(const SCREEN_INFORMATION& screenInfo);

Expand Down
22 changes: 20 additions & 2 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ BOOL ConhostInternalGetSet::PrivateSetLegacyAttributes(const WORD wAttr,
return TRUE;
}

BOOL ConhostInternalGetSet::PrivateSetAttributes(const TextAttribute& attributes)
{
DoSrvPrivateSetAttributes(_io.GetActiveOutputBuffer(), attributes);
return TRUE;
}

// Routine Description:
// - Sets the current attributes of the screen buffer to use the color table entry specified by
// the iXtermTableEntry. Sets either the FG or the BG component of the attributes.
Expand Down Expand Up @@ -629,9 +635,21 @@ BOOL ConhostInternalGetSet::SetCursorStyle(const CursorType cursorType)
// - pwAttributes - Pointer to space to receive color attributes data
// Return Value:
// - TRUE if successful. FALSE otherwise.
BOOL ConhostInternalGetSet::PrivateGetConsoleScreenBufferAttributes(_Out_ WORD* const pwAttributes)
BOOL ConhostInternalGetSet::PrivateGetConsoleScreenBufferLegacyAttributes(_Out_ WORD* const pwAttributes)
{
return NT_SUCCESS(DoSrvPrivateGetConsoleScreenBufferLegacyAttributes(_io.GetActiveOutputBuffer(), pwAttributes));
}

// Routine Description:
// - Retrieves the default text attributes information for the active screen buffer.
// - Similar to PrivateGetConsoleScreenBufferLegacyAttributes, but gets the full attributes.
// Arguments:
// - pAttributes - Pointer to space to receive attributes data
// Return Value:
// - TRUE if successful. FALSE otherwise.
BOOL ConhostInternalGetSet::PrivateGetConsoleScreenBufferAttributes(_Out_ TextAttribute* const pAttributes)
{
return NT_SUCCESS(DoSrvPrivateGetConsoleScreenBufferAttributes(_io.GetActiveOutputBuffer(), pwAttributes));
return NT_SUCCESS(DoSrvPrivateGetConsoleScreenBufferAttributes(_io.GetActiveOutputBuffer(), pAttributes));
}

// Routine Description:
Expand Down
5 changes: 4 additions & 1 deletion src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
const bool fBackground,
const bool fMeta) override;

BOOL PrivateSetAttributes(const TextAttribute& attributes) override;

BOOL PrivateSetDefaultAttributes(const bool fForeground,
const bool fBackground) override;

Expand Down Expand Up @@ -132,7 +134,8 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
BOOL PrivateEnableAlternateScroll(const bool fEnabled) override;
BOOL PrivateEraseAll() override;

BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ WORD* const pwAttributes) override;
BOOL PrivateGetConsoleScreenBufferLegacyAttributes(_Out_ WORD* const pwAttributes) override;
BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ TextAttribute* const pAttributes) override;

BOOL PrivatePrependConsoleInput(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
_Out_ size_t& eventsWritten) override;
Expand Down
2 changes: 1 addition & 1 deletion src/terminal/adapter/adaptDispatchGraphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ bool AdaptDispatch::SetGraphicsRendition(_In_reads_(cOptions) const DispatchType
// because it has to fill the Largest Window Size by asking the OS and wastes time memcpying colors and other data
// we do not need to resolve this Set Graphics Rendition request.
WORD attr;
bool fSuccess = !!_conApi->PrivateGetConsoleScreenBufferAttributes(&attr);
bool fSuccess = !!_conApi->PrivateGetConsoleScreenBufferLegacyAttributes(&attr);

if (fSuccess)
{
Expand Down
6 changes: 5 additions & 1 deletion src/terminal/adapter/conGetSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Author(s):

#include "..\..\types\inc\IInputEvent.hpp"
#include "..\..\inc\conattrs.hpp"
#include "..\..\buffer\out\TextAttribute.hpp"

#include <deque>
#include <memory>
Expand Down Expand Up @@ -46,6 +47,8 @@ namespace Microsoft::Console::VirtualTerminal
const bool fBackground,
const bool fMeta) = 0;

virtual BOOL PrivateSetAttributes(const TextAttribute& attributes) = 0;

virtual BOOL PrivateSetDefaultAttributes(const bool fForeground, const bool fBackground) = 0;

virtual BOOL SetConsoleXtermTextAttribute(const int iXtermTableEntry,
Expand Down Expand Up @@ -87,7 +90,8 @@ namespace Microsoft::Console::VirtualTerminal
virtual BOOL PrivateEraseAll() = 0;
virtual BOOL SetCursorStyle(const CursorType cursorType) = 0;
virtual BOOL SetCursorColor(const COLORREF cursorColor) = 0;
virtual BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ WORD* const pwAttributes) = 0;
virtual BOOL PrivateGetConsoleScreenBufferLegacyAttributes(_Out_ WORD* const pwAttributes) = 0;
virtual BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ TextAttribute* const pAttributes) = 0;
virtual BOOL PrivatePrependConsoleInput(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
_Out_ size_t& eventsWritten) = 0;
virtual BOOL PrivateWriteConsoleControlInput(_In_ KeyEvent key) = 0;
Expand Down
33 changes: 29 additions & 4 deletions src/terminal/adapter/ut_adapter/adapterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,16 @@ class TestGetSet final : public ConGetSet
return _fPrivateSetLegacyAttributesResult;
}

BOOL PrivateSetAttributes(const TextAttribute& attributes) override
{
Log::Comment(L"PrivateSetAttributes MOCK called...");

// TODO
UNREFERENCED_PARAMETER(attributes);

return TRUE;
}

BOOL SetConsoleXtermTextAttribute(const int iXtermTableEntry, const bool fIsForeground) override
{
Log::Comment(L"SetConsoleXtermTextAttribute MOCK called...");
Expand Down Expand Up @@ -579,15 +589,28 @@ class TestGetSet final : public ConGetSet
return _fSetCursorColorResult;
}

BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ WORD* const pwAttributes) override
BOOL PrivateGetConsoleScreenBufferLegacyAttributes(_Out_ WORD* const pwAttributes) override
{
Log::Comment(L"PrivateGetConsoleScreenBufferAttributes MOCK returning data...");
Log::Comment(L"PrivateGetConsoleScreenBufferLegacyAttributes MOCK returning data...");

if (pwAttributes != nullptr && _fPrivateGetConsoleScreenBufferAttributesResult)
if (pwAttributes != nullptr && _fPrivateGetConsoleScreenBufferLegacyAttributesResult)
{
*pwAttributes = _wAttribute;
}

return _fPrivateGetConsoleScreenBufferLegacyAttributesResult;
}

BOOL PrivateGetConsoleScreenBufferAttributes(_Out_ TextAttribute* const pAttributes) override
{
Log::Comment(L"PrivateGetConsoleScreenBufferAttributes MOCK returning data...");

if (pAttributes != nullptr && _fPrivateGetConsoleScreenBufferAttributesResult)
{
// TODO
*pAttributes = TextAttribute();
}

return _fPrivateGetConsoleScreenBufferAttributesResult;
}

Expand Down Expand Up @@ -761,6 +784,7 @@ class TestGetSet final : public ConGetSet
_fPrivateWriteConsoleControlInputResult = TRUE;
_fScrollConsoleScreenBufferWResult = TRUE;
_fSetConsoleWindowInfoResult = TRUE;
_fPrivateGetConsoleScreenBufferLegacyAttributesResult = TRUE;
_fPrivateGetConsoleScreenBufferAttributesResult = TRUE;
_fMoveToBottomResult = true;

Expand Down Expand Up @@ -1095,6 +1119,7 @@ class TestGetSet final : public ConGetSet
BOOL _fSetConsoleXtermTextAttributeResult = false;
BOOL _fSetConsoleRGBTextAttributeResult = false;
BOOL _fPrivateSetLegacyAttributesResult = false;
BOOL _fPrivateGetConsoleScreenBufferLegacyAttributesResult = false;
BOOL _fPrivateGetConsoleScreenBufferAttributesResult = false;
BOOL _fSetCursorStyleResult = false;
CursorType _ExpectedCursorStyle;
Expand Down Expand Up @@ -1897,7 +1922,7 @@ class AdapterTest
Log::Comment(L"Test 2: Gracefully fail when getting buffer information fails.");

_testGetSet->PrepData();
_testGetSet->_fPrivateGetConsoleScreenBufferAttributesResult = FALSE;
_testGetSet->_fPrivateGetConsoleScreenBufferLegacyAttributesResult = FALSE;

VERIFY_IS_FALSE(_pDispatch->SetGraphicsRendition(rgOptions, cOptions));

Expand Down

0 comments on commit df23e7c

Please sign in to comment.