Fix SGR indexed colors to distinguish Indexed256 color (and more) (#5834)

This PR introduces a new `ColorType` to allow us to distinguish between
`SGR` indexed colors from the 16 color table, the lower half of which
can be brightened, and the ISO/ITU indexed colors from the 256 color
table, which have a fixed brightness. Retaining the distinction between
these two types will enable us to forward the correct `SGR` sequences to
conpty when addressing issue #2661. 

The other benefit of retaining the color index (which we didn't
previously do for ISO/ITU colors) is that it ensures that the colors are
updated correctly when the color scheme is changed.

## References

* This is another step towards fixing the conpty narrowing bugs in issue
  #2661.
* This is technically a fix for issue #5384, but that won't be apparent
  until #2661 is complete.

## PR Checklist
* [x] Closes #1223
* [x] CLA signed. 
* [x] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments

The first part of this PR was the introduction of a new `ColorType` in
the `TextColor` class. Instead of just the one `IsIndex` type, there is
now an `IsIndex16` and an `IsIndex256`. `IsIndex16` covers the eight
original ANSI colors set with `SGR 3x` and `SGR 4x`, as well as the
brighter aixterm variants set with `SGR 9x` and `SGR 10x`. `IsIndex256`
covers the 256 ISO/ITU indexed colors set with `SGR 38;5` and `SGR
48;5`.

There are two reasons for this distinction. The first is that the ANSI
colors have the potential to be brightened by the `SGR 1` bold
attribute, while the ISO/ITO color do not. The second reason is that
when forwarding an attributes through conpty, we want to try and
preserve the original SGR sequence that generated each color (to the
extent that that is possible). By having the two separate types, we can
map the `IsIndex16` colors back to ANSI/aixterm values, and `IsIndex256`
to the ISO/ITU sequences.

In addition to the VT colors, we also have to deal with the legacy
colors set by the Windows console APIs, but we don't really need a
separate type for those. It seemed most appropriate to me to store them
as `IsIndex256` colors, since it doesn't make sense to have them
brightened by the `SGR 1` attribute (which is what would happen if they
were stored as `IsIndex16`). If a console app wanted a bright color it
would have selected one, so we shouldn't be messing with that choice.

The second part of the PR was the unification of the two color tables.
Originally we had a 16 color table for the legacy colors, and a separate
table for the 256 ISO/ITU colors. These have now been merged into one,
so color table lookups no longer need to decide which of the two tables
they should be referencing. I've also updated all the methods that took
a color table as a parameter to use a `basic_string_view` instead of
separate pointer and length variables, which I think makes them a lot
easier and safer to work with. 

With this new architecture in place, I could now update the
`AdaptDispatch` SGR implementation to store the ISO/ITU indexed colors
as `IsIndex256` values, where before they were mapped to RGB values
(which prevented them reflecting any color scheme changes). I could also
update the `TerminalDispatch` implementation to differentiate between
the two index types, so that the `SGR 1` brightening would only be
applied to the ANSI colors.

I've also done a bit of code refactoring to try and minimise any direct
access to the color tables, getting rid of a lot of places that were
copying tables with `memmove` operations. I'm hoping this will make it
easier for us to update the code in the future if we want to reorder the
table entries (which is likely a requirement for unifying the
`AdaptDispatch` and `TerminalDispatch` implementations). 

## Validation Steps Performed

For testing, I've just updated the existing unit tests to account for
the API changes. The `TextColorTests` required an extra parameter
specifying the index type when setting an index. And the `AdapterTest`
and `ScreenBufferTests` required the use of the new `SetIndexedXXX`
methods in order to be explicit about the index type, instead of relying
on the `TextAttribute` constructor and the old `SetForeground` and
`SetBackground` methods which didn't have a way to differentiate index
types.

I've manually tested the various console APIs
(`SetConsoleTextAttribute`, `ReadConsoleOutputAttribute`, and
`ReadConsoleOutput`), to make sure they are still setting and reading
the attributes as well as they used to. And I've tested the
`SetConsoleScreenBufferInfoEx` and `GetConsoleScreenBufferInfoEx` APIs
to make sure they can read and write the color table correctly. I've
also tested the color table in the properties dialog, made sure it was
saved and restored from the registry correctly, and similarly saved and
restored from a shortcut link.

Note that there are still a bunch of issues with the color table APIs,
but no new problems have been introduced by the changes in this PR, as
far as I could tell.

I've also done a bunch of manual tests of `OSC 4` to make sure it's
updating all the colors correctly (at least in conhost), and confirmed
that the test case in issue #1223 now works as expected.
This commit is contained in:
James Holderness 2020-05-27 23:34:45 +01:00 committed by GitHub
parent e7c22fbadb
commit fa7c1abdf8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 327 additions and 375 deletions

View file

@ -10,6 +10,11 @@ bool TextAttribute::IsLegacy() const noexcept
return _foreground.IsLegacy() && _background.IsLegacy(); return _foreground.IsLegacy() && _background.IsLegacy();
} }
bool TextAttribute::IsHighColor() const noexcept
{
return _foreground.IsHighColor() || _background.IsHighColor();
}
// Arguments: // Arguments:
// - None // - None
// Return Value: // Return Value:
@ -72,12 +77,22 @@ void TextAttribute::SetBackground(const COLORREF rgbBackground) noexcept
void TextAttribute::SetIndexedForeground(const BYTE fgIndex) noexcept void TextAttribute::SetIndexedForeground(const BYTE fgIndex) noexcept
{ {
_foreground = TextColor(fgIndex); _foreground = TextColor(fgIndex, false);
} }
void TextAttribute::SetIndexedBackground(const BYTE bgIndex) noexcept void TextAttribute::SetIndexedBackground(const BYTE bgIndex) noexcept
{ {
_background = TextColor(bgIndex); _background = TextColor(bgIndex, false);
}
void TextAttribute::SetIndexedForeground256(const BYTE fgIndex) noexcept
{
_foreground = TextColor(fgIndex, true);
}
void TextAttribute::SetIndexedBackground256(const BYTE bgIndex) noexcept
{
_background = TextColor(bgIndex, true);
} }
void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept

View file

@ -42,8 +42,8 @@ public:
constexpr TextAttribute(const WORD wLegacyAttr) noexcept : constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) }, _wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
_foreground{ gsl::narrow_cast<BYTE>(wLegacyAttr & FG_ATTRS) }, _foreground{ gsl::narrow_cast<BYTE>(wLegacyAttr & FG_ATTRS), true },
_background{ gsl::narrow_cast<BYTE>((wLegacyAttr & BG_ATTRS) >> 4) }, _background{ gsl::narrow_cast<BYTE>((wLegacyAttr & BG_ATTRS) >> 4), true },
_extendedAttrs{ ExtendedAttributes::Normal } _extendedAttrs{ ExtendedAttributes::Normal }
{ {
// If we're given lead/trailing byte information with the legacy color, strip it. // If we're given lead/trailing byte information with the legacy color, strip it.
@ -59,12 +59,13 @@ public:
{ {
} }
constexpr WORD GetLegacyAttributes() const noexcept WORD GetLegacyAttributes() const noexcept
{ {
const BYTE fg = (_foreground.GetIndex() & FG_ATTRS); const BYTE fg = (_foreground.GetIndex() & FG_ATTRS);
const BYTE bg = (_background.GetIndex() << 4) & BG_ATTRS; const BYTE bg = (_background.GetIndex() << 4) & BG_ATTRS;
const WORD meta = (_wAttrLegacy & META_ATTRS); const WORD meta = (_wAttrLegacy & META_ATTRS);
return (fg | bg | meta) | (IsBold() ? FOREGROUND_INTENSITY : 0); const bool brighten = _foreground.IsIndex16() && IsBold();
return (fg | bg | meta) | (brighten ? FOREGROUND_INTENSITY : 0);
} }
// Method Description: // Method Description:
@ -79,15 +80,16 @@ public:
// the background not be a legacy style attribute. // the background not be a legacy style attribute.
// Return Value: // Return Value:
// - a WORD with legacy-style attributes for this textattribute. // - a WORD with legacy-style attributes for this textattribute.
constexpr WORD GetLegacyAttributes(const BYTE defaultFgIndex, WORD GetLegacyAttributes(const BYTE defaultFgIndex,
const BYTE defaultBgIndex) const noexcept const BYTE defaultBgIndex) const noexcept
{ {
const BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex; const BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex;
const BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex; const BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex;
const BYTE fg = (fgIndex & FG_ATTRS); const BYTE fg = (fgIndex & FG_ATTRS);
const BYTE bg = (bgIndex << 4) & BG_ATTRS; const BYTE bg = (bgIndex << 4) & BG_ATTRS;
const WORD meta = (_wAttrLegacy & META_ATTRS); const WORD meta = (_wAttrLegacy & META_ATTRS);
return (fg | bg | meta) | (IsBold() ? FOREGROUND_INTENSITY : 0); const bool brighten = _foreground.IsIndex16() && IsBold();
return (fg | bg | meta) | (brighten ? FOREGROUND_INTENSITY : 0);
} }
COLORREF CalculateRgbForeground(std::basic_string_view<COLORREF> colorTable, COLORREF CalculateRgbForeground(std::basic_string_view<COLORREF> colorTable,
@ -117,6 +119,7 @@ public:
friend constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept; friend constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept;
bool IsLegacy() const noexcept; bool IsLegacy() const noexcept;
bool IsHighColor() const noexcept;
bool IsBold() const noexcept; bool IsBold() const noexcept;
bool IsItalic() const noexcept; bool IsItalic() const noexcept;
bool IsBlinking() const noexcept; bool IsBlinking() const noexcept;
@ -139,6 +142,8 @@ public:
void SetBackground(const COLORREF rgbBackground) noexcept; void SetBackground(const COLORREF rgbBackground) noexcept;
void SetIndexedForeground(const BYTE fgIndex) noexcept; void SetIndexedForeground(const BYTE fgIndex) noexcept;
void SetIndexedBackground(const BYTE bgIndex) noexcept; void SetIndexedBackground(const BYTE bgIndex) noexcept;
void SetIndexedForeground256(const BYTE fgIndex) noexcept;
void SetIndexedBackground256(const BYTE bgIndex) noexcept;
void SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept; void SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept;
void SetDefaultForeground() noexcept; void SetDefaultForeground() noexcept;
@ -149,11 +154,6 @@ public:
void SetStandardErase() noexcept; void SetStandardErase() noexcept;
constexpr bool IsRgb() const noexcept
{
return _foreground.IsRgb() || _background.IsRgb();
}
// This returns whether this attribute, if printed directly next to another attribute, for the space // This returns whether this attribute, if printed directly next to another attribute, for the space
// character, would look identical to the other one. // character, would look identical to the other one.
bool HasIdenticalVisualRepresentationForBlankSpace(const TextAttribute& other, const bool inverted = false) const noexcept bool HasIdenticalVisualRepresentationForBlankSpace(const TextAttribute& other, const bool inverted = false) const noexcept
@ -224,26 +224,6 @@ constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexce
return !(a == b); return !(a == b);
} }
constexpr bool operator==(const TextAttribute& attr, const WORD& legacyAttr) noexcept
{
return attr.GetLegacyAttributes() == legacyAttr;
}
constexpr bool operator!=(const TextAttribute& attr, const WORD& legacyAttr) noexcept
{
return !(attr == legacyAttr);
}
constexpr bool operator==(const WORD& legacyAttr, const TextAttribute& attr) noexcept
{
return attr == legacyAttr;
}
constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept
{
return !(attr == legacyAttr);
}
#ifdef UNIT_TESTING #ifdef UNIT_TESTING
#define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \ #define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \

View file

@ -4,6 +4,36 @@
#include "precomp.h" #include "precomp.h"
#include "TextColor.h" #include "TextColor.h"
bool TextColor::IsLegacy() const noexcept
{
return IsIndex16() || (IsIndex256() && _index < 16);
}
bool TextColor::IsHighColor() const noexcept
{
return IsRgb() || (IsIndex256() && _index >= 16);
}
bool TextColor::IsIndex16() const noexcept
{
return _meta == ColorType::IsIndex16;
}
bool TextColor::IsIndex256() const noexcept
{
return _meta == ColorType::IsIndex256;
}
bool TextColor::IsDefault() const noexcept
{
return _meta == ColorType::IsDefault;
}
bool TextColor::IsRgb() const noexcept
{
return _meta == ColorType::IsRgb;
}
// Method Description: // Method Description:
// - Sets the color value of this attribute, and sets this color to be an RGB // - Sets the color value of this attribute, and sets this color to be an RGB
// attribute. // attribute.
@ -23,11 +53,12 @@ void TextColor::SetColor(const COLORREF rgbColor) noexcept
// - Sets this TextColor to be a legacy-style index into the color table. // - Sets this TextColor to be a legacy-style index into the color table.
// Arguments: // Arguments:
// - index: the index of the colortable we should use for this TextColor. // - index: the index of the colortable we should use for this TextColor.
// - isIndex256: is this a 256 color index (true) or a 16 color index (false).
// Return Value: // Return Value:
// - <none> // - <none>
void TextColor::SetIndex(const BYTE index) noexcept void TextColor::SetIndex(const BYTE index, const bool isIndex256) noexcept
{ {
_meta = ColorType::IsIndex; _meta = isIndex256 ? ColorType::IsIndex256 : ColorType::IsIndex16;
_index = index; _index = index;
} }
@ -48,15 +79,15 @@ void TextColor::SetDefault() noexcept
// * If we're an RGB color, we'll use that value. // * If we're an RGB color, we'll use that value.
// * If we're an indexed color table value, we'll use that index to look up // * If we're an indexed color table value, we'll use that index to look up
// our value in the provided color table. // our value in the provided color table.
// - If brighten is true, and the index is in the "dark" portion of the // - If brighten is true, and we've got a 16 color index in the "dark"
// color table (indices [0,7]), then we'll look up the bright version of // portion of the color table (indices [0,7]), then we'll look up the
// this color (from indices [8,15]). This should be true for // bright version of this color (from indices [8,15]). This should be
// TextAttributes that are "Bold" and we're treating bold as bright // true for TextAttributes that are "Bold" and we're treating bold as
// (which is the default behavior of most terminals.) // bright (which is the default behavior of most terminals.)
// * If we're a default color, we'll return the default color provided. // * If we're a default color, we'll return the default color provided.
// Arguments: // Arguments:
// - colorTable: The table of colors we should use to look up the value of a // - colorTable: The table of colors we should use to look up the value of
// legacy attribute from // an indexed attribute from.
// - defaultColor: The color value to use if we're a default attribute. // - defaultColor: The color value to use if we're a default attribute.
// - brighten: if true, we'll brighten a dark color table index. // - brighten: if true, we'll brighten a dark color table index.
// Return Value: // Return Value:
@ -94,21 +125,13 @@ COLORREF TextColor::GetColor(std::basic_string_view<COLORREF> colorTable,
{ {
return _GetRGB(); return _GetRGB();
} }
else if (IsIndex16() && brighten)
{
return colorTable.at(_index | 8);
}
else else
{ {
FAIL_FAST_IF(colorTable.size() < _index); return colorTable.at(_index);
// If the color is already bright (it's in index [8,15] or it's a
// 256color value [16,255], then boldness does nothing.
if (brighten && _index < 8)
{
FAIL_FAST_IF(colorTable.size() < 16);
FAIL_FAST_IF(gsl::narrow_cast<size_t>(_index) + 8 > colorTable.size());
return colorTable.at(gsl::narrow_cast<size_t>(_index) + 8);
}
else
{
return colorTable.at(_index);
}
} }
} }

View file

@ -41,9 +41,10 @@ Revision History:
enum class ColorType : BYTE enum class ColorType : BYTE
{ {
IsIndex = 0x0, IsIndex256 = 0x0,
IsDefault = 0x1, IsIndex16 = 0x1,
IsRgb = 0x2 IsDefault = 0x2,
IsRgb = 0x3
}; };
struct TextColor struct TextColor
@ -57,9 +58,9 @@ public:
{ {
} }
constexpr TextColor(const BYTE wLegacyAttr) noexcept : constexpr TextColor(const BYTE index, const bool isIndex256) noexcept :
_meta{ ColorType::IsIndex }, _meta{ isIndex256 ? ColorType::IsIndex256 : ColorType::IsIndex16 },
_index{ wLegacyAttr }, _index{ index },
_green{ 0 }, _green{ 0 },
_blue{ 0 } _blue{ 0 }
{ {
@ -76,23 +77,15 @@ public:
friend constexpr bool operator==(const TextColor& a, const TextColor& b) noexcept; friend constexpr bool operator==(const TextColor& a, const TextColor& b) noexcept;
friend constexpr bool operator!=(const TextColor& a, const TextColor& b) noexcept; friend constexpr bool operator!=(const TextColor& a, const TextColor& b) noexcept;
constexpr bool IsLegacy() const noexcept bool IsLegacy() const noexcept;
{ bool IsHighColor() const noexcept;
return !(IsDefault() || IsRgb()); bool IsIndex16() const noexcept;
} bool IsIndex256() const noexcept;
bool IsDefault() const noexcept;
constexpr bool IsDefault() const noexcept bool IsRgb() const noexcept;
{
return _meta == ColorType::IsDefault;
}
constexpr bool IsRgb() const noexcept
{
return _meta == ColorType::IsRgb;
}
void SetColor(const COLORREF rgbColor) noexcept; void SetColor(const COLORREF rgbColor) noexcept;
void SetIndex(const BYTE index) noexcept; void SetIndex(const BYTE index, const bool isIndex256) noexcept;
void SetDefault() noexcept; void SetDefault() noexcept;
COLORREF GetColor(std::basic_string_view<COLORREF> colorTable, COLORREF GetColor(std::basic_string_view<COLORREF> colorTable,

View file

@ -81,7 +81,7 @@ void TextColorTests::TestDefaultColor()
void TextColorTests::TestDarkIndexColor() void TextColorTests::TestDarkIndexColor()
{ {
TextColor indexColor((BYTE)(7)); TextColor indexColor((BYTE)(7), false);
VERIFY_IS_FALSE(indexColor.IsDefault()); VERIFY_IS_FALSE(indexColor.IsDefault());
VERIFY_IS_TRUE(indexColor.IsLegacy()); VERIFY_IS_TRUE(indexColor.IsLegacy());
@ -104,7 +104,7 @@ void TextColorTests::TestDarkIndexColor()
void TextColorTests::TestBrightIndexColor() void TextColorTests::TestBrightIndexColor()
{ {
TextColor indexColor((BYTE)(15)); TextColor indexColor((BYTE)(15), false);
VERIFY_IS_FALSE(indexColor.IsDefault()); VERIFY_IS_FALSE(indexColor.IsDefault());
VERIFY_IS_TRUE(indexColor.IsLegacy()); VERIFY_IS_TRUE(indexColor.IsLegacy());
@ -186,7 +186,7 @@ void TextColorTests::TestChangeColor()
color = rgbColor.GetColor(view, _defaultBg, true); color = rgbColor.GetColor(view, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color); VERIFY_ARE_EQUAL(_defaultBg, color);
rgbColor.SetIndex(7); rgbColor.SetIndex(7, false);
color = rgbColor.GetColor(view, _defaultFg, false); color = rgbColor.GetColor(view, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color); VERIFY_ARE_EQUAL(_colorTable[7], color);
@ -199,7 +199,7 @@ void TextColorTests::TestChangeColor()
color = rgbColor.GetColor(view, _defaultBg, true); color = rgbColor.GetColor(view, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
rgbColor.SetIndex(15); rgbColor.SetIndex(15, false);
color = rgbColor.GetColor(view, _defaultFg, false); color = rgbColor.GetColor(view, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);

View file

@ -21,6 +21,8 @@ namespace Microsoft::Terminal::Core
virtual bool SetTextToDefaults(bool foreground, bool background) noexcept = 0; virtual bool SetTextToDefaults(bool foreground, bool background) noexcept = 0;
virtual bool SetTextForegroundIndex(BYTE colorIndex) noexcept = 0; virtual bool SetTextForegroundIndex(BYTE colorIndex) noexcept = 0;
virtual bool SetTextBackgroundIndex(BYTE colorIndex) noexcept = 0; virtual bool SetTextBackgroundIndex(BYTE colorIndex) noexcept = 0;
virtual bool SetTextForegroundIndex256(BYTE colorIndex) noexcept = 0;
virtual bool SetTextBackgroundIndex256(BYTE colorIndex) noexcept = 0;
virtual bool SetTextRgbColor(COLORREF color, bool foreground) noexcept = 0; virtual bool SetTextRgbColor(COLORREF color, bool foreground) noexcept = 0;
virtual bool BoldText(bool boldOn) noexcept = 0; virtual bool BoldText(bool boldOn) noexcept = 0;
virtual bool UnderlineText(bool underlineOn) noexcept = 0; virtual bool UnderlineText(bool underlineOn) noexcept = 0;

View file

@ -81,6 +81,8 @@ public:
bool SetTextToDefaults(bool foreground, bool background) noexcept override; bool SetTextToDefaults(bool foreground, bool background) noexcept override;
bool SetTextForegroundIndex(BYTE colorIndex) noexcept override; bool SetTextForegroundIndex(BYTE colorIndex) noexcept override;
bool SetTextBackgroundIndex(BYTE colorIndex) noexcept override; bool SetTextBackgroundIndex(BYTE colorIndex) noexcept override;
bool SetTextForegroundIndex256(BYTE colorIndex) noexcept override;
bool SetTextBackgroundIndex256(BYTE colorIndex) noexcept override;
bool SetTextRgbColor(COLORREF color, bool foreground) noexcept override; bool SetTextRgbColor(COLORREF color, bool foreground) noexcept override;
bool BoldText(bool boldOn) noexcept override; bool BoldText(bool boldOn) noexcept override;
bool UnderlineText(bool underlineOn) noexcept override; bool UnderlineText(bool underlineOn) noexcept override;

View file

@ -57,6 +57,22 @@ bool Terminal::SetTextBackgroundIndex(BYTE colorIndex) noexcept
return true; return true;
} }
bool Terminal::SetTextForegroundIndex256(BYTE colorIndex) noexcept
{
TextAttribute attrs = _buffer->GetCurrentAttributes();
attrs.SetIndexedForeground256(colorIndex);
_buffer->SetCurrentAttributes(attrs);
return true;
}
bool Terminal::SetTextBackgroundIndex256(BYTE colorIndex) noexcept
{
TextAttribute attrs = _buffer->GetCurrentAttributes();
attrs.SetIndexedBackground256(colorIndex);
_buffer->SetCurrentAttributes(attrs);
return true;
}
bool Terminal::SetTextRgbColor(COLORREF color, bool foreground) noexcept bool Terminal::SetTextRgbColor(COLORREF color, bool foreground) noexcept
{ {
TextAttribute attrs = _buffer->GetCurrentAttributes(); TextAttribute attrs = _buffer->GetCurrentAttributes();

View file

@ -121,8 +121,8 @@ bool TerminalDispatch::_SetRgbColorsHelper(const std::basic_string_view<Dispatch
{ {
const auto tableIndex = til::at(options, 2); const auto tableIndex = til::at(options, 2);
success = isForeground ? success = isForeground ?
_terminalApi.SetTextForegroundIndex(gsl::narrow_cast<BYTE>(tableIndex)) : _terminalApi.SetTextForegroundIndex256(gsl::narrow_cast<BYTE>(tableIndex)) :
_terminalApi.SetTextBackgroundIndex(gsl::narrow_cast<BYTE>(tableIndex)); _terminalApi.SetTextBackgroundIndex256(gsl::narrow_cast<BYTE>(tableIndex));
} }
} }
} }

View file

@ -119,8 +119,7 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
auto vtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hFile), auto vtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hFile),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable());
static_cast<WORD>(gci.GetColorTableSize()));
auto pfn = std::bind(&ConptyRoundtripTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&ConptyRoundtripTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2);
vtRenderEngine->SetTestCallback(pfn); vtRenderEngine->SetTestCallback(pfn);

View file

@ -161,31 +161,27 @@ VtIo::VtIo() :
_pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(_hOutput), _pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(_hOutput),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable());
static_cast<WORD>(gci.GetColorTableSize()));
break; break;
case VtIoMode::XTERM: case VtIoMode::XTERM:
_pVtRenderEngine = std::make_unique<XtermEngine>(std::move(_hOutput), _pVtRenderEngine = std::make_unique<XtermEngine>(std::move(_hOutput),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable(),
static_cast<WORD>(gci.GetColorTableSize()),
false); false);
break; break;
case VtIoMode::XTERM_ASCII: case VtIoMode::XTERM_ASCII:
_pVtRenderEngine = std::make_unique<XtermEngine>(std::move(_hOutput), _pVtRenderEngine = std::make_unique<XtermEngine>(std::move(_hOutput),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable(),
static_cast<WORD>(gci.GetColorTableSize()),
true); true);
break; break;
case VtIoMode::WIN_TELNET: case VtIoMode::WIN_TELNET:
_pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(_hOutput), _pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(_hOutput),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable());
static_cast<WORD>(gci.GetColorTableSize()));
break; break;
default: default:
return E_FAIL; return E_FAIL;

View file

@ -81,13 +81,12 @@ static double _FindDifference(const _HSL* const phslColorA, const COLORREF rgbCo
//Arguments: //Arguments:
// - Color - The RGB color to fine the nearest color to. // - Color - The RGB color to fine the nearest color to.
// - ColorTable - The array of colors to find a nearest color from. // - ColorTable - The array of colors to find a nearest color from.
// - cColorTable - The number of elements in ColorTable
// Return value: // Return value:
// The index in ColorTable of the nearest match to Color. // The index in ColorTable of the nearest match to Color.
WORD FindNearestTableIndex(const COLORREF Color, _In_reads_(cColorTable) const COLORREF* const ColorTable, const WORD cColorTable) WORD FindNearestTableIndex(const COLORREF Color, const std::basic_string_view<COLORREF> ColorTable)
{ {
// Quick check for an exact match in the color table: // Quick check for an exact match in the color table:
for (WORD i = 0; i < cColorTable; i++) for (WORD i = 0; i < ColorTable.size(); i++)
{ {
if (Color == ColorTable[i]) if (Color == ColorTable[i])
{ {
@ -100,7 +99,7 @@ WORD FindNearestTableIndex(const COLORREF Color, _In_reads_(cColorTable) const C
const _HSL hslColor = _HSL(Color); const _HSL hslColor = _HSL(Color);
WORD closest = 0; WORD closest = 0;
double minDiff = _FindDifference(&hslColor, ColorTable[0]); double minDiff = _FindDifference(&hslColor, ColorTable[0]);
for (WORD i = 1; i < cColorTable; i++) for (WORD i = 1; i < ColorTable.size(); i++)
{ {
double diff = _FindDifference(&hslColor, ColorTable[i]); double diff = _FindDifference(&hslColor, ColorTable[i]);
if (diff < minDiff) if (diff < minDiff)
@ -146,36 +145,19 @@ WORD Xterm256ToWindowsIndex(const size_t xtermTableEntry) noexcept
static_cast<WORD>(xtermTableEntry); static_cast<WORD>(xtermTableEntry);
} }
// Function Description:
// - Converts the value of a pair of xterm color table indices to the legacy attr equivalent.
// Arguments:
// - xtermForeground: the xterm color table foreground index
// - xtermBackground: the xterm color table background index
// Return Value:
// - The legacy windows attribute equivalent.
WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground)
{
const WORD fgAttr = XtermToWindowsIndex(xtermForeground);
const WORD bgAttr = XtermToWindowsIndex(xtermBackground);
return (bgAttr << 4) | fgAttr;
}
//Routine Description: //Routine Description:
// Returns the exact entry from the color table, if it's in there. // Returns the exact entry from the color table, if it's in there.
//Arguments: //Arguments:
// - Color - The RGB color to fine the nearest color to. // - Color - The RGB color to fine the nearest color to.
// - ColorTable - The array of colors to find a nearest color from. // - ColorTable - The array of colors to find a nearest color from.
// - cColorTable - The number of elements in ColorTable
// Return value: // Return value:
// The index in ColorTable of the nearest match to Color. // The index in ColorTable of the nearest match to Color.
bool FindTableIndex(const COLORREF Color, bool FindTableIndex(const COLORREF Color,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> ColorTable,
const WORD cColorTable,
_Out_ WORD* const pFoundIndex) _Out_ WORD* const pFoundIndex)
{ {
*pFoundIndex = 0; *pFoundIndex = 0;
for (WORD i = 0; i < cColorTable; i++) for (WORD i = 0; i < ColorTable.size(); i++)
{ {
if (ColorTable[i] == Color) if (ColorTable[i] == Color)
{ {
@ -185,41 +167,3 @@ bool FindTableIndex(const COLORREF Color,
} }
return false; return false;
} }
// Method Description:
// - Get a COLORREF for the foreground component of the given legacy attributes.
// Arguments:
// - wLegacyAttrs - The legacy attributes to get the foreground color from.
// - ColorTable - The array of colors to get the color from.
// - cColorTable - The number of elements in ColorTable
// Return Value:
// - the COLORREF for the foreground component
COLORREF ForegroundColor(const WORD wLegacyAttrs,
_In_reads_(cColorTable) const COLORREF* const ColorTable,
const size_t cColorTable)
{
const byte iColorTableIndex = LOBYTE(wLegacyAttrs) & FG_ATTRS;
return (iColorTableIndex < cColorTable && iColorTableIndex >= 0) ?
ColorTable[iColorTableIndex] :
INVALID_COLOR;
}
// Method Description:
// - Get a COLORREF for the background component of the given legacy attributes.
// Arguments:
// - wLegacyAttrs - The legacy attributes to get the background color from.
// - ColorTable - The array of colors to get the color from.
// - cColorTable - The number of elements in ColorTable
// Return Value:
// - the COLORREF for the background component
COLORREF BackgroundColor(const WORD wLegacyAttrs,
_In_reads_(cColorTable) const COLORREF* const ColorTable,
const size_t cColorTable)
{
const byte iColorTableIndex = (LOBYTE(wLegacyAttrs) & BG_ATTRS) >> 4;
return (iColorTableIndex < cColorTable && iColorTableIndex >= 0) ?
ColorTable[iColorTableIndex] :
INVALID_COLOR;
}

View file

@ -572,7 +572,10 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
} }
const COORD newBufferSize = context.GetBufferSize().Dimensions(); const COORD newBufferSize = context.GetBufferSize().Dimensions();
gci.SetColorTable(data.ColorTable, ARRAYSIZE(data.ColorTable)); for (size_t i = 0; i < std::size(data.ColorTable); i++)
{
gci.SetColorTableEntry(i, data.ColorTable[i]);
}
context.SetDefaultAttributes({ data.wAttributes }, { data.wPopupAttributes }); context.SetDefaultAttributes({ data.wAttributes }, { data.wPopupAttributes });

View file

@ -360,7 +360,10 @@ void SCREEN_INFORMATION::GetScreenBufferInformation(_Out_ PCOORD pcoordSize,
*pwPopupAttributes = gci.GenerateLegacyAttributes(_PopupAttributes); *pwPopupAttributes = gci.GenerateLegacyAttributes(_PopupAttributes);
// the copy length must be constant for now to keep OACR happy with buffer overruns. // the copy length must be constant for now to keep OACR happy with buffer overruns.
memmove(lpColorTable, gci.GetColorTable(), COLOR_TABLE_SIZE * sizeof(COLORREF)); for (size_t i = 0; i < COLOR_TABLE_SIZE; i++)
{
lpColorTable[i] = gci.GetColorTableEntry(i);
}
*pcoordMaximumWindowSize = GetMaxWindowSizeInCharacters(); *pcoordMaximumWindowSize = GetMaxWindowSizeInCharacters();
} }

View file

@ -81,9 +81,8 @@ Settings::Settings() :
_CursorColor = Cursor::s_InvertCursorColor; _CursorColor = Cursor::s_InvertCursorColor;
_CursorType = CursorType::Legacy; _CursorType = CursorType::Legacy;
gsl::span<COLORREF> tableView = { _ColorTable, gsl::narrow<ptrdiff_t>(COLOR_TABLE_SIZE) }; gsl::span<COLORREF> tableView = { _colorTable.data(), gsl::narrow<ptrdiff_t>(_colorTable.size()) };
gsl::span<COLORREF> xtermTableView = { _XtermColorTable, gsl::narrow<ptrdiff_t>(XTERM_COLOR_TABLE_SIZE) }; ::Microsoft::Console::Utils::Initialize256ColorTable(tableView);
::Microsoft::Console::Utils::Initialize256ColorTable(xtermTableView);
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
} }
@ -123,7 +122,7 @@ void Settings::ApplyDesktopSpecificDefaults()
_uNumberOfHistoryBuffers = 4; _uNumberOfHistoryBuffers = 4;
_bHistoryNoDup = FALSE; _bHistoryNoDup = FALSE;
gsl::span<COLORREF> tableView = { _ColorTable, gsl::narrow<ptrdiff_t>(COLOR_TABLE_SIZE) }; gsl::span<COLORREF> tableView = { _colorTable.data(), gsl::narrow<ptrdiff_t>(_colorTable.size()) };
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
_fTrimLeadingZeros = false; _fTrimLeadingZeros = false;
@ -221,7 +220,10 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
_bHistoryNoDup = pStateInfo->HistoryNoDup; _bHistoryNoDup = pStateInfo->HistoryNoDup;
_uHistoryBufferSize = pStateInfo->HistoryBufferSize; _uHistoryBufferSize = pStateInfo->HistoryBufferSize;
_uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers; _uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers;
memmove(_ColorTable, pStateInfo->ColorTable, sizeof(_ColorTable)); for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
SetColorTableEntry(i, pStateInfo->ColorTable[i]);
}
_uCodePage = pStateInfo->CodePage; _uCodePage = pStateInfo->CodePage;
_bWrapText = !!pStateInfo->fWrapText; _bWrapText = !!pStateInfo->fWrapText;
_fFilterOnPaste = pStateInfo->fFilterOnPaste; _fFilterOnPaste = pStateInfo->fFilterOnPaste;
@ -263,7 +265,10 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
csi.HistoryNoDup = _bHistoryNoDup; csi.HistoryNoDup = _bHistoryNoDup;
csi.HistoryBufferSize = _uHistoryBufferSize; csi.HistoryBufferSize = _uHistoryBufferSize;
csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers; csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers;
memmove(csi.ColorTable, _ColorTable, sizeof(_ColorTable)); for (size_t i = 0; i < std::size(csi.ColorTable); i++)
{
csi.ColorTable[i] = GetColorTableEntry(i);
}
csi.CodePage = _uCodePage; csi.CodePage = _uCodePage;
csi.fWrapText = !!_bWrapText; csi.fWrapText = !!_bWrapText;
csi.fFilterOnPaste = _fFilterOnPaste; csi.fFilterOnPaste = _fFilterOnPaste;
@ -717,26 +722,19 @@ void Settings::SetHistoryNoDup(const bool bHistoryNoDup)
_bHistoryNoDup = bHistoryNoDup; _bHistoryNoDup = bHistoryNoDup;
} }
const COLORREF* const Settings::GetColorTable() const std::basic_string_view<COLORREF> Settings::Get16ColorTable() const
{ {
return _ColorTable; return Get256ColorTable().substr(0, 16);
} }
void Settings::SetColorTable(_In_reads_(cSize) const COLORREF* const pColorTable, const size_t cSize)
{
size_t cSizeWritten = std::min(cSize, static_cast<size_t>(COLOR_TABLE_SIZE));
memmove(_ColorTable, pColorTable, cSizeWritten * sizeof(COLORREF)); std::basic_string_view<COLORREF> Settings::Get256ColorTable() const
{
return { _colorTable.data(), _colorTable.size() };
} }
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue) void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
{ {
if (index < ARRAYSIZE(_ColorTable)) _colorTable.at(index) = ColorValue;
{
_ColorTable[index] = ColorValue;
}
else
{
_XtermColorTable[index] = ColorValue;
}
} }
bool Settings::IsStartupTitleIsLinkNameSet() const bool Settings::IsStartupTitleIsLinkNameSet() const
@ -754,21 +752,9 @@ void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset)
_dwStartupFlags &= ~dwFlagToUnset; _dwStartupFlags &= ~dwFlagToUnset;
} }
const size_t Settings::GetColorTableSize() const
{
return ARRAYSIZE(_ColorTable);
}
COLORREF Settings::GetColorTableEntry(const size_t index) const COLORREF Settings::GetColorTableEntry(const size_t index) const
{ {
if (index < ARRAYSIZE(_ColorTable)) return _colorTable.at(index);
{
return _ColorTable[index];
}
else
{
return _XtermColorTable[index];
}
} }
// Routine Description: // Routine Description:
@ -792,19 +778,21 @@ WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const
BYTE bgIndex = static_cast<BYTE>((_wFillAttribute & BG_ATTRS) >> 4); BYTE bgIndex = static_cast<BYTE>((_wFillAttribute & BG_ATTRS) >> 4);
// If the attributes have any RGB components, we need to match that RGB // If the attributes have any RGB components, we need to match that RGB
// color to a color table value. // color to a color table value.
if (attributes.IsRgb()) if (attributes.IsHighColor())
{ {
// If the attribute doesn't have a "default" colored *ground, look up // If the attribute doesn't have a "default" colored *ground, look up
// the nearest color table value for its *ground. // the nearest color table value for its *ground.
const COLORREF rgbForeground = LookupForegroundColor(attributes); if (!attributes.ForegroundIsDefault())
fgIndex = attributes.ForegroundIsDefault() ? {
fgIndex : const COLORREF rgbForeground = LookupForegroundColor(attributes);
static_cast<BYTE>(FindNearestTableIndex(rgbForeground)); fgIndex = static_cast<BYTE>(::FindNearestTableIndex(rgbForeground, Get16ColorTable()));
}
const COLORREF rgbBackground = LookupBackgroundColor(attributes); if (!attributes.BackgroundIsDefault())
bgIndex = attributes.BackgroundIsDefault() ? {
bgIndex : const COLORREF rgbBackground = LookupBackgroundColor(attributes);
static_cast<BYTE>(FindNearestTableIndex(rgbBackground)); bgIndex = static_cast<BYTE>(::FindNearestTableIndex(rgbBackground, Get16ColorTable()));
}
} }
// TextAttribute::GetLegacyAttributes(BYTE, BYTE) will use the legacy value // TextAttribute::GetLegacyAttributes(BYTE, BYTE) will use the legacy value
@ -815,19 +803,6 @@ WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const
return wCompleteAttr; return wCompleteAttr;
} }
//Routine Description:
// For a given RGB color Color, finds the nearest color from the array ColorTable, and returns the index of that match.
//Arguments:
// - Color - The RGB color to fine the nearest color to.
// - ColorTable - The array of colors to find a nearest color from.
// - cColorTable - The number of elements in ColorTable
// Return value:
// The index in ColorTable of the nearest match to Color.
WORD Settings::FindNearestTableIndex(const COLORREF Color) const
{
return ::FindNearestTableIndex(Color, _ColorTable, ARRAYSIZE(_ColorTable));
}
COLORREF Settings::GetCursorColor() const noexcept COLORREF Settings::GetCursorColor() const noexcept
{ {
return _CursorColor; return _CursorColor;
@ -924,7 +899,7 @@ bool Settings::GetUseDx() const noexcept
COLORREF Settings::CalculateDefaultForeground() const noexcept COLORREF Settings::CalculateDefaultForeground() const noexcept
{ {
const auto fg = GetDefaultForegroundColor(); const auto fg = GetDefaultForegroundColor();
return fg != INVALID_COLOR ? fg : ForegroundColor(GetFillAttribute(), GetColorTable(), GetColorTableSize()); return fg != INVALID_COLOR ? fg : GetColorTableEntry(LOBYTE(_wFillAttribute) & FG_ATTRS);
} }
// Method Description: // Method Description:
@ -939,7 +914,7 @@ COLORREF Settings::CalculateDefaultForeground() const noexcept
COLORREF Settings::CalculateDefaultBackground() const noexcept COLORREF Settings::CalculateDefaultBackground() const noexcept
{ {
const auto bg = GetDefaultBackgroundColor(); const auto bg = GetDefaultBackgroundColor();
return bg != INVALID_COLOR ? bg : BackgroundColor(GetFillAttribute(), GetColorTable(), GetColorTableSize()); return bg != INVALID_COLOR ? bg : GetColorTableEntry((LOBYTE(_wFillAttribute) & BG_ATTRS) >> 4);
} }
// Method Description: // Method Description:
@ -951,7 +926,7 @@ COLORREF Settings::CalculateDefaultBackground() const noexcept
// - The color value of the attribute's foreground TextColor. // - The color value of the attribute's foreground TextColor.
COLORREF Settings::LookupForegroundColor(const TextAttribute& attr) const noexcept COLORREF Settings::LookupForegroundColor(const TextAttribute& attr) const noexcept
{ {
const auto tableView = std::basic_string_view<COLORREF>(&GetColorTable()[0], GetColorTableSize()); const auto tableView = Get256ColorTable();
if (_fScreenReversed) if (_fScreenReversed)
{ {
return attr.CalculateRgbBackground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground()); return attr.CalculateRgbBackground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
@ -971,7 +946,7 @@ COLORREF Settings::LookupForegroundColor(const TextAttribute& attr) const noexce
// - The color value of the attribute's background TextColor. // - The color value of the attribute's background TextColor.
COLORREF Settings::LookupBackgroundColor(const TextAttribute& attr) const noexcept COLORREF Settings::LookupBackgroundColor(const TextAttribute& attr) const noexcept
{ {
const auto tableView = std::basic_string_view<COLORREF>(&GetColorTable()[0], GetColorTableSize()); const auto tableView = Get256ColorTable();
if (_fScreenReversed) if (_fScreenReversed)
{ {
return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground()); return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());

View file

@ -159,9 +159,8 @@ public:
bool GetHistoryNoDup() const; bool GetHistoryNoDup() const;
void SetHistoryNoDup(const bool fHistoryNoDup); void SetHistoryNoDup(const bool fHistoryNoDup);
const COLORREF* const GetColorTable() const; std::basic_string_view<COLORREF> Get16ColorTable() const;
const size_t GetColorTableSize() const; std::basic_string_view<COLORREF> Get256ColorTable() const;
void SetColorTable(_In_reads_(cSize) const COLORREF* const pColorTable, const size_t cSize);
void SetColorTableEntry(const size_t index, const COLORREF ColorValue); void SetColorTableEntry(const size_t index, const COLORREF ColorValue);
COLORREF GetColorTableEntry(const size_t index) const; COLORREF GetColorTableEntry(const size_t index) const;
@ -217,7 +216,6 @@ private:
UINT _uHistoryBufferSize; UINT _uHistoryBufferSize;
UINT _uNumberOfHistoryBuffers; UINT _uNumberOfHistoryBuffers;
BOOL _bHistoryNoDup; BOOL _bHistoryNoDup;
COLORREF _ColorTable[COLOR_TABLE_SIZE];
// END - memcpy // END - memcpy
UINT _uCodePage; UINT _uCodePage;
UINT _uScrollScale; UINT _uScrollScale;
@ -238,7 +236,7 @@ private:
bool _fUseDx; bool _fUseDx;
bool _fCopyColor; bool _fCopyColor;
COLORREF _XtermColorTable[XTERM_COLOR_TABLE_SIZE]; std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
// this is used for the special STARTF_USESIZE mode. // this is used for the special STARTF_USESIZE mode.
bool _fUseWindowSizePixels; bool _fUseWindowSizePixels;
@ -257,5 +255,4 @@ private:
public: public:
WORD GenerateLegacyAttributes(const TextAttribute attributes) const; WORD GenerateLegacyAttributes(const TextAttribute attributes) const;
WORD FindNearestTableIndex(const COLORREF Color) const;
}; };

View file

@ -419,7 +419,7 @@ void Telemetry::WriteFinalTraceLog()
TraceLoggingBool(gci.GetQuickEdit(), "QuickEdit"), TraceLoggingBool(gci.GetQuickEdit(), "QuickEdit"),
TraceLoggingValue(gci.GetWindowAlpha(), "WindowAlpha"), TraceLoggingValue(gci.GetWindowAlpha(), "WindowAlpha"),
TraceLoggingBool(gci.GetWrapText(), "WrapText"), TraceLoggingBool(gci.GetWrapText(), "WrapText"),
TraceLoggingUInt32Array((UINT32 const*)gci.GetColorTable(), (UINT16)gci.GetColorTableSize(), "ColorTable"), TraceLoggingUInt32Array((UINT32 const*)gci.Get16ColorTable().data(), (UINT16)gci.Get16ColorTable().size(), "ColorTable"),
TraceLoggingValue(gci.CP, "CodePageInput"), TraceLoggingValue(gci.CP, "CodePageInput"),
TraceLoggingValue(gci.OutputCP, "CodePageOutput"), TraceLoggingValue(gci.OutputCP, "CodePageOutput"),
TraceLoggingValue(gci.GetFontSize().X, "FontSizeX"), TraceLoggingValue(gci.GetFontSize().X, "FontSizeX"),
@ -453,7 +453,7 @@ void Telemetry::WriteFinalTraceLog()
TraceLoggingValue(gci.GetShowWindow(), "ShowWindow"), TraceLoggingValue(gci.GetShowWindow(), "ShowWindow"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage)); TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
static_assert(sizeof(UINT32) == sizeof(*gci.GetColorTable()), "gci.GetColorTable()"); static_assert(sizeof(UINT32) == sizeof(gci.Get16ColorTable()[0]), "gci.Get16ColorTable()");
// I could use the TraceLoggingUIntArray, but then we would have to know the order of the enums on the backend. // I could use the TraceLoggingUIntArray, but then we would have to know the order of the enums on the backend.
// So just log each enum count separately with its string representation which makes it more human readable. // So just log each enum count separately with its string representation which makes it more human readable.

View file

@ -88,8 +88,7 @@ class ConptyOutputTests
auto vtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hFile), auto vtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hFile),
gci, gci,
initialViewport, initialViewport,
gci.GetColorTable(), gci.Get16ColorTable());
static_cast<WORD>(gci.GetColorTableSize()));
auto pfn = std::bind(&ConptyOutputTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&ConptyOutputTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2);
vtRenderEngine->SetTestCallback(pfn); vtRenderEngine->SetTestCallback(pfn);

View file

@ -1844,7 +1844,9 @@ void ScreenBufferTests::VtEraseAllPersistCursorFillColor()
L"Change the colors to dark_red on bright_blue, then execute a Erase All.\n" L"Change the colors to dark_red on bright_blue, then execute a Erase All.\n"
L"The viewport should be full of dark_red on bright_blue")); L"The viewport should be full of dark_red on bright_blue"));
auto expectedAttr = TextAttribute(XtermToLegacy(1, 12)); auto expectedAttr = TextAttribute{};
expectedAttr.SetIndexedForeground((BYTE)XtermToWindowsIndex(1));
expectedAttr.SetIndexedBackground((BYTE)XtermToWindowsIndex(12));
stateMachine.ProcessString(L"\x1b[31;104m"); stateMachine.ProcessString(L"\x1b[31;104m");
VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes()); VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes());
@ -2222,12 +2224,14 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
// See the log comment above for description of these values. // See the log comment above for description of these values.
TextAttribute expectedDefaults{}; TextAttribute expectedDefaults{};
TextAttribute expectedTwo{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; TextAttribute expectedTwo;
TextAttribute expectedThree{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; expectedTwo.SetIndexedForeground((BYTE)XtermToWindowsIndex(10));
expectedTwo.SetIndexedBackground((BYTE)XtermToWindowsIndex(4));
TextAttribute expectedThree = expectedTwo;
expectedThree.SetDefaultForeground(); expectedThree.SetDefaultForeground();
// Four is the same as Defaults // Four is the same as Defaults
// Five is the same as two // Five is the same as two
TextAttribute expectedSix{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; TextAttribute expectedSix = expectedTwo;
expectedSix.SetDefaultBackground(); expectedSix.SetDefaultBackground();
COORD expectedCursor{ 6, 0 }; COORD expectedCursor{ 6, 0 };
@ -2324,7 +2328,7 @@ void ScreenBufferTests::SetDefaultsTogether()
// See the log comment above for description of these values. // See the log comment above for description of these values.
TextAttribute expectedDefaults{}; TextAttribute expectedDefaults{};
TextAttribute expectedTwo{}; TextAttribute expectedTwo{};
expectedTwo.SetBackground(color250); expectedTwo.SetIndexedBackground256(250);
COORD expectedCursor{ 3, 0 }; COORD expectedCursor{ 3, 0 };
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition()); VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
@ -4503,14 +4507,14 @@ void ScreenBufferTests::ScrollLines256Colors()
auto& cursor = si.GetTextBuffer().GetCursor(); auto& cursor = si.GetTextBuffer().GetCursor();
TextAttribute expectedAttr{ si.GetAttributes() }; TextAttribute expectedAttr{ si.GetAttributes() };
std::wstring_view sgrSeq = L"\x1b[48;5;2m"; std::wstring_view sgrSeq = L"\x1b[42m";
if (colorStyle == Use16Color) if (colorStyle == Use16Color)
{ {
expectedAttr.SetBackground(gci.GetColorTableEntry(2)); expectedAttr.SetIndexedBackground(2);
} }
else if (colorStyle == Use256Color) else if (colorStyle == Use256Color)
{ {
expectedAttr.SetBackground(gci.GetColorTableEntry(20)); expectedAttr.SetIndexedBackground256(20);
sgrSeq = L"\x1b[48;5;20m"; sgrSeq = L"\x1b[48;5;20m";
} }
else if (colorStyle == UseRGBColor) else if (colorStyle == UseRGBColor)
@ -5237,7 +5241,7 @@ void ScreenBufferTests::TestExtendedTextAttributesWithColors()
} }
else if (setForegroundType == Use256Color) else if (setForegroundType == Use256Color)
{ {
expectedAttr.SetForeground(gci.GetColorTableEntry(20)); expectedAttr.SetIndexedForeground256(20);
vtSeq += L"\x1b[38;5;20m"; vtSeq += L"\x1b[38;5;20m";
} }
else if (setForegroundType == UseRGBColor) else if (setForegroundType == UseRGBColor)
@ -5259,7 +5263,7 @@ void ScreenBufferTests::TestExtendedTextAttributesWithColors()
} }
else if (setBackgroundType == Use256Color) else if (setBackgroundType == Use256Color)
{ {
expectedAttr.SetBackground(gci.GetColorTableEntry(20)); expectedAttr.SetIndexedBackground256(20);
vtSeq += L"\x1b[48;5;20m"; vtSeq += L"\x1b[48;5;20m";
} }
else if (setBackgroundType == UseRGBColor) else if (setBackgroundType == UseRGBColor)

View file

@ -498,7 +498,7 @@ void TextBufferIteratorTests::DereferenceOperatorCell()
const auto textExpected = (std::wstring_view)row.GetCharRow().GlyphAt(it._pos.X); const auto textExpected = (std::wstring_view)row.GetCharRow().GlyphAt(it._pos.X);
const auto dbcsExpected = row.GetCharRow().DbcsAttrAt(it._pos.X); const auto dbcsExpected = row.GetCharRow().DbcsAttrAt(it._pos.X);
const auto attrExpected = row.GetAttrRow().GetAttrByColumn(it._pos.X).GetLegacyAttributes(); const auto attrExpected = row.GetAttrRow().GetAttrByColumn(it._pos.X);
const auto cellActual = *it; const auto cellActual = *it;
const auto textActual = cellActual.Chars(); const auto textActual = cellActual.Chars();

View file

@ -124,28 +124,28 @@ void VtIoTests::DtorTestJustEngine()
wil::unique_hfile hOutputFile; wil::unique_hfile hOutputFile;
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
auto pRenderer256 = new Xterm256Engine(std::move(hOutputFile), p, SetUpViewport(), colorTable, colorTableSize); auto pRenderer256 = new Xterm256Engine(std::move(hOutputFile), p, SetUpViewport(), colorTable);
Log::Comment(NoThrowString().Format(L"Made Xterm256Engine")); Log::Comment(NoThrowString().Format(L"Made Xterm256Engine"));
delete pRenderer256; delete pRenderer256;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
auto pRenderEngineXterm = new XtermEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable, colorTableSize, false); auto pRenderEngineXterm = new XtermEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable, false);
Log::Comment(NoThrowString().Format(L"Made XtermEngine")); Log::Comment(NoThrowString().Format(L"Made XtermEngine"));
delete pRenderEngineXterm; delete pRenderEngineXterm;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
auto pRenderEngineXtermAscii = new XtermEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable, colorTableSize, true); auto pRenderEngineXtermAscii = new XtermEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable, true);
Log::Comment(NoThrowString().Format(L"Made XtermEngine")); Log::Comment(NoThrowString().Format(L"Made XtermEngine"));
delete pRenderEngineXtermAscii; delete pRenderEngineXtermAscii;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
auto pRenderEngineWinTelnet = new WinTelnetEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable, colorTableSize); auto pRenderEngineWinTelnet = new WinTelnetEngine(std::move(hOutputFile), p, SetUpViewport(), colorTable);
Log::Comment(NoThrowString().Format(L"Made WinTelnetEngine")); Log::Comment(NoThrowString().Format(L"Made WinTelnetEngine"));
delete pRenderEngineWinTelnet; delete pRenderEngineWinTelnet;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
@ -180,8 +180,7 @@ void VtIoTests::DtorTestDeleteVtio()
vtio->_pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile), vtio->_pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
Log::Comment(NoThrowString().Format(L"Made Xterm256Engine")); Log::Comment(NoThrowString().Format(L"Made Xterm256Engine"));
delete vtio; delete vtio;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
@ -193,7 +192,6 @@ void VtIoTests::DtorTestDeleteVtio()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
false); false);
Log::Comment(NoThrowString().Format(L"Made XtermEngine")); Log::Comment(NoThrowString().Format(L"Made XtermEngine"));
delete vtio; delete vtio;
@ -206,7 +204,6 @@ void VtIoTests::DtorTestDeleteVtio()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
true); true);
Log::Comment(NoThrowString().Format(L"Made XtermEngine")); Log::Comment(NoThrowString().Format(L"Made XtermEngine"));
delete vtio; delete vtio;
@ -218,8 +215,7 @@ void VtIoTests::DtorTestDeleteVtio()
vtio->_pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile), vtio->_pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
Log::Comment(NoThrowString().Format(L"Made WinTelnetEngine")); Log::Comment(NoThrowString().Format(L"Made WinTelnetEngine"));
delete vtio; delete vtio;
Log::Comment(NoThrowString().Format(L"Deleted.")); Log::Comment(NoThrowString().Format(L"Deleted."));
@ -253,8 +249,7 @@ void VtIoTests::DtorTestStackAlloc()
vtio._pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile), vtio._pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
} }
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
@ -264,7 +259,6 @@ void VtIoTests::DtorTestStackAlloc()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
false); false);
} }
@ -275,7 +269,6 @@ void VtIoTests::DtorTestStackAlloc()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
true); true);
} }
@ -285,8 +278,7 @@ void VtIoTests::DtorTestStackAlloc()
vtio._pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile), vtio._pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
} }
} }
} }
@ -317,8 +309,7 @@ void VtIoTests::DtorTestStackAllocMany()
vtio1._pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile), vtio1._pVtRenderEngine = std::make_unique<Xterm256Engine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
VtIo vtio2; VtIo vtio2;
@ -326,7 +317,6 @@ void VtIoTests::DtorTestStackAllocMany()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
false); false);
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
@ -335,7 +325,6 @@ void VtIoTests::DtorTestStackAllocMany()
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable,
colorTableSize,
true); true);
hOutputFile.reset(INVALID_HANDLE_VALUE); hOutputFile.reset(INVALID_HANDLE_VALUE);
@ -343,8 +332,7 @@ void VtIoTests::DtorTestStackAllocMany()
vtio4._pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile), vtio4._pVtRenderEngine = std::make_unique<WinTelnetEngine>(std::move(hOutputFile),
p, p,
SetUpViewport(), SetUpViewport(),
colorTable, colorTable);
colorTableSize);
} }
} }
} }

View file

@ -189,7 +189,7 @@ void VtRendererTest::TestPaint(VtEngine& engine, std::function<void()> pfn)
void VtRendererTest::VtSequenceHelperTests() void VtRendererTest::VtSequenceHelperTests()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -246,7 +246,7 @@ void VtRendererTest::VtSequenceHelperTests()
void VtRendererTest::Xterm256TestInvalidate() void VtRendererTest::Xterm256TestInvalidate()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -434,7 +434,7 @@ void VtRendererTest::Xterm256TestInvalidate()
void VtRendererTest::Xterm256TestColors() void VtRendererTest::Xterm256TestColors()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -571,7 +571,7 @@ void VtRendererTest::Xterm256TestColors()
void VtRendererTest::Xterm256TestCursor() void VtRendererTest::Xterm256TestCursor()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -723,7 +723,7 @@ void VtRendererTest::Xterm256TestExtendedAttributes()
} }
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -767,7 +767,7 @@ void VtRendererTest::Xterm256TestExtendedAttributes()
void VtRendererTest::XtermTestInvalidate() void VtRendererTest::XtermTestInvalidate()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE), false); std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, false);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -954,7 +954,7 @@ void VtRendererTest::XtermTestInvalidate()
void VtRendererTest::XtermTestColors() void VtRendererTest::XtermTestColors()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE), false); std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, false);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1040,7 +1040,7 @@ void VtRendererTest::XtermTestColors()
void VtRendererTest::XtermTestCursor() void VtRendererTest::XtermTestCursor()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE), false); std::unique_ptr<XtermEngine> engine = std::make_unique<XtermEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, false);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1149,7 +1149,7 @@ void VtRendererTest::XtermTestCursor()
void VtRendererTest::WinTelnetTestInvalidate() void VtRendererTest::WinTelnetTestInvalidate()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1221,7 +1221,7 @@ void VtRendererTest::WinTelnetTestInvalidate()
void VtRendererTest::WinTelnetTestColors() void VtRendererTest::WinTelnetTestColors()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1299,7 +1299,7 @@ void VtRendererTest::WinTelnetTestColors()
void VtRendererTest::WinTelnetTestCursor() void VtRendererTest::WinTelnetTestCursor()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<WinTelnetEngine> engine = std::make_unique<WinTelnetEngine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1379,7 +1379,7 @@ void VtRendererTest::WinTelnetTestCursor()
void VtRendererTest::TestWrapping() void VtRendererTest::TestWrapping()
{ {
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); std::unique_ptr<Xterm256Engine> engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, SetUpViewport(), g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1432,7 +1432,7 @@ void VtRendererTest::TestResize()
{ {
Viewport view = SetUpViewport(); Viewport view = SetUpViewport();
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1469,7 +1469,7 @@ void VtRendererTest::TestCursorVisibility()
{ {
Viewport view = SetUpViewport(); Viewport view = SetUpViewport();
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);
@ -1594,7 +1594,7 @@ void VtRendererTest::FormattedString()
Viewport view = SetUpViewport(); Viewport view = SetUpViewport();
wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE);
auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable, static_cast<WORD>(COLOR_TABLE_SIZE)); auto engine = std::make_unique<Xterm256Engine>(std::move(hFile), p, view, g_ColorTable);
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn); engine->SetTestCallback(pfn);

View file

@ -24,26 +24,16 @@ enum class ExtendedAttributes : BYTE
DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes); DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes);
WORD FindNearestTableIndex(const COLORREF Color, WORD FindNearestTableIndex(const COLORREF Color,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> ColorTable);
const WORD cColorTable);
bool FindTableIndex(const COLORREF Color, bool FindTableIndex(const COLORREF Color,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> ColorTable,
const WORD cColorTable,
_Out_ WORD* const pFoundIndex); _Out_ WORD* const pFoundIndex);
WORD XtermToWindowsIndex(const size_t index) noexcept; WORD XtermToWindowsIndex(const size_t index) noexcept;
WORD Xterm256ToWindowsIndex(const size_t index) noexcept; WORD Xterm256ToWindowsIndex(const size_t index) noexcept;
WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground); WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground);
COLORREF ForegroundColor(const WORD wLegacyAttrs,
_In_reads_(cColorTable) const COLORREF* const ColorTable,
const size_t cColorTable);
COLORREF BackgroundColor(const WORD wLegacyAttrs,
_In_reads_(cColorTable) const COLORREF* const ColorTable,
const size_t cColorTable);
const WORD WINDOWS_RED_ATTR = FOREGROUND_RED; const WORD WINDOWS_RED_ATTR = FOREGROUND_RED;
const WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN; const WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN;
const WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE; const WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE;

View file

@ -335,7 +335,10 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
pStateInfo->NumberOfHistoryBuffers = gci.GetNumberOfHistoryBuffers(); pStateInfo->NumberOfHistoryBuffers = gci.GetNumberOfHistoryBuffers();
pStateInfo->HistoryNoDup = !!(gci.Flags & CONSOLE_HISTORY_NODUP); pStateInfo->HistoryNoDup = !!(gci.Flags & CONSOLE_HISTORY_NODUP);
memmove(pStateInfo->ColorTable, gci.GetColorTable(), gci.GetColorTableSize() * sizeof(COLORREF)); for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
pStateInfo->ColorTable[i] = gci.GetColorTableEntry(i);
}
// Create mutable copies of the titles so the propsheet can do something with them. // Create mutable copies of the titles so the propsheet can do something with them.
if (gci.GetOriginalTitle().length() > 0) if (gci.GetOriginalTitle().length() > 0)
@ -562,7 +565,10 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
} }
} }
gci.SetColorTable(pStateInfo->ColorTable, gci.GetColorTableSize()); for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
gci.SetColorTableEntry(i, pStateInfo->ColorTable[i]);
}
// Ensure that attributes only contain color specification. // Ensure that attributes only contain color specification.
WI_ClearAllFlags(pStateInfo->ScreenAttributes, ~(FG_ATTRS | BG_ATTRS)); WI_ClearAllFlags(pStateInfo->ScreenAttributes, ~(FG_ATTRS | BG_ATTRS));

View file

@ -12,11 +12,9 @@ using namespace Microsoft::Console::Types;
WinTelnetEngine::WinTelnetEngine(_In_ wil::unique_hfile hPipe, WinTelnetEngine::WinTelnetEngine(_In_ wil::unique_hfile hPipe,
const IDefaultColorProvider& colorProvider, const IDefaultColorProvider& colorProvider,
const Viewport initialViewport, const Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) :
const WORD cColorTable) :
VtEngine(std::move(hPipe), colorProvider, initialViewport), VtEngine(std::move(hPipe), colorProvider, initialViewport),
_ColorTable(ColorTable), _colorTable(colorTable)
_cColorTable(cColorTable)
{ {
} }
@ -42,8 +40,7 @@ WinTelnetEngine::WinTelnetEngine(_In_ wil::unique_hfile hPipe,
return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground, return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground,
colorBackground, colorBackground,
WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold),
_ColorTable, _colorTable);
_cColorTable);
} }
// Routine Description: // Routine Description:

View file

@ -26,8 +26,7 @@ namespace Microsoft::Console::Render
WinTelnetEngine(_In_ wil::unique_hfile hPipe, WinTelnetEngine(_In_ wil::unique_hfile hPipe,
const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::IDefaultColorProvider& colorProvider,
const Microsoft::Console::Types::Viewport initialViewport, const Microsoft::Console::Types::Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable);
const WORD cColorTable);
virtual ~WinTelnetEngine() override = default; virtual ~WinTelnetEngine() override = default;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const COLORREF colorForeground, [[nodiscard]] HRESULT UpdateDrawingBrushes(const COLORREF colorForeground,
@ -45,8 +44,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept; [[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept;
private: private:
const COLORREF* const _ColorTable; const std::basic_string_view<COLORREF> _colorTable;
const WORD _cColorTable;
#ifdef UNIT_TESTING #ifdef UNIT_TESTING
friend class VtRendererTest; friend class VtRendererTest;

View file

@ -11,9 +11,8 @@ using namespace Microsoft::Console::Types;
Xterm256Engine::Xterm256Engine(_In_ wil::unique_hfile hPipe, Xterm256Engine::Xterm256Engine(_In_ wil::unique_hfile hPipe,
const IDefaultColorProvider& colorProvider, const IDefaultColorProvider& colorProvider,
const Viewport initialViewport, const Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) :
const WORD cColorTable) : XtermEngine(std::move(hPipe), colorProvider, initialViewport, colorTable, false),
XtermEngine(std::move(hPipe), colorProvider, initialViewport, ColorTable, cColorTable, false),
_lastExtendedAttrsState{ ExtendedAttributes::Normal } _lastExtendedAttrsState{ ExtendedAttributes::Normal }
{ {
} }
@ -52,8 +51,7 @@ Xterm256Engine::Xterm256Engine(_In_ wil::unique_hfile hPipe,
return VtEngine::_RgbUpdateDrawingBrushes(colorForeground, return VtEngine::_RgbUpdateDrawingBrushes(colorForeground,
colorBackground, colorBackground,
WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold),
_ColorTable, _colorTable);
_cColorTable);
} }
// Routine Description: // Routine Description:

View file

@ -26,8 +26,7 @@ namespace Microsoft::Console::Render
Xterm256Engine(_In_ wil::unique_hfile hPipe, Xterm256Engine(_In_ wil::unique_hfile hPipe,
const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::IDefaultColorProvider& colorProvider,
const Microsoft::Console::Types::Viewport initialViewport, const Microsoft::Console::Types::Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable);
const WORD cColorTable);
virtual ~Xterm256Engine() override = default; virtual ~Xterm256Engine() override = default;

View file

@ -12,12 +12,10 @@ using namespace Microsoft::Console::Types;
XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
const IDefaultColorProvider& colorProvider, const IDefaultColorProvider& colorProvider,
const Viewport initialViewport, const Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable,
const WORD cColorTable,
const bool fUseAsciiOnly) : const bool fUseAsciiOnly) :
VtEngine(std::move(hPipe), colorProvider, initialViewport), VtEngine(std::move(hPipe), colorProvider, initialViewport),
_ColorTable(ColorTable), _colorTable(colorTable),
_cColorTable(cColorTable),
_fUseAsciiOnly(fUseAsciiOnly), _fUseAsciiOnly(fUseAsciiOnly),
_usingUnderLine(false), _usingUnderLine(false),
_needToDisableCursor(false), _needToDisableCursor(false),
@ -192,8 +190,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground, return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground,
colorBackground, colorBackground,
WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold),
_ColorTable, _colorTable);
_cColorTable);
} }
// Routine Description: // Routine Description:

View file

@ -30,8 +30,7 @@ namespace Microsoft::Console::Render
XtermEngine(_In_ wil::unique_hfile hPipe, XtermEngine(_In_ wil::unique_hfile hPipe,
const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::IDefaultColorProvider& colorProvider,
const Microsoft::Console::Types::Viewport initialViewport, const Microsoft::Console::Types::Viewport initialViewport,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable,
const WORD cColorTable,
const bool fUseAsciiOnly); const bool fUseAsciiOnly);
virtual ~XtermEngine() override = default; virtual ~XtermEngine() override = default;
@ -57,8 +56,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override; [[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override;
protected: protected:
const COLORREF* const _ColorTable; const std::basic_string_view<COLORREF> _colorTable;
const WORD _cColorTable;
const bool _fUseAsciiOnly; const bool _fUseAsciiOnly;
bool _usingUnderLine; bool _usingUnderLine;
bool _needToDisableCursor; bool _needToDisableCursor;

View file

@ -192,8 +192,7 @@ using namespace Microsoft::Console::Types;
[[nodiscard]] HRESULT VtEngine::_RgbUpdateDrawingBrushes(const COLORREF colorForeground, [[nodiscard]] HRESULT VtEngine::_RgbUpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground, const COLORREF colorBackground,
const bool isBold, const bool isBold,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) noexcept
const WORD cColorTable) noexcept
{ {
const bool fgChanged = colorForeground != _LastFG; const bool fgChanged = colorForeground != _LastFG;
const bool bgChanged = colorBackground != _LastBG; const bool bgChanged = colorBackground != _LastBG;
@ -232,7 +231,7 @@ using namespace Microsoft::Console::Types;
{ {
RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(true)); RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(true));
} }
else if (::FindTableIndex(colorForeground, ColorTable, cColorTable, &wFoundColor)) else if (::FindTableIndex(colorForeground, colorTable, &wFoundColor))
{ {
RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, true)); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, true));
} }
@ -249,7 +248,7 @@ using namespace Microsoft::Console::Types;
{ {
RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(false)); RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(false));
} }
else if (::FindTableIndex(colorBackground, ColorTable, cColorTable, &wFoundColor)) else if (::FindTableIndex(colorBackground, colorTable, &wFoundColor))
{ {
RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, false)); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, false));
} }
@ -278,8 +277,7 @@ using namespace Microsoft::Console::Types;
[[nodiscard]] HRESULT VtEngine::_16ColorUpdateDrawingBrushes(const COLORREF colorForeground, [[nodiscard]] HRESULT VtEngine::_16ColorUpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground, const COLORREF colorBackground,
const bool isBold, const bool isBold,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) noexcept
const WORD cColorTable) noexcept
{ {
const bool fgChanged = colorForeground != _LastFG; const bool fgChanged = colorForeground != _LastFG;
const bool bgChanged = colorBackground != _LastBG; const bool bgChanged = colorBackground != _LastBG;
@ -312,7 +310,7 @@ using namespace Microsoft::Console::Types;
if (fgChanged) if (fgChanged)
{ {
const WORD wNearestFg = ::FindNearestTableIndex(colorForeground, ColorTable, cColorTable); const WORD wNearestFg = ::FindNearestTableIndex(colorForeground, colorTable);
RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestFg, true)); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestFg, true));
_LastFG = colorForeground; _LastFG = colorForeground;
@ -320,7 +318,7 @@ using namespace Microsoft::Console::Types;
if (bgChanged) if (bgChanged)
{ {
const WORD wNearestBg = ::FindNearestTableIndex(colorBackground, ColorTable, cColorTable); const WORD wNearestBg = ::FindNearestTableIndex(colorBackground, colorTable);
RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestBg, false)); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestBg, false));
_LastBG = colorBackground; _LastBG = colorBackground;

View file

@ -212,13 +212,11 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const COLORREF colorForeground, [[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground, const COLORREF colorBackground,
const bool isBold, const bool isBold,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) noexcept;
const WORD cColorTable) noexcept;
[[nodiscard]] HRESULT _16ColorUpdateDrawingBrushes(const COLORREF colorForeground, [[nodiscard]] HRESULT _16ColorUpdateDrawingBrushes(const COLORREF colorForeground,
const COLORREF colorBackground, const COLORREF colorBackground,
const bool isBold, const bool isBold,
_In_reads_(cColorTable) const COLORREF* const ColorTable, const std::basic_string_view<COLORREF> colorTable) noexcept;
const WORD cColorTable) noexcept;
bool _WillWriteSingleChar() const; bool _WillWriteSingleChar() const;

View file

@ -178,6 +178,6 @@ namespace Microsoft::Console::VirtualTerminal
size_t _SetRgbColorsHelper(const std::basic_string_view<DispatchTypes::GraphicsOptions> options, size_t _SetRgbColorsHelper(const std::basic_string_view<DispatchTypes::GraphicsOptions> options,
TextAttribute& attr, TextAttribute& attr,
const bool isForeground); const bool isForeground) noexcept;
}; };
} }

View file

@ -49,7 +49,7 @@ const BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR;
// - The number of options consumed, not including the initial 38/48. // - The number of options consumed, not including the initial 38/48.
size_t AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchTypes::GraphicsOptions> options, size_t AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchTypes::GraphicsOptions> options,
TextAttribute& attr, TextAttribute& attr,
const bool isForeground) const bool isForeground) noexcept
{ {
size_t optionsConsumed = 0; size_t optionsConsumed = 0;
if (options.size() >= 1) if (options.size() >= 1)
@ -73,11 +73,17 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchT
{ {
optionsConsumed = 2; optionsConsumed = 2;
const size_t tableIndex = til::at(options, 1); const size_t tableIndex = til::at(options, 1);
COLORREF rgbColor; if (tableIndex <= 255)
if (_pConApi->PrivateGetColorTableEntry(tableIndex, rgbColor))
{ {
// TODO GH#1223: Decouple xterm-256color indexed storage from RGB storage const auto adjustedIndex = gsl::narrow_cast<BYTE>(::Xterm256ToWindowsIndex(tableIndex));
attr.SetColor(rgbColor, isForeground); if (isForeground)
{
attr.SetIndexedForeground256(adjustedIndex);
}
else
{
attr.SetIndexedBackground256(adjustedIndex);
}
} }
} }
} }

View file

@ -1286,42 +1286,50 @@ public:
case DispatchTypes::GraphicsOptions::ForegroundBlack: case DispatchTypes::GraphicsOptions::ForegroundBlack:
Log::Comment(L"Testing graphics 'Foreground Color Black'"); Log::Comment(L"Testing graphics 'Foreground Color Black'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = 0; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(0);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundBlue: case DispatchTypes::GraphicsOptions::ForegroundBlue:
Log::Comment(L"Testing graphics 'Foreground Color Blue'"); Log::Comment(L"Testing graphics 'Foreground Color Blue'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_BLUE; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundGreen: case DispatchTypes::GraphicsOptions::ForegroundGreen:
Log::Comment(L"Testing graphics 'Foreground Color Green'"); Log::Comment(L"Testing graphics 'Foreground Color Green'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundCyan: case DispatchTypes::GraphicsOptions::ForegroundCyan:
Log::Comment(L"Testing graphics 'Foreground Color Cyan'"); Log::Comment(L"Testing graphics 'Foreground Color Cyan'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundRed: case DispatchTypes::GraphicsOptions::ForegroundRed:
Log::Comment(L"Testing graphics 'Foreground Color Red'"); Log::Comment(L"Testing graphics 'Foreground Color Red'");
_testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundMagenta: case DispatchTypes::GraphicsOptions::ForegroundMagenta:
Log::Comment(L"Testing graphics 'Foreground Color Magenta'"); Log::Comment(L"Testing graphics 'Foreground Color Magenta'");
_testGetSet->_attribute = FOREGROUND_GREEN | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_BLUE | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundYellow: case DispatchTypes::GraphicsOptions::ForegroundYellow:
Log::Comment(L"Testing graphics 'Foreground Color Yellow'"); Log::Comment(L"Testing graphics 'Foreground Color Yellow'");
_testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_GREEN | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundWhite: case DispatchTypes::GraphicsOptions::ForegroundWhite:
Log::Comment(L"Testing graphics 'Foreground Color White'"); Log::Comment(L"Testing graphics 'Foreground Color White'");
_testGetSet->_attribute = FOREGROUND_INTENSITY; _testGetSet->_attribute = FOREGROUND_INTENSITY;
_testGetSet->_expectedAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::ForegroundDefault: case DispatchTypes::GraphicsOptions::ForegroundDefault:
Log::Comment(L"Testing graphics 'Foreground Color Default'"); Log::Comment(L"Testing graphics 'Foreground Color Default'");
@ -1333,42 +1341,50 @@ public:
case DispatchTypes::GraphicsOptions::BackgroundBlack: case DispatchTypes::GraphicsOptions::BackgroundBlack:
Log::Comment(L"Testing graphics 'Background Color Black'"); Log::Comment(L"Testing graphics 'Background Color Black'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = 0; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(0);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundBlue: case DispatchTypes::GraphicsOptions::BackgroundBlue:
Log::Comment(L"Testing graphics 'Background Color Blue'"); Log::Comment(L"Testing graphics 'Background Color Blue'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_BLUE; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundGreen: case DispatchTypes::GraphicsOptions::BackgroundGreen:
Log::Comment(L"Testing graphics 'Background Color Green'"); Log::Comment(L"Testing graphics 'Background Color Green'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundCyan: case DispatchTypes::GraphicsOptions::BackgroundCyan:
Log::Comment(L"Testing graphics 'Background Color Cyan'"); Log::Comment(L"Testing graphics 'Background Color Cyan'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_BLUE | BACKGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundRed: case DispatchTypes::GraphicsOptions::BackgroundRed:
Log::Comment(L"Testing graphics 'Background Color Red'"); Log::Comment(L"Testing graphics 'Background Color Red'");
_testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_RED >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundMagenta: case DispatchTypes::GraphicsOptions::BackgroundMagenta:
Log::Comment(L"Testing graphics 'Background Color Magenta'"); Log::Comment(L"Testing graphics 'Background Color Magenta'");
_testGetSet->_attribute = BACKGROUND_GREEN | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_GREEN | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_BLUE | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundYellow: case DispatchTypes::GraphicsOptions::BackgroundYellow:
Log::Comment(L"Testing graphics 'Background Color Yellow'"); Log::Comment(L"Testing graphics 'Background Color Yellow'");
_testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_GREEN | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundWhite: case DispatchTypes::GraphicsOptions::BackgroundWhite:
Log::Comment(L"Testing graphics 'Background Color White'"); Log::Comment(L"Testing graphics 'Background Color White'");
_testGetSet->_attribute = BACKGROUND_INTENSITY; _testGetSet->_attribute = BACKGROUND_INTENSITY;
_testGetSet->_expectedAttribute = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BackgroundDefault: case DispatchTypes::GraphicsOptions::BackgroundDefault:
Log::Comment(L"Testing graphics 'Background Color Default'"); Log::Comment(L"Testing graphics 'Background Color Default'");
@ -1380,82 +1396,98 @@ public:
case DispatchTypes::GraphicsOptions::BrightForegroundBlack: case DispatchTypes::GraphicsOptions::BrightForegroundBlack:
Log::Comment(L"Testing graphics 'Bright Foreground Color Black'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Black'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundBlue: case DispatchTypes::GraphicsOptions::BrightForegroundBlue:
Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_BLUE; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundGreen: case DispatchTypes::GraphicsOptions::BrightForegroundGreen:
Log::Comment(L"Testing graphics 'Bright Foreground Color Green'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Green'");
_testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE; _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundCyan: case DispatchTypes::GraphicsOptions::BrightForegroundCyan:
Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'");
_testGetSet->_attribute = FOREGROUND_RED; _testGetSet->_attribute = FOREGROUND_RED;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundRed: case DispatchTypes::GraphicsOptions::BrightForegroundRed:
Log::Comment(L"Testing graphics 'Bright Foreground Color Red'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Red'");
_testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN; _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundMagenta: case DispatchTypes::GraphicsOptions::BrightForegroundMagenta:
Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'");
_testGetSet->_attribute = FOREGROUND_GREEN; _testGetSet->_attribute = FOREGROUND_GREEN;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundYellow: case DispatchTypes::GraphicsOptions::BrightForegroundYellow:
Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'"); Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'");
_testGetSet->_attribute = FOREGROUND_BLUE; _testGetSet->_attribute = FOREGROUND_BLUE;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::BrightForegroundWhite: case DispatchTypes::GraphicsOptions::BrightForegroundWhite:
Log::Comment(L"Testing graphics 'Bright Foreground Color White'"); Log::Comment(L"Testing graphics 'Bright Foreground Color White'");
_testGetSet->_attribute = 0; _testGetSet->_attribute = 0;
_testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundBlack: case DispatchTypes::GraphicsOptions::BrightBackgroundBlack:
Log::Comment(L"Testing graphics 'Bright Background Color Black'"); Log::Comment(L"Testing graphics 'Bright Background Color Black'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_INTENSITY >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundBlue: case DispatchTypes::GraphicsOptions::BrightBackgroundBlue:
Log::Comment(L"Testing graphics 'Bright Background Color Blue'"); Log::Comment(L"Testing graphics 'Bright Background Color Blue'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_BLUE; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundGreen: case DispatchTypes::GraphicsOptions::BrightBackgroundGreen:
Log::Comment(L"Testing graphics 'Bright Background Color Green'"); Log::Comment(L"Testing graphics 'Bright Background Color Green'");
_testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_BLUE; _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_BLUE;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundCyan: case DispatchTypes::GraphicsOptions::BrightBackgroundCyan:
Log::Comment(L"Testing graphics 'Bright Background Color Cyan'"); Log::Comment(L"Testing graphics 'Bright Background Color Cyan'");
_testGetSet->_attribute = BACKGROUND_RED; _testGetSet->_attribute = BACKGROUND_RED;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundRed: case DispatchTypes::GraphicsOptions::BrightBackgroundRed:
Log::Comment(L"Testing graphics 'Bright Background Color Red'"); Log::Comment(L"Testing graphics 'Bright Background Color Red'");
_testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_GREEN; _testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_GREEN;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta: case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta:
Log::Comment(L"Testing graphics 'Bright Background Color Magenta'"); Log::Comment(L"Testing graphics 'Bright Background Color Magenta'");
_testGetSet->_attribute = BACKGROUND_GREEN; _testGetSet->_attribute = BACKGROUND_GREEN;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundYellow: case DispatchTypes::GraphicsOptions::BrightBackgroundYellow:
Log::Comment(L"Testing graphics 'Bright Background Color Yellow'"); Log::Comment(L"Testing graphics 'Bright Background Color Yellow'");
_testGetSet->_attribute = BACKGROUND_BLUE; _testGetSet->_attribute = BACKGROUND_BLUE;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
break; break;
case DispatchTypes::GraphicsOptions::BrightBackgroundWhite: case DispatchTypes::GraphicsOptions::BrightBackgroundWhite:
Log::Comment(L"Testing graphics 'Bright Background Color White'"); Log::Comment(L"Testing graphics 'Bright Background Color White'");
_testGetSet->_attribute = 0; _testGetSet->_attribute = 0;
_testGetSet->_expectedAttribute = BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
break; break;
default: default:
VERIFY_FAIL(L"Test not implemented yet!"); VERIFY_FAIL(L"Test not implemented yet!");
@ -1880,32 +1912,28 @@ public:
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green
_testGetSet->_expectedAttribute.SetForeground(2); _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(2));
_testGetSet->_expectedColorTableIndex = 2;
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Test 2: Change Background"); Log::Comment(L"Test 2: Change Background");
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
_testGetSet->_expectedAttribute.SetBackground(9); _testGetSet->_expectedAttribute.SetIndexedBackground256((BYTE)::XtermToWindowsIndex(9));
_testGetSet->_expectedColorTableIndex = 9;
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Test 3: Change Foreground to RGB color"); Log::Comment(L"Test 3: Change Foreground to RGB color");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)42; // Arbitrary Color rgOptions[2] = (DispatchTypes::GraphicsOptions)42; // Arbitrary Color
_testGetSet->_expectedColorTableIndex = 42; _testGetSet->_expectedAttribute.SetIndexedForeground256(42);
_testGetSet->_expectedAttribute.SetForeground(42);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Test 4: Change Background to RGB color"); Log::Comment(L"Test 4: Change Background to RGB color");
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)142; // Arbitrary Color rgOptions[2] = (DispatchTypes::GraphicsOptions)142; // Arbitrary Color
_testGetSet->_expectedColorTableIndex = 142; _testGetSet->_expectedAttribute.SetIndexedBackground256(142);
_testGetSet->_expectedAttribute.SetBackground(142);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Test 5: Change Foreground to Legacy Attr while BG is RGB color"); Log::Comment(L"Test 5: Change Foreground to Legacy Attr while BG is RGB color");
@ -1915,8 +1943,7 @@ public:
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
_testGetSet->_expectedAttribute.SetForeground(9); _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(9));
_testGetSet->_expectedColorTableIndex = 9;
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
} }

View file

@ -2,7 +2,8 @@
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<!-- See https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2017#BKMK_Syntax_reference for documentation --> <!-- See https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2017#BKMK_Syntax_reference for documentation -->
<Type Name="TextColor"> <Type Name="TextColor">
<DisplayString Condition="_meta==ColorType::IsIndex">{{Index:{_index}}}</DisplayString> <DisplayString Condition="_meta==ColorType::IsIndex256">{{Index256:{_index}}}</DisplayString>
<DisplayString Condition="_meta==ColorType::IsIndex16">{{Index16:{_index}}}</DisplayString>
<DisplayString Condition="_meta==ColorType::IsDefault">{{Default}}</DisplayString> <DisplayString Condition="_meta==ColorType::IsDefault">{{Default}}</DisplayString>
<DisplayString Condition="_meta==ColorType::IsRgb">{{RGB:{_red},{_green},{_blue}}}</DisplayString> <DisplayString Condition="_meta==ColorType::IsRgb">{{RGB:{_red},{_green},{_blue}}}</DisplayString>
<Expand></Expand> <Expand></Expand>