From fa7c1abdf8f857be12af51cea7ac16ac10e95df1 Mon Sep 17 00:00:00 2001 From: James Holderness Date: Wed, 27 May 2020 23:34:45 +0100 Subject: [PATCH] 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. --- src/buffer/out/TextAttribute.cpp | 19 ++- src/buffer/out/TextAttribute.hpp | 44 ++----- src/buffer/out/TextColor.cpp | 67 +++++++---- src/buffer/out/TextColor.h | 35 +++--- .../out/ut_textbuffer/TextColorTests.cpp | 8 +- src/cascadia/TerminalCore/ITerminalApi.hpp | 2 + src/cascadia/TerminalCore/Terminal.hpp | 2 + src/cascadia/TerminalCore/TerminalApi.cpp | 16 +++ .../TerminalCore/TerminalDispatchGraphics.cpp | 4 +- .../ConptyRoundtripTests.cpp | 3 +- src/host/VtIo.cpp | 12 +- src/host/conattrs.cpp | 66 +---------- src/host/getset.cpp | 5 +- src/host/screenInfo.cpp | 5 +- src/host/settings.cpp | 93 ++++++--------- src/host/settings.hpp | 9 +- src/host/telemetry.cpp | 4 +- src/host/ut_host/ConptyOutputTests.cpp | 3 +- src/host/ut_host/ScreenBufferTests.cpp | 24 ++-- src/host/ut_host/TextBufferIteratorTests.cpp | 2 +- src/host/ut_host/VtIoTests.cpp | 32 ++--- src/host/ut_host/VtRendererTests.cpp | 30 ++--- src/inc/conattrs.hpp | 14 +-- src/interactivity/win32/menu.cpp | 10 +- src/renderer/vt/WinTelnetEngine.cpp | 9 +- src/renderer/vt/WinTelnetEngine.hpp | 6 +- src/renderer/vt/Xterm256Engine.cpp | 8 +- src/renderer/vt/Xterm256Engine.hpp | 3 +- src/renderer/vt/XtermEngine.cpp | 9 +- src/renderer/vt/XtermEngine.hpp | 6 +- src/renderer/vt/paint.cpp | 14 +-- src/renderer/vt/vtrenderer.hpp | 6 +- src/terminal/adapter/adaptDispatch.hpp | 2 +- .../adapter/adaptDispatchGraphics.cpp | 16 ++- .../adapter/ut_adapter/adapterTest.cpp | 111 +++++++++++------- tools/ConsoleTypes.natvis | 3 +- 36 files changed, 327 insertions(+), 375 deletions(-) diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp index aa66a3ed4..ee7794022 100644 --- a/src/buffer/out/TextAttribute.cpp +++ b/src/buffer/out/TextAttribute.cpp @@ -10,6 +10,11 @@ bool TextAttribute::IsLegacy() const noexcept return _foreground.IsLegacy() && _background.IsLegacy(); } +bool TextAttribute::IsHighColor() const noexcept +{ + return _foreground.IsHighColor() || _background.IsHighColor(); +} + // Arguments: // - None // Return Value: @@ -72,12 +77,22 @@ void TextAttribute::SetBackground(const COLORREF rgbBackground) noexcept void TextAttribute::SetIndexedForeground(const BYTE fgIndex) noexcept { - _foreground = TextColor(fgIndex); + _foreground = TextColor(fgIndex, false); } 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 diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index edabdc456..df6278e3f 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -42,8 +42,8 @@ public: constexpr TextAttribute(const WORD wLegacyAttr) noexcept : _wAttrLegacy{ gsl::narrow_cast(wLegacyAttr & META_ATTRS) }, - _foreground{ gsl::narrow_cast(wLegacyAttr & FG_ATTRS) }, - _background{ gsl::narrow_cast((wLegacyAttr & BG_ATTRS) >> 4) }, + _foreground{ gsl::narrow_cast(wLegacyAttr & FG_ATTRS), true }, + _background{ gsl::narrow_cast((wLegacyAttr & BG_ATTRS) >> 4), true }, _extendedAttrs{ ExtendedAttributes::Normal } { // 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 bg = (_background.GetIndex() << 4) & BG_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: @@ -79,15 +80,16 @@ public: // the background not be a legacy style attribute. // Return Value: // - a WORD with legacy-style attributes for this textattribute. - constexpr WORD GetLegacyAttributes(const BYTE defaultFgIndex, - const BYTE defaultBgIndex) const noexcept + WORD GetLegacyAttributes(const BYTE defaultFgIndex, + const BYTE defaultBgIndex) const noexcept { const BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex; const BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex; const BYTE fg = (fgIndex & FG_ATTRS); const BYTE bg = (bgIndex << 4) & BG_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 colorTable, @@ -117,6 +119,7 @@ public: friend constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept; bool IsLegacy() const noexcept; + bool IsHighColor() const noexcept; bool IsBold() const noexcept; bool IsItalic() const noexcept; bool IsBlinking() const noexcept; @@ -139,6 +142,8 @@ public: void SetBackground(const COLORREF rgbBackground) noexcept; void SetIndexedForeground(const BYTE fgIndex) 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 SetDefaultForeground() noexcept; @@ -149,11 +154,6 @@ public: 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 // character, would look identical to the other one. 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); } -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 #define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \ diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index 05fcded14..11c054fe8 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -4,6 +4,36 @@ #include "precomp.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: // - Sets the color value of this attribute, and sets this color to be an RGB // 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. // Arguments: // - 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: // - -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; } @@ -48,15 +79,15 @@ void TextColor::SetDefault() noexcept // * 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 // our value in the provided color table. -// - If brighten is true, and the index is in the "dark" portion of the -// color table (indices [0,7]), then we'll look up the bright version of -// this color (from indices [8,15]). This should be true for -// TextAttributes that are "Bold" and we're treating bold as bright -// (which is the default behavior of most terminals.) +// - If brighten is true, and we've got a 16 color index in the "dark" +// portion of the color table (indices [0,7]), then we'll look up the +// bright version of this color (from indices [8,15]). This should be +// true for TextAttributes that are "Bold" and we're treating bold as +// bright (which is the default behavior of most terminals.) // * If we're a default color, we'll return the default color provided. // Arguments: -// - colorTable: The table of colors we should use to look up the value of a -// legacy attribute from +// - colorTable: The table of colors we should use to look up the value of +// an indexed attribute from. // - defaultColor: The color value to use if we're a default attribute. // - brighten: if true, we'll brighten a dark color table index. // Return Value: @@ -94,21 +125,13 @@ COLORREF TextColor::GetColor(std::basic_string_view colorTable, { return _GetRGB(); } + else if (IsIndex16() && brighten) + { + return colorTable.at(_index | 8); + } else { - FAIL_FAST_IF(colorTable.size() < _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(_index) + 8 > colorTable.size()); - return colorTable.at(gsl::narrow_cast(_index) + 8); - } - else - { - return colorTable.at(_index); - } + return colorTable.at(_index); } } diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h index 21896ca04..08db63b83 100644 --- a/src/buffer/out/TextColor.h +++ b/src/buffer/out/TextColor.h @@ -41,9 +41,10 @@ Revision History: enum class ColorType : BYTE { - IsIndex = 0x0, - IsDefault = 0x1, - IsRgb = 0x2 + IsIndex256 = 0x0, + IsIndex16 = 0x1, + IsDefault = 0x2, + IsRgb = 0x3 }; struct TextColor @@ -57,9 +58,9 @@ public: { } - constexpr TextColor(const BYTE wLegacyAttr) noexcept : - _meta{ ColorType::IsIndex }, - _index{ wLegacyAttr }, + constexpr TextColor(const BYTE index, const bool isIndex256) noexcept : + _meta{ isIndex256 ? ColorType::IsIndex256 : ColorType::IsIndex16 }, + _index{ index }, _green{ 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; - constexpr bool IsLegacy() const noexcept - { - return !(IsDefault() || IsRgb()); - } - - constexpr bool IsDefault() const noexcept - { - return _meta == ColorType::IsDefault; - } - - constexpr bool IsRgb() const noexcept - { - return _meta == ColorType::IsRgb; - } + bool IsLegacy() const noexcept; + bool IsHighColor() const noexcept; + bool IsIndex16() const noexcept; + bool IsIndex256() const noexcept; + bool IsDefault() const noexcept; + bool IsRgb() const 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; COLORREF GetColor(std::basic_string_view colorTable, diff --git a/src/buffer/out/ut_textbuffer/TextColorTests.cpp b/src/buffer/out/ut_textbuffer/TextColorTests.cpp index 3497bdcae..794331fee 100644 --- a/src/buffer/out/ut_textbuffer/TextColorTests.cpp +++ b/src/buffer/out/ut_textbuffer/TextColorTests.cpp @@ -81,7 +81,7 @@ void TextColorTests::TestDefaultColor() void TextColorTests::TestDarkIndexColor() { - TextColor indexColor((BYTE)(7)); + TextColor indexColor((BYTE)(7), false); VERIFY_IS_FALSE(indexColor.IsDefault()); VERIFY_IS_TRUE(indexColor.IsLegacy()); @@ -104,7 +104,7 @@ void TextColorTests::TestDarkIndexColor() void TextColorTests::TestBrightIndexColor() { - TextColor indexColor((BYTE)(15)); + TextColor indexColor((BYTE)(15), false); VERIFY_IS_FALSE(indexColor.IsDefault()); VERIFY_IS_TRUE(indexColor.IsLegacy()); @@ -186,7 +186,7 @@ void TextColorTests::TestChangeColor() color = rgbColor.GetColor(view, _defaultBg, true); VERIFY_ARE_EQUAL(_defaultBg, color); - rgbColor.SetIndex(7); + rgbColor.SetIndex(7, false); color = rgbColor.GetColor(view, _defaultFg, false); VERIFY_ARE_EQUAL(_colorTable[7], color); @@ -199,7 +199,7 @@ void TextColorTests::TestChangeColor() color = rgbColor.GetColor(view, _defaultBg, true); VERIFY_ARE_EQUAL(_colorTable[15], color); - rgbColor.SetIndex(15); + rgbColor.SetIndex(15, false); color = rgbColor.GetColor(view, _defaultFg, false); VERIFY_ARE_EQUAL(_colorTable[15], color); diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp index b521f4ece..5b1f3d0ec 100644 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ b/src/cascadia/TerminalCore/ITerminalApi.hpp @@ -21,6 +21,8 @@ namespace Microsoft::Terminal::Core virtual bool SetTextToDefaults(bool foreground, bool background) noexcept = 0; virtual bool SetTextForegroundIndex(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 BoldText(bool boldOn) noexcept = 0; virtual bool UnderlineText(bool underlineOn) noexcept = 0; diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index fd0e70e4d..55b1ef2dc 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -81,6 +81,8 @@ public: bool SetTextToDefaults(bool foreground, bool background) noexcept override; bool SetTextForegroundIndex(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 BoldText(bool boldOn) noexcept override; bool UnderlineText(bool underlineOn) noexcept override; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index 4189e07b1..72abe4e61 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -57,6 +57,22 @@ bool Terminal::SetTextBackgroundIndex(BYTE colorIndex) noexcept 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 { TextAttribute attrs = _buffer->GetCurrentAttributes(); diff --git a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp index 0a37cebed..4403de582 100644 --- a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp @@ -121,8 +121,8 @@ bool TerminalDispatch::_SetRgbColorsHelper(const std::basic_string_view(tableIndex)) : - _terminalApi.SetTextBackgroundIndex(gsl::narrow_cast(tableIndex)); + _terminalApi.SetTextForegroundIndex256(gsl::narrow_cast(tableIndex)) : + _terminalApi.SetTextBackgroundIndex256(gsl::narrow_cast(tableIndex)); } } } diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index 062969f93..541989d42 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -119,8 +119,7 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final auto vtRenderEngine = std::make_unique(std::move(hFile), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize())); + gci.Get16ColorTable()); auto pfn = std::bind(&ConptyRoundtripTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2); vtRenderEngine->SetTestCallback(pfn); diff --git a/src/host/VtIo.cpp b/src/host/VtIo.cpp index 09b3af630..3fea6aa60 100644 --- a/src/host/VtIo.cpp +++ b/src/host/VtIo.cpp @@ -161,31 +161,27 @@ VtIo::VtIo() : _pVtRenderEngine = std::make_unique(std::move(_hOutput), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize())); + gci.Get16ColorTable()); break; case VtIoMode::XTERM: _pVtRenderEngine = std::make_unique(std::move(_hOutput), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize()), + gci.Get16ColorTable(), false); break; case VtIoMode::XTERM_ASCII: _pVtRenderEngine = std::make_unique(std::move(_hOutput), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize()), + gci.Get16ColorTable(), true); break; case VtIoMode::WIN_TELNET: _pVtRenderEngine = std::make_unique(std::move(_hOutput), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize())); + gci.Get16ColorTable()); break; default: return E_FAIL; diff --git a/src/host/conattrs.cpp b/src/host/conattrs.cpp index c33864d8a..b64ff757f 100644 --- a/src/host/conattrs.cpp +++ b/src/host/conattrs.cpp @@ -81,13 +81,12 @@ static double _FindDifference(const _HSL* const phslColorA, const COLORREF rgbCo //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 FindNearestTableIndex(const COLORREF Color, _In_reads_(cColorTable) const COLORREF* const ColorTable, const WORD cColorTable) +WORD FindNearestTableIndex(const COLORREF Color, const std::basic_string_view ColorTable) { // 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]) { @@ -100,7 +99,7 @@ WORD FindNearestTableIndex(const COLORREF Color, _In_reads_(cColorTable) const C const _HSL hslColor = _HSL(Color); WORD closest = 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]); if (diff < minDiff) @@ -146,36 +145,19 @@ WORD Xterm256ToWindowsIndex(const size_t xtermTableEntry) noexcept static_cast(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: // Returns the exact entry from the color table, if it's in there. //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. bool FindTableIndex(const COLORREF Color, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable, + const std::basic_string_view ColorTable, _Out_ WORD* const pFoundIndex) { *pFoundIndex = 0; - for (WORD i = 0; i < cColorTable; i++) + for (WORD i = 0; i < ColorTable.size(); i++) { if (ColorTable[i] == Color) { @@ -185,41 +167,3 @@ bool FindTableIndex(const COLORREF Color, } 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; -} diff --git a/src/host/getset.cpp b/src/host/getset.cpp index b7af4741e..0699e72ab 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -572,7 +572,10 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont } 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 }); diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index ecd49d0c5..2aa6a3b51 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -360,7 +360,10 @@ void SCREEN_INFORMATION::GetScreenBufferInformation(_Out_ PCOORD pcoordSize, *pwPopupAttributes = gci.GenerateLegacyAttributes(_PopupAttributes); // 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(); } diff --git a/src/host/settings.cpp b/src/host/settings.cpp index 154d3b921..58f14cc7d 100644 --- a/src/host/settings.cpp +++ b/src/host/settings.cpp @@ -81,9 +81,8 @@ Settings::Settings() : _CursorColor = Cursor::s_InvertCursorColor; _CursorType = CursorType::Legacy; - gsl::span tableView = { _ColorTable, gsl::narrow(COLOR_TABLE_SIZE) }; - gsl::span xtermTableView = { _XtermColorTable, gsl::narrow(XTERM_COLOR_TABLE_SIZE) }; - ::Microsoft::Console::Utils::Initialize256ColorTable(xtermTableView); + gsl::span tableView = { _colorTable.data(), gsl::narrow(_colorTable.size()) }; + ::Microsoft::Console::Utils::Initialize256ColorTable(tableView); ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); } @@ -123,7 +122,7 @@ void Settings::ApplyDesktopSpecificDefaults() _uNumberOfHistoryBuffers = 4; _bHistoryNoDup = FALSE; - gsl::span tableView = { _ColorTable, gsl::narrow(COLOR_TABLE_SIZE) }; + gsl::span tableView = { _colorTable.data(), gsl::narrow(_colorTable.size()) }; ::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView); _fTrimLeadingZeros = false; @@ -221,7 +220,10 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo) _bHistoryNoDup = pStateInfo->HistoryNoDup; _uHistoryBufferSize = pStateInfo->HistoryBufferSize; _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; _bWrapText = !!pStateInfo->fWrapText; _fFilterOnPaste = pStateInfo->fFilterOnPaste; @@ -263,7 +265,10 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const csi.HistoryNoDup = _bHistoryNoDup; csi.HistoryBufferSize = _uHistoryBufferSize; 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.fWrapText = !!_bWrapText; csi.fFilterOnPaste = _fFilterOnPaste; @@ -717,26 +722,19 @@ void Settings::SetHistoryNoDup(const bool bHistoryNoDup) _bHistoryNoDup = bHistoryNoDup; } -const COLORREF* const Settings::GetColorTable() const +std::basic_string_view 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(COLOR_TABLE_SIZE)); - memmove(_ColorTable, pColorTable, cSizeWritten * sizeof(COLORREF)); +std::basic_string_view Settings::Get256ColorTable() const +{ + return { _colorTable.data(), _colorTable.size() }; } + void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue) { - if (index < ARRAYSIZE(_ColorTable)) - { - _ColorTable[index] = ColorValue; - } - else - { - _XtermColorTable[index] = ColorValue; - } + _colorTable.at(index) = ColorValue; } bool Settings::IsStartupTitleIsLinkNameSet() const @@ -754,21 +752,9 @@ void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset) _dwStartupFlags &= ~dwFlagToUnset; } -const size_t Settings::GetColorTableSize() const -{ - return ARRAYSIZE(_ColorTable); -} - COLORREF Settings::GetColorTableEntry(const size_t index) const { - if (index < ARRAYSIZE(_ColorTable)) - { - return _ColorTable[index]; - } - else - { - return _XtermColorTable[index]; - } + return _colorTable.at(index); } // Routine Description: @@ -792,19 +778,21 @@ WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const BYTE bgIndex = static_cast((_wFillAttribute & BG_ATTRS) >> 4); // If the attributes have any RGB components, we need to match that RGB // color to a color table value. - if (attributes.IsRgb()) + if (attributes.IsHighColor()) { // If the attribute doesn't have a "default" colored *ground, look up // the nearest color table value for its *ground. - const COLORREF rgbForeground = LookupForegroundColor(attributes); - fgIndex = attributes.ForegroundIsDefault() ? - fgIndex : - static_cast(FindNearestTableIndex(rgbForeground)); + if (!attributes.ForegroundIsDefault()) + { + const COLORREF rgbForeground = LookupForegroundColor(attributes); + fgIndex = static_cast(::FindNearestTableIndex(rgbForeground, Get16ColorTable())); + } - const COLORREF rgbBackground = LookupBackgroundColor(attributes); - bgIndex = attributes.BackgroundIsDefault() ? - bgIndex : - static_cast(FindNearestTableIndex(rgbBackground)); + if (!attributes.BackgroundIsDefault()) + { + const COLORREF rgbBackground = LookupBackgroundColor(attributes); + bgIndex = static_cast(::FindNearestTableIndex(rgbBackground, Get16ColorTable())); + } } // TextAttribute::GetLegacyAttributes(BYTE, BYTE) will use the legacy value @@ -815,19 +803,6 @@ WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const 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 { return _CursorColor; @@ -924,7 +899,7 @@ bool Settings::GetUseDx() const noexcept COLORREF Settings::CalculateDefaultForeground() const noexcept { 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: @@ -939,7 +914,7 @@ COLORREF Settings::CalculateDefaultForeground() const noexcept COLORREF Settings::CalculateDefaultBackground() const noexcept { 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: @@ -951,7 +926,7 @@ COLORREF Settings::CalculateDefaultBackground() const noexcept // - The color value of the attribute's foreground TextColor. COLORREF Settings::LookupForegroundColor(const TextAttribute& attr) const noexcept { - const auto tableView = std::basic_string_view(&GetColorTable()[0], GetColorTableSize()); + const auto tableView = Get256ColorTable(); if (_fScreenReversed) { 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. COLORREF Settings::LookupBackgroundColor(const TextAttribute& attr) const noexcept { - const auto tableView = std::basic_string_view(&GetColorTable()[0], GetColorTableSize()); + const auto tableView = Get256ColorTable(); if (_fScreenReversed) { return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground()); diff --git a/src/host/settings.hpp b/src/host/settings.hpp index 05503cf97..2163204c9 100644 --- a/src/host/settings.hpp +++ b/src/host/settings.hpp @@ -159,9 +159,8 @@ public: bool GetHistoryNoDup() const; void SetHistoryNoDup(const bool fHistoryNoDup); - const COLORREF* const GetColorTable() const; - const size_t GetColorTableSize() const; - void SetColorTable(_In_reads_(cSize) const COLORREF* const pColorTable, const size_t cSize); + std::basic_string_view Get16ColorTable() const; + std::basic_string_view Get256ColorTable() const; void SetColorTableEntry(const size_t index, const COLORREF ColorValue); COLORREF GetColorTableEntry(const size_t index) const; @@ -217,7 +216,6 @@ private: UINT _uHistoryBufferSize; UINT _uNumberOfHistoryBuffers; BOOL _bHistoryNoDup; - COLORREF _ColorTable[COLOR_TABLE_SIZE]; // END - memcpy UINT _uCodePage; UINT _uScrollScale; @@ -238,7 +236,7 @@ private: bool _fUseDx; bool _fCopyColor; - COLORREF _XtermColorTable[XTERM_COLOR_TABLE_SIZE]; + std::array _colorTable; // this is used for the special STARTF_USESIZE mode. bool _fUseWindowSizePixels; @@ -257,5 +255,4 @@ private: public: WORD GenerateLegacyAttributes(const TextAttribute attributes) const; - WORD FindNearestTableIndex(const COLORREF Color) const; }; diff --git a/src/host/telemetry.cpp b/src/host/telemetry.cpp index 7a0d91601..4f4d1bb10 100644 --- a/src/host/telemetry.cpp +++ b/src/host/telemetry.cpp @@ -419,7 +419,7 @@ void Telemetry::WriteFinalTraceLog() TraceLoggingBool(gci.GetQuickEdit(), "QuickEdit"), TraceLoggingValue(gci.GetWindowAlpha(), "WindowAlpha"), 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.OutputCP, "CodePageOutput"), TraceLoggingValue(gci.GetFontSize().X, "FontSizeX"), @@ -453,7 +453,7 @@ void Telemetry::WriteFinalTraceLog() TraceLoggingValue(gci.GetShowWindow(), "ShowWindow"), TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), 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. // So just log each enum count separately with its string representation which makes it more human readable. diff --git a/src/host/ut_host/ConptyOutputTests.cpp b/src/host/ut_host/ConptyOutputTests.cpp index 071e7dd21..6c76aae19 100644 --- a/src/host/ut_host/ConptyOutputTests.cpp +++ b/src/host/ut_host/ConptyOutputTests.cpp @@ -88,8 +88,7 @@ class ConptyOutputTests auto vtRenderEngine = std::make_unique(std::move(hFile), gci, initialViewport, - gci.GetColorTable(), - static_cast(gci.GetColorTableSize())); + gci.Get16ColorTable()); auto pfn = std::bind(&ConptyOutputTests::_writeCallback, this, std::placeholders::_1, std::placeholders::_2); vtRenderEngine->SetTestCallback(pfn); diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 2ca2f63e0..ebda0167a 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -1844,7 +1844,9 @@ void ScreenBufferTests::VtEraseAllPersistCursorFillColor() 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")); - 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"); VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes()); @@ -2222,12 +2224,14 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault() // See the log comment above for description of these values. TextAttribute expectedDefaults{}; - TextAttribute expectedTwo{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; - TextAttribute expectedThree{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; + TextAttribute expectedTwo; + expectedTwo.SetIndexedForeground((BYTE)XtermToWindowsIndex(10)); + expectedTwo.SetIndexedBackground((BYTE)XtermToWindowsIndex(4)); + TextAttribute expectedThree = expectedTwo; expectedThree.SetDefaultForeground(); // Four is the same as Defaults // Five is the same as two - TextAttribute expectedSix{ FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE }; + TextAttribute expectedSix = expectedTwo; expectedSix.SetDefaultBackground(); COORD expectedCursor{ 6, 0 }; @@ -2324,7 +2328,7 @@ void ScreenBufferTests::SetDefaultsTogether() // See the log comment above for description of these values. TextAttribute expectedDefaults{}; TextAttribute expectedTwo{}; - expectedTwo.SetBackground(color250); + expectedTwo.SetIndexedBackground256(250); COORD expectedCursor{ 3, 0 }; VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition()); @@ -4503,14 +4507,14 @@ void ScreenBufferTests::ScrollLines256Colors() auto& cursor = si.GetTextBuffer().GetCursor(); TextAttribute expectedAttr{ si.GetAttributes() }; - std::wstring_view sgrSeq = L"\x1b[48;5;2m"; + std::wstring_view sgrSeq = L"\x1b[42m"; if (colorStyle == Use16Color) { - expectedAttr.SetBackground(gci.GetColorTableEntry(2)); + expectedAttr.SetIndexedBackground(2); } else if (colorStyle == Use256Color) { - expectedAttr.SetBackground(gci.GetColorTableEntry(20)); + expectedAttr.SetIndexedBackground256(20); sgrSeq = L"\x1b[48;5;20m"; } else if (colorStyle == UseRGBColor) @@ -5237,7 +5241,7 @@ void ScreenBufferTests::TestExtendedTextAttributesWithColors() } else if (setForegroundType == Use256Color) { - expectedAttr.SetForeground(gci.GetColorTableEntry(20)); + expectedAttr.SetIndexedForeground256(20); vtSeq += L"\x1b[38;5;20m"; } else if (setForegroundType == UseRGBColor) @@ -5259,7 +5263,7 @@ void ScreenBufferTests::TestExtendedTextAttributesWithColors() } else if (setBackgroundType == Use256Color) { - expectedAttr.SetBackground(gci.GetColorTableEntry(20)); + expectedAttr.SetIndexedBackground256(20); vtSeq += L"\x1b[48;5;20m"; } else if (setBackgroundType == UseRGBColor) diff --git a/src/host/ut_host/TextBufferIteratorTests.cpp b/src/host/ut_host/TextBufferIteratorTests.cpp index 13630a51a..55f0ae328 100644 --- a/src/host/ut_host/TextBufferIteratorTests.cpp +++ b/src/host/ut_host/TextBufferIteratorTests.cpp @@ -498,7 +498,7 @@ void TextBufferIteratorTests::DereferenceOperatorCell() const auto textExpected = (std::wstring_view)row.GetCharRow().GlyphAt(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 textActual = cellActual.Chars(); diff --git a/src/host/ut_host/VtIoTests.cpp b/src/host/ut_host/VtIoTests.cpp index f9f609464..01124b083 100644 --- a/src/host/ut_host/VtIoTests.cpp +++ b/src/host/ut_host/VtIoTests.cpp @@ -124,28 +124,28 @@ void VtIoTests::DtorTestJustEngine() wil::unique_hfile hOutputFile; 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")); delete pRenderer256; Log::Comment(NoThrowString().Format(L"Deleted.")); 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")); delete pRenderEngineXterm; Log::Comment(NoThrowString().Format(L"Deleted.")); 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")); delete pRenderEngineXtermAscii; Log::Comment(NoThrowString().Format(L"Deleted.")); 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")); delete pRenderEngineWinTelnet; Log::Comment(NoThrowString().Format(L"Deleted.")); @@ -180,8 +180,7 @@ void VtIoTests::DtorTestDeleteVtio() vtio->_pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); Log::Comment(NoThrowString().Format(L"Made Xterm256Engine")); delete vtio; Log::Comment(NoThrowString().Format(L"Deleted.")); @@ -193,7 +192,6 @@ void VtIoTests::DtorTestDeleteVtio() p, SetUpViewport(), colorTable, - colorTableSize, false); Log::Comment(NoThrowString().Format(L"Made XtermEngine")); delete vtio; @@ -206,7 +204,6 @@ void VtIoTests::DtorTestDeleteVtio() p, SetUpViewport(), colorTable, - colorTableSize, true); Log::Comment(NoThrowString().Format(L"Made XtermEngine")); delete vtio; @@ -218,8 +215,7 @@ void VtIoTests::DtorTestDeleteVtio() vtio->_pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); Log::Comment(NoThrowString().Format(L"Made WinTelnetEngine")); delete vtio; Log::Comment(NoThrowString().Format(L"Deleted.")); @@ -253,8 +249,7 @@ void VtIoTests::DtorTestStackAlloc() vtio._pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); } hOutputFile.reset(INVALID_HANDLE_VALUE); @@ -264,7 +259,6 @@ void VtIoTests::DtorTestStackAlloc() p, SetUpViewport(), colorTable, - colorTableSize, false); } @@ -275,7 +269,6 @@ void VtIoTests::DtorTestStackAlloc() p, SetUpViewport(), colorTable, - colorTableSize, true); } @@ -285,8 +278,7 @@ void VtIoTests::DtorTestStackAlloc() vtio._pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); } } } @@ -317,8 +309,7 @@ void VtIoTests::DtorTestStackAllocMany() vtio1._pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); hOutputFile.reset(INVALID_HANDLE_VALUE); VtIo vtio2; @@ -326,7 +317,6 @@ void VtIoTests::DtorTestStackAllocMany() p, SetUpViewport(), colorTable, - colorTableSize, false); hOutputFile.reset(INVALID_HANDLE_VALUE); @@ -335,7 +325,6 @@ void VtIoTests::DtorTestStackAllocMany() p, SetUpViewport(), colorTable, - colorTableSize, true); hOutputFile.reset(INVALID_HANDLE_VALUE); @@ -343,8 +332,7 @@ void VtIoTests::DtorTestStackAllocMany() vtio4._pVtRenderEngine = std::make_unique(std::move(hOutputFile), p, SetUpViewport(), - colorTable, - colorTableSize); + colorTable); } } } diff --git a/src/host/ut_host/VtRendererTests.cpp b/src/host/ut_host/VtRendererTests.cpp index 4be9db4b8..7e5bfdd21 100644 --- a/src/host/ut_host/VtRendererTests.cpp +++ b/src/host/ut_host/VtRendererTests.cpp @@ -189,7 +189,7 @@ void VtRendererTest::TestPaint(VtEngine& engine, std::function pfn) void VtRendererTest::VtSequenceHelperTests() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -246,7 +246,7 @@ void VtRendererTest::VtSequenceHelperTests() void VtRendererTest::Xterm256TestInvalidate() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -434,7 +434,7 @@ void VtRendererTest::Xterm256TestInvalidate() void VtRendererTest::Xterm256TestColors() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -571,7 +571,7 @@ void VtRendererTest::Xterm256TestColors() void VtRendererTest::Xterm256TestCursor() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -723,7 +723,7 @@ void VtRendererTest::Xterm256TestExtendedAttributes() } wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -767,7 +767,7 @@ void VtRendererTest::Xterm256TestExtendedAttributes() void VtRendererTest::XtermTestInvalidate() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE), false); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, false); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -954,7 +954,7 @@ void VtRendererTest::XtermTestInvalidate() void VtRendererTest::XtermTestColors() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE), false); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, false); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1040,7 +1040,7 @@ void VtRendererTest::XtermTestColors() void VtRendererTest::XtermTestCursor() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE), false); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, false); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1149,7 +1149,7 @@ void VtRendererTest::XtermTestCursor() void VtRendererTest::WinTelnetTestInvalidate() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1221,7 +1221,7 @@ void VtRendererTest::WinTelnetTestInvalidate() void VtRendererTest::WinTelnetTestColors() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1299,7 +1299,7 @@ void VtRendererTest::WinTelnetTestColors() void VtRendererTest::WinTelnetTestCursor() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1379,7 +1379,7 @@ void VtRendererTest::WinTelnetTestCursor() void VtRendererTest::TestWrapping() { wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + std::unique_ptr engine = std::make_unique(std::move(hFile), p, SetUpViewport(), g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1432,7 +1432,7 @@ void VtRendererTest::TestResize() { Viewport view = SetUpViewport(); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1469,7 +1469,7 @@ void VtRendererTest::TestCursorVisibility() { Viewport view = SetUpViewport(); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); @@ -1594,7 +1594,7 @@ void VtRendererTest::FormattedString() Viewport view = SetUpViewport(); wil::unique_hfile hFile = wil::unique_hfile(INVALID_HANDLE_VALUE); - auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable, static_cast(COLOR_TABLE_SIZE)); + auto engine = std::make_unique(std::move(hFile), p, view, g_ColorTable); auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2); engine->SetTestCallback(pfn); diff --git a/src/inc/conattrs.hpp b/src/inc/conattrs.hpp index a168b173c..a33deaf49 100644 --- a/src/inc/conattrs.hpp +++ b/src/inc/conattrs.hpp @@ -24,26 +24,16 @@ enum class ExtendedAttributes : BYTE DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes); WORD FindNearestTableIndex(const COLORREF Color, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable); + const std::basic_string_view ColorTable); bool FindTableIndex(const COLORREF Color, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable, + const std::basic_string_view ColorTable, _Out_ WORD* const pFoundIndex); WORD XtermToWindowsIndex(const size_t index) noexcept; WORD Xterm256ToWindowsIndex(const size_t index) noexcept; 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_GREEN_ATTR = FOREGROUND_GREEN; const WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE; diff --git a/src/interactivity/win32/menu.cpp b/src/interactivity/win32/menu.cpp index b9e09b32f..0555a315d 100644 --- a/src/interactivity/win32/menu.cpp +++ b/src/interactivity/win32/menu.cpp @@ -335,7 +335,10 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults) pStateInfo->NumberOfHistoryBuffers = gci.GetNumberOfHistoryBuffers(); 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. 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. WI_ClearAllFlags(pStateInfo->ScreenAttributes, ~(FG_ATTRS | BG_ATTRS)); diff --git a/src/renderer/vt/WinTelnetEngine.cpp b/src/renderer/vt/WinTelnetEngine.cpp index f08a186c3..c8081cf61 100644 --- a/src/renderer/vt/WinTelnetEngine.cpp +++ b/src/renderer/vt/WinTelnetEngine.cpp @@ -12,11 +12,9 @@ using namespace Microsoft::Console::Types; WinTelnetEngine::WinTelnetEngine(_In_ wil::unique_hfile hPipe, const IDefaultColorProvider& colorProvider, const Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) : + const std::basic_string_view colorTable) : VtEngine(std::move(hPipe), colorProvider, initialViewport), - _ColorTable(ColorTable), - _cColorTable(cColorTable) + _colorTable(colorTable) { } @@ -42,8 +40,7 @@ WinTelnetEngine::WinTelnetEngine(_In_ wil::unique_hfile hPipe, return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground, colorBackground, WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), - _ColorTable, - _cColorTable); + _colorTable); } // Routine Description: diff --git a/src/renderer/vt/WinTelnetEngine.hpp b/src/renderer/vt/WinTelnetEngine.hpp index 179697a5a..4d40c232d 100644 --- a/src/renderer/vt/WinTelnetEngine.hpp +++ b/src/renderer/vt/WinTelnetEngine.hpp @@ -26,8 +26,7 @@ namespace Microsoft::Console::Render WinTelnetEngine(_In_ wil::unique_hfile hPipe, const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::Types::Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable); + const std::basic_string_view colorTable); virtual ~WinTelnetEngine() override = default; [[nodiscard]] HRESULT UpdateDrawingBrushes(const COLORREF colorForeground, @@ -45,8 +44,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept; private: - const COLORREF* const _ColorTable; - const WORD _cColorTable; + const std::basic_string_view _colorTable; #ifdef UNIT_TESTING friend class VtRendererTest; diff --git a/src/renderer/vt/Xterm256Engine.cpp b/src/renderer/vt/Xterm256Engine.cpp index ba440db03..2fed81c2a 100644 --- a/src/renderer/vt/Xterm256Engine.cpp +++ b/src/renderer/vt/Xterm256Engine.cpp @@ -11,9 +11,8 @@ using namespace Microsoft::Console::Types; Xterm256Engine::Xterm256Engine(_In_ wil::unique_hfile hPipe, const IDefaultColorProvider& colorProvider, const Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) : - XtermEngine(std::move(hPipe), colorProvider, initialViewport, ColorTable, cColorTable, false), + const std::basic_string_view colorTable) : + XtermEngine(std::move(hPipe), colorProvider, initialViewport, colorTable, false), _lastExtendedAttrsState{ ExtendedAttributes::Normal } { } @@ -52,8 +51,7 @@ Xterm256Engine::Xterm256Engine(_In_ wil::unique_hfile hPipe, return VtEngine::_RgbUpdateDrawingBrushes(colorForeground, colorBackground, WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), - _ColorTable, - _cColorTable); + _colorTable); } // Routine Description: diff --git a/src/renderer/vt/Xterm256Engine.hpp b/src/renderer/vt/Xterm256Engine.hpp index 3addb195e..e4e5562f6 100644 --- a/src/renderer/vt/Xterm256Engine.hpp +++ b/src/renderer/vt/Xterm256Engine.hpp @@ -26,8 +26,7 @@ namespace Microsoft::Console::Render Xterm256Engine(_In_ wil::unique_hfile hPipe, const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::Types::Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable); + const std::basic_string_view colorTable); virtual ~Xterm256Engine() override = default; diff --git a/src/renderer/vt/XtermEngine.cpp b/src/renderer/vt/XtermEngine.cpp index f212c1eeb..6073b0358 100644 --- a/src/renderer/vt/XtermEngine.cpp +++ b/src/renderer/vt/XtermEngine.cpp @@ -12,12 +12,10 @@ using namespace Microsoft::Console::Types; XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, const IDefaultColorProvider& colorProvider, const Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable, + const std::basic_string_view colorTable, const bool fUseAsciiOnly) : VtEngine(std::move(hPipe), colorProvider, initialViewport), - _ColorTable(ColorTable), - _cColorTable(cColorTable), + _colorTable(colorTable), _fUseAsciiOnly(fUseAsciiOnly), _usingUnderLine(false), _needToDisableCursor(false), @@ -192,8 +190,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, return VtEngine::_16ColorUpdateDrawingBrushes(colorForeground, colorBackground, WI_IsFlagSet(extendedAttrs, ExtendedAttributes::Bold), - _ColorTable, - _cColorTable); + _colorTable); } // Routine Description: diff --git a/src/renderer/vt/XtermEngine.hpp b/src/renderer/vt/XtermEngine.hpp index e6a0a868c..cf5249ab6 100644 --- a/src/renderer/vt/XtermEngine.hpp +++ b/src/renderer/vt/XtermEngine.hpp @@ -30,8 +30,7 @@ namespace Microsoft::Console::Render XtermEngine(_In_ wil::unique_hfile hPipe, const Microsoft::Console::IDefaultColorProvider& colorProvider, const Microsoft::Console::Types::Viewport initialViewport, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable, + const std::basic_string_view colorTable, const bool fUseAsciiOnly); virtual ~XtermEngine() override = default; @@ -57,8 +56,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override; protected: - const COLORREF* const _ColorTable; - const WORD _cColorTable; + const std::basic_string_view _colorTable; const bool _fUseAsciiOnly; bool _usingUnderLine; bool _needToDisableCursor; diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index 0294fe20b..d9604f685 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -192,8 +192,7 @@ using namespace Microsoft::Console::Types; [[nodiscard]] HRESULT VtEngine::_RgbUpdateDrawingBrushes(const COLORREF colorForeground, const COLORREF colorBackground, const bool isBold, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) noexcept + const std::basic_string_view colorTable) noexcept { const bool fgChanged = colorForeground != _LastFG; const bool bgChanged = colorBackground != _LastBG; @@ -232,7 +231,7 @@ using namespace Microsoft::Console::Types; { RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(true)); } - else if (::FindTableIndex(colorForeground, ColorTable, cColorTable, &wFoundColor)) + else if (::FindTableIndex(colorForeground, colorTable, &wFoundColor)) { RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, true)); } @@ -249,7 +248,7 @@ using namespace Microsoft::Console::Types; { RETURN_IF_FAILED(_SetGraphicsRenditionDefaultColor(false)); } - else if (::FindTableIndex(colorBackground, ColorTable, cColorTable, &wFoundColor)) + else if (::FindTableIndex(colorBackground, colorTable, &wFoundColor)) { RETURN_IF_FAILED(_SetGraphicsRendition16Color(wFoundColor, false)); } @@ -278,8 +277,7 @@ using namespace Microsoft::Console::Types; [[nodiscard]] HRESULT VtEngine::_16ColorUpdateDrawingBrushes(const COLORREF colorForeground, const COLORREF colorBackground, const bool isBold, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) noexcept + const std::basic_string_view colorTable) noexcept { const bool fgChanged = colorForeground != _LastFG; const bool bgChanged = colorBackground != _LastBG; @@ -312,7 +310,7 @@ using namespace Microsoft::Console::Types; if (fgChanged) { - const WORD wNearestFg = ::FindNearestTableIndex(colorForeground, ColorTable, cColorTable); + const WORD wNearestFg = ::FindNearestTableIndex(colorForeground, colorTable); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestFg, true)); _LastFG = colorForeground; @@ -320,7 +318,7 @@ using namespace Microsoft::Console::Types; if (bgChanged) { - const WORD wNearestBg = ::FindNearestTableIndex(colorBackground, ColorTable, cColorTable); + const WORD wNearestBg = ::FindNearestTableIndex(colorBackground, colorTable); RETURN_IF_FAILED(_SetGraphicsRendition16Color(wNearestBg, false)); _LastBG = colorBackground; diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 5f683bc9b..715cd9ce7 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -212,13 +212,11 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const COLORREF colorForeground, const COLORREF colorBackground, const bool isBold, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) noexcept; + const std::basic_string_view colorTable) noexcept; [[nodiscard]] HRESULT _16ColorUpdateDrawingBrushes(const COLORREF colorForeground, const COLORREF colorBackground, const bool isBold, - _In_reads_(cColorTable) const COLORREF* const ColorTable, - const WORD cColorTable) noexcept; + const std::basic_string_view colorTable) noexcept; bool _WillWriteSingleChar() const; diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index 8bdd40b72..a5319d912 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -178,6 +178,6 @@ namespace Microsoft::Console::VirtualTerminal size_t _SetRgbColorsHelper(const std::basic_string_view options, TextAttribute& attr, - const bool isForeground); + const bool isForeground) noexcept; }; } diff --git a/src/terminal/adapter/adaptDispatchGraphics.cpp b/src/terminal/adapter/adaptDispatchGraphics.cpp index 9e565ecf3..7cb0d161f 100644 --- a/src/terminal/adapter/adaptDispatchGraphics.cpp +++ b/src/terminal/adapter/adaptDispatchGraphics.cpp @@ -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. size_t AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view options, TextAttribute& attr, - const bool isForeground) + const bool isForeground) noexcept { size_t optionsConsumed = 0; if (options.size() >= 1) @@ -73,11 +73,17 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_viewPrivateGetColorTableEntry(tableIndex, rgbColor)) + if (tableIndex <= 255) { - // TODO GH#1223: Decouple xterm-256color indexed storage from RGB storage - attr.SetColor(rgbColor, isForeground); + const auto adjustedIndex = gsl::narrow_cast(::Xterm256ToWindowsIndex(tableIndex)); + if (isForeground) + { + attr.SetIndexedForeground256(adjustedIndex); + } + else + { + attr.SetIndexedBackground256(adjustedIndex); + } } } } diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index fbcbe3e6e..7b16c3d69 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -1286,42 +1286,50 @@ public: case DispatchTypes::GraphicsOptions::ForegroundBlack: Log::Comment(L"Testing graphics 'Foreground Color Black'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = 0; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(0); break; case DispatchTypes::GraphicsOptions::ForegroundBlue: Log::Comment(L"Testing graphics 'Foreground Color Blue'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_BLUE; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE); break; case DispatchTypes::GraphicsOptions::ForegroundGreen: Log::Comment(L"Testing graphics 'Foreground Color Green'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_GREEN; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN); break; case DispatchTypes::GraphicsOptions::ForegroundCyan: Log::Comment(L"Testing graphics 'Foreground Color Cyan'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN); break; case DispatchTypes::GraphicsOptions::ForegroundRed: Log::Comment(L"Testing graphics 'Foreground Color Red'"); _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_RED; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED); break; case DispatchTypes::GraphicsOptions::ForegroundMagenta: Log::Comment(L"Testing graphics 'Foreground Color Magenta'"); _testGetSet->_attribute = FOREGROUND_GREEN | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_BLUE | FOREGROUND_RED; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_RED); break; case DispatchTypes::GraphicsOptions::ForegroundYellow: Log::Comment(L"Testing graphics 'Foreground Color Yellow'"); _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_INTENSITY; - _testGetSet->_expectedAttribute = FOREGROUND_GREEN | FOREGROUND_RED; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN | FOREGROUND_RED); break; case DispatchTypes::GraphicsOptions::ForegroundWhite: Log::Comment(L"Testing graphics 'Foreground Color White'"); _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; case DispatchTypes::GraphicsOptions::ForegroundDefault: Log::Comment(L"Testing graphics 'Foreground Color Default'"); @@ -1333,42 +1341,50 @@ public: case DispatchTypes::GraphicsOptions::BackgroundBlack: Log::Comment(L"Testing graphics 'Background Color Black'"); _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY; - _testGetSet->_expectedAttribute = 0; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedBackground(0); break; case DispatchTypes::GraphicsOptions::BackgroundBlue: Log::Comment(L"Testing graphics 'Background Color Blue'"); _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY; - _testGetSet->_expectedAttribute = BACKGROUND_BLUE; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4); break; case DispatchTypes::GraphicsOptions::BackgroundGreen: Log::Comment(L"Testing graphics 'Background Color Green'"); _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY; - _testGetSet->_expectedAttribute = BACKGROUND_GREEN; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4); break; case DispatchTypes::GraphicsOptions::BackgroundCyan: Log::Comment(L"Testing graphics 'Background Color Cyan'"); _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; case DispatchTypes::GraphicsOptions::BackgroundRed: Log::Comment(L"Testing graphics 'Background Color Red'"); _testGetSet->_attribute = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; - _testGetSet->_expectedAttribute = BACKGROUND_RED; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_RED >> 4); break; case DispatchTypes::GraphicsOptions::BackgroundMagenta: Log::Comment(L"Testing graphics 'Background Color Magenta'"); _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; case DispatchTypes::GraphicsOptions::BackgroundYellow: Log::Comment(L"Testing graphics 'Background Color Yellow'"); _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; case DispatchTypes::GraphicsOptions::BackgroundWhite: Log::Comment(L"Testing graphics 'Background Color White'"); _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; case DispatchTypes::GraphicsOptions::BackgroundDefault: Log::Comment(L"Testing graphics 'Background Color Default'"); @@ -1380,82 +1396,98 @@ public: case DispatchTypes::GraphicsOptions::BrightForegroundBlack: Log::Comment(L"Testing graphics 'Bright Foreground Color Black'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - _testGetSet->_expectedAttribute = FOREGROUND_INTENSITY; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY); break; case DispatchTypes::GraphicsOptions::BrightForegroundBlue: Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_GREEN; - _testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_BLUE; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE); break; case DispatchTypes::GraphicsOptions::BrightForegroundGreen: Log::Comment(L"Testing graphics 'Bright Foreground Color Green'"); _testGetSet->_attribute = FOREGROUND_RED | FOREGROUND_BLUE; - _testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_GREEN; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; case DispatchTypes::GraphicsOptions::BrightForegroundCyan: Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'"); _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; case DispatchTypes::GraphicsOptions::BrightForegroundRed: Log::Comment(L"Testing graphics 'Bright Foreground Color Red'"); _testGetSet->_attribute = FOREGROUND_BLUE | FOREGROUND_GREEN; - _testGetSet->_expectedAttribute = FOREGROUND_INTENSITY | FOREGROUND_RED; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_RED); break; case DispatchTypes::GraphicsOptions::BrightForegroundMagenta: Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'"); _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; case DispatchTypes::GraphicsOptions::BrightForegroundYellow: Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'"); _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; case DispatchTypes::GraphicsOptions::BrightForegroundWhite: Log::Comment(L"Testing graphics 'Bright Foreground Color White'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundBlack: Log::Comment(L"Testing graphics 'Bright Background Color Black'"); _testGetSet->_attribute = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; - _testGetSet->_expectedAttribute = BACKGROUND_INTENSITY; + _testGetSet->_expectedAttribute = _testGetSet->_attribute; + _testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_INTENSITY >> 4); break; case DispatchTypes::GraphicsOptions::BrightBackgroundBlue: Log::Comment(L"Testing graphics 'Bright Background Color Blue'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundGreen: Log::Comment(L"Testing graphics 'Bright Background Color Green'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundCyan: Log::Comment(L"Testing graphics 'Bright Background Color Cyan'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundRed: Log::Comment(L"Testing graphics 'Bright Background Color Red'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta: Log::Comment(L"Testing graphics 'Bright Background Color Magenta'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundYellow: Log::Comment(L"Testing graphics 'Bright Background Color Yellow'"); _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; case DispatchTypes::GraphicsOptions::BrightBackgroundWhite: Log::Comment(L"Testing graphics 'Bright Background Color White'"); _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; default: VERIFY_FAIL(L"Test not implemented yet!"); @@ -1880,32 +1912,28 @@ public: rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green - _testGetSet->_expectedAttribute.SetForeground(2); - _testGetSet->_expectedColorTableIndex = 2; + _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(2)); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Test 2: Change Background"); rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red - _testGetSet->_expectedAttribute.SetBackground(9); - _testGetSet->_expectedColorTableIndex = 9; + _testGetSet->_expectedAttribute.SetIndexedBackground256((BYTE)::XtermToWindowsIndex(9)); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Test 3: Change Foreground to RGB color"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)42; // Arbitrary Color - _testGetSet->_expectedColorTableIndex = 42; - _testGetSet->_expectedAttribute.SetForeground(42); + _testGetSet->_expectedAttribute.SetIndexedForeground256(42); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); Log::Comment(L"Test 4: Change Background to RGB color"); rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)142; // Arbitrary Color - _testGetSet->_expectedColorTableIndex = 142; - _testGetSet->_expectedAttribute.SetBackground(142); + _testGetSet->_expectedAttribute.SetIndexedBackground256(142); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); 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[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red - _testGetSet->_expectedAttribute.SetForeground(9); - _testGetSet->_expectedColorTableIndex = 9; + _testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(9)); VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions })); } diff --git a/tools/ConsoleTypes.natvis b/tools/ConsoleTypes.natvis index 27b29d154..224afd9bd 100644 --- a/tools/ConsoleTypes.natvis +++ b/tools/ConsoleTypes.natvis @@ -2,7 +2,8 @@ - {{Index:{_index}}} + {{Index256:{_index}}} + {{Index16:{_index}}} {{Default}} {{RGB:{_red},{_green},{_blue}}}