Standardize the color table order (#11602)

## Summary of the Pull Request

In the original implementation, we used two different orderings for the color tables. The WT color table used ANSI order, while the conhost color table used a Windows-specific order. This PR standardizes on the ANSI color order everywhere, so the usage of indexed colors is consistent across both parts of the code base, which will hopefully allow more of the code to be shared one day.

## References

This is another small step towards de-duplicating `AdaptDispatch` and `TerminalDispatch` for issue #3849, and is essentially a followup to the SGR dispatch refactoring in PR #6728.

## PR Checklist
* [x] Closes #11461
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #11461

## Detailed Description of the Pull Request / Additional comments

Conhost still needs to deal with legacy attributes using Windows color order, so those values now need to be transposed to ANSI colors order when creating a `TextAttribute` object. This is done with a simple mapping table, which also handles the translation of the default color entries, so it's actually slightly faster than the original code.

And when converting `TextAttribute` values back to legacy console attributes, we were already using a mapping table to handle the narrowing of 256-color values down to 16 colors, so we just needed to adjust that table to account for the translation from ANSI to Windows, and then could make use of the same table for both 256-color and 16-color values.

There are also a few places in conhost that read from or write to the color tables, and those now need to transpose the index values. I've addressed this by creating separate `SetLegacyColorTableEntry` and `GetLegacyColorTableEntry` methods in the `Settings` class which take care of the mapping, so it's now clearer in which cases the code is dealing with legacy values, and which are ANSI values.

These methods are used in the `SetConsoleScreenBufferInfoEx` and `GetConsoleScreenBufferInfoEx` APIs, as well as a few place where color preferences are handled (the registry, shortcut links, and the properties dialog), none of which are particularly sensitive to performance. However, we also use the legacy table when looking up the default colors for rendering (which happens a lot), so I've refactored that code so the default color calculations now only occur once per frame.

The plus side of all of this is that the VT code doesn't need to do the index translation anymore, so we can finally get rid of all the calls to `XTermToWindowsIndex`, and we no longer need a separate color table initialization method for conhost, so I was able to merge a number of color initialization methods into one. We also no longer need to translate from legacy values to ANSI when generating VT sequences for conpty.

The one exception to that is the 16-color VT renderer, which uses the `TextColor::GetLegacyIndex` method to approximate 16-color equivalents for RGB and 256-color values. Since that method returns a legacy index, it still needs to be translated to ANSI before it can be used in a VT sequence. But this should be no worse than it was before.

One more special case is conhost's secret _Color Selection_ feature. That uses `Ctrl`+Number and `Alt`+Number key sequences to highlight parts of the buffer, and the mapping from number to color is based on the Windows color order. So that mapping now needs to be transposed, but that's also not performance sensitive.

The only thing that I haven't bothered to update is the trace logging code in the `Telemetry` class, which logs the first 16 entries in the color table. Those entries are now going to be in a different order, but I didn't think that would be of great concern to anyone.

## Validation Steps Performed

A lot of unit tests needed to be updated to use ANSI color constants when setting indexed colors, where before they might have been expecting values in Windows order. But this replaced a wild mix of different constants, sometimes having to use bit shifting, as well as values mapped with `XTermToWindowsIndex`, so I think the tests are a whole lot clearer now. Only a few cases have been left with literal numbers where that seemed more appropriate.

In addition to getting the unit tests working, I've also manually tested the behaviour of all the console APIs which I thought could be affected by these changes, and confirmed that they produced the same results in the new code as they did in the original implementation.

This includes:
- `WriteConsoleOutput`
- `ReadConsoleOutput`
- `SetConsoleTextAttribute` with `WriteConsoleOutputCharacter`
- `FillConsoleOutputAttribute` and `FillConsoleOutputCharacter` 
- `ScrollConsoleScreenBuffer`
- `GetConsoleScreenBufferInfo`
- `GetConsoleScreenBufferInfoEx`
- `SetConsoleScreenBufferInfoEx`

I've also manually tested changing colors via the console properties menu, the registry, and shortcut links, including setting default colors and popup colors. And I've tested that the "Quirks Mode" is still working as expected in PowerShell.

In terms of performance, I wrote a little test app that filled a 80x9999 buffer with random color combinations using `WriteConsoleOutput`, which I figured was likely to be the most performance sensitive call, and I think it now actually performs slightly better than the original implementation.

I've also tested similar code - just filling the visible window - with SGR VT sequences of various types, and the performance seems about the same as it was before.
This commit is contained in:
James Holderness 2021-11-04 22:13:22 +00:00 committed by GitHub
parent 761203d95e
commit b604117421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 377 additions and 520 deletions

View File

@ -12,8 +12,30 @@ static_assert(alignof(TextAttribute) == 2);
// Ensure that we can memcpy() and memmove() the struct for performance.
static_assert(std::is_trivially_copyable_v<TextAttribute>);
BYTE TextAttribute::s_legacyDefaultForeground = 7;
BYTE TextAttribute::s_legacyDefaultBackground = 0;
namespace
{
constexpr std::array<TextColor, 16> s_initLegacyColorMap(const BYTE defaultIndex)
{
std::array<TextColor, 16> legacyColorMap;
for (auto i = 0u; i < legacyColorMap.size(); i++)
{
const auto legacyIndex = TextColor::TransposeLegacyIndex(i);
gsl::at(legacyColorMap, i) = i == defaultIndex ? TextColor{} : TextColor{ legacyIndex, true };
}
return legacyColorMap;
}
BYTE s_legacyDefaultForeground = 7;
BYTE s_legacyDefaultBackground = 0;
BYTE s_ansiDefaultForeground = 7;
BYTE s_ansiDefaultBackground = 0;
}
// These maps allow for an efficient conversion from a legacy attribute index
// to a TextColor with the corresponding ANSI index, also taking into account
// the legacy index values that need to be converted to a default TextColor.
std::array<TextColor, 16> TextAttribute::s_legacyForegroundColorMap = s_initLegacyColorMap(7);
std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLegacyColorMap(0);
// Routine Description:
// - Sets the legacy attributes which map to and from the default colors.
@ -23,8 +45,22 @@ BYTE TextAttribute::s_legacyDefaultBackground = 0;
// - None
void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept
{
// First we reset the current default color map entries to what they should
// be for a regular translation from a legacy index to an ANSI TextColor.
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{ s_ansiDefaultForeground, true };
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{ s_ansiDefaultBackground, true };
// Then we save the new default attribute values and their corresponding
// ANSI translations. We use the latter values to more efficiently handle
// the "VT Quirk" conversion below.
s_legacyDefaultForeground = defaultAttributes & FG_ATTRS;
s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4;
s_ansiDefaultForeground = TextColor::TransposeLegacyIndex(s_legacyDefaultForeground);
s_ansiDefaultBackground = TextColor::TransposeLegacyIndex(s_legacyDefaultBackground);
// Finally we set the new default color map entries.
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{};
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{};
}
// Routine Description:
@ -55,13 +91,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
const auto bg{ attribute.GetBackground() };
auto copy{ attribute };
if (fg.IsIndex16() &&
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_legacyDefaultForeground & ~FOREGROUND_INTENSITY))
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY))
{
// We don't want to turn 1;37m into 39m (or even 1;39m), as this was meant to mimic a legacy color.
copy.SetDefaultForeground();
}
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground)
{
copy.SetDefaultBackground();
}

View File

@ -41,8 +41,8 @@ public:
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_extendedAttrs{ ExtendedAttributes::Normal },
_hyperlinkId{ 0 }
{
@ -167,13 +167,8 @@ public:
}
private:
static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex)
{
return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true };
}
static BYTE s_legacyDefaultForeground;
static BYTE s_legacyDefaultBackground;
static std::array<TextColor, 16> s_legacyForegroundColorMap;
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2

View File

@ -32,7 +32,7 @@ constexpr std::array<BYTE, 256> CompressedRgbToIndex16 = {
// A table mapping indexed colors from the 256-color palette,
// down to one of the 16 colors in the legacy palette.
constexpr std::array<BYTE, 256> Index256ToIndex16 = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15,
0, 1, 1, 1, 9, 9, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3,
3, 3, 2, 2, 11, 11, 3, 3, 10, 10, 11, 11, 11, 11, 10, 10,
10, 10, 11, 11, 5, 5, 5, 5, 1, 1, 8, 8, 1, 1, 9, 9,
@ -252,11 +252,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
{
return defaultIndex;
}
else if (IsIndex16())
{
return GetIndex();
}
else if (IsIndex256())
else if (IsIndex16() || IsIndex256())
{
return til::at(Index256ToIndex16, GetIndex());
}

View File

@ -48,6 +48,23 @@ enum class ColorType : BYTE
struct TextColor
{
public:
static constexpr BYTE DARK_BLACK = 0;
static constexpr BYTE DARK_RED = 1;
static constexpr BYTE DARK_GREEN = 2;
static constexpr BYTE DARK_YELLOW = 3;
static constexpr BYTE DARK_BLUE = 4;
static constexpr BYTE DARK_MAGENTA = 5;
static constexpr BYTE DARK_CYAN = 6;
static constexpr BYTE DARK_WHITE = 7;
static constexpr BYTE BRIGHT_BLACK = 8;
static constexpr BYTE BRIGHT_RED = 9;
static constexpr BYTE BRIGHT_GREEN = 10;
static constexpr BYTE BRIGHT_YELLOW = 11;
static constexpr BYTE BRIGHT_BLUE = 12;
static constexpr BYTE BRIGHT_MAGENTA = 13;
static constexpr BYTE BRIGHT_CYAN = 14;
static constexpr BYTE BRIGHT_WHITE = 15;
constexpr TextColor() noexcept :
_meta{ ColorType::IsDefault },
_red{ 0 },
@ -96,6 +113,16 @@ public:
COLORREF GetRGB() const noexcept;
static constexpr BYTE TransposeLegacyIndex(const size_t index)
{
// When converting a 16-color index in the legacy Windows order to or
// from an ANSI-compatible order, we need to swap the bits in positions
// 0 and 2. We do this by XORing the index with 00000101, but only if
// one (but not both) of those bit positions is set.
const auto oneBitSet = (index ^ (index >> 2)) & 1;
return gsl::narrow_cast<BYTE>(index ^ oneBitSet ^ (oneBitSet << 2));
}
private:
union
{

View File

@ -237,7 +237,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
Log::Comment(L"Foreground legacy default index should map to default text color.");
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
textAttribute.SetDefaultForeground();
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default foreground text color should map back to legacy default index.");
@ -245,7 +245,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
Log::Comment(L"Background legacy default index should map to default text color.");
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
textAttribute.SetDefaultBackground();
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
@ -288,7 +288,7 @@ void TextAttributeTests::TestBoldAsBright()
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedForeground(0);
attr.SetIndexedForeground(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
@ -297,7 +297,7 @@ void TextAttributeTests::TestBoldAsBright()
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedBackground(2);
attr.SetIndexedBackground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"background should be unaffected by 'bold is bright'");
@ -312,7 +312,7 @@ void TextAttributeTests::TestBoldAsBright()
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
attr.SetBold(true);
attr.SetIndexedForeground(8);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));

View File

@ -80,7 +80,7 @@ namespace SettingsModelLocalTests
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
Utils::InitializeCampbellColorTable(campbellSpan);
Utils::InitializeColorTable(campbellSpan);
Utils::SetColorTableAlpha(campbellSpan, 0);
for (size_t i = 0; i < expectedCampbellTable.size(); i++)

View File

@ -1210,9 +1210,7 @@ try
{
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
// First set up the basic 256 colors
Utils::Initialize256ColorTable(tableView);
// Then use fill the first 16 values with the Campbell scheme
Utils::InitializeCampbellColorTable(tableView);
Utils::InitializeColorTable(tableView);
// Then make sure all the values have an alpha of 255
Utils::SetColorTableAlpha(tableView, 0xff);
}

View File

@ -7,29 +7,6 @@
using namespace Microsoft::Console::VirtualTerminal;
using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
// clang-format off
const BYTE RED_ATTR = 0x01;
const BYTE GREEN_ATTR = 0x02;
const BYTE BLUE_ATTR = 0x04;
const BYTE BRIGHT_ATTR = 0x08;
const BYTE DARK_BLACK = 0;
const BYTE DARK_RED = RED_ATTR;
const BYTE DARK_GREEN = GREEN_ATTR;
const BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR;
const BYTE DARK_BLUE = BLUE_ATTR;
const BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR;
const BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR;
const BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR;
const BYTE BRIGHT_BLACK = BRIGHT_ATTR;
const BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR;
const BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR;
const BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR;
const BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR;
const BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR;
const BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR;
const BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR;
// clang-format on
// Routine Description:
// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG)
// These options are followed by either a 2 (RGB) or 5 (xterm index)
@ -169,100 +146,100 @@ bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept
attr.SetOverlined(false);
break;
case ForegroundBlack:
attr.SetIndexedForeground(DARK_BLACK);
attr.SetIndexedForeground(TextColor::DARK_BLACK);
break;
case ForegroundBlue:
attr.SetIndexedForeground(DARK_BLUE);
attr.SetIndexedForeground(TextColor::DARK_BLUE);
break;
case ForegroundGreen:
attr.SetIndexedForeground(DARK_GREEN);
attr.SetIndexedForeground(TextColor::DARK_GREEN);
break;
case ForegroundCyan:
attr.SetIndexedForeground(DARK_CYAN);
attr.SetIndexedForeground(TextColor::DARK_CYAN);
break;
case ForegroundRed:
attr.SetIndexedForeground(DARK_RED);
attr.SetIndexedForeground(TextColor::DARK_RED);
break;
case ForegroundMagenta:
attr.SetIndexedForeground(DARK_MAGENTA);
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
break;
case ForegroundYellow:
attr.SetIndexedForeground(DARK_YELLOW);
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
break;
case ForegroundWhite:
attr.SetIndexedForeground(DARK_WHITE);
attr.SetIndexedForeground(TextColor::DARK_WHITE);
break;
case BackgroundBlack:
attr.SetIndexedBackground(DARK_BLACK);
attr.SetIndexedBackground(TextColor::DARK_BLACK);
break;
case BackgroundBlue:
attr.SetIndexedBackground(DARK_BLUE);
attr.SetIndexedBackground(TextColor::DARK_BLUE);
break;
case BackgroundGreen:
attr.SetIndexedBackground(DARK_GREEN);
attr.SetIndexedBackground(TextColor::DARK_GREEN);
break;
case BackgroundCyan:
attr.SetIndexedBackground(DARK_CYAN);
attr.SetIndexedBackground(TextColor::DARK_CYAN);
break;
case BackgroundRed:
attr.SetIndexedBackground(DARK_RED);
attr.SetIndexedBackground(TextColor::DARK_RED);
break;
case BackgroundMagenta:
attr.SetIndexedBackground(DARK_MAGENTA);
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
break;
case BackgroundYellow:
attr.SetIndexedBackground(DARK_YELLOW);
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
break;
case BackgroundWhite:
attr.SetIndexedBackground(DARK_WHITE);
attr.SetIndexedBackground(TextColor::DARK_WHITE);
break;
case BrightForegroundBlack:
attr.SetIndexedForeground(BRIGHT_BLACK);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
break;
case BrightForegroundBlue:
attr.SetIndexedForeground(BRIGHT_BLUE);
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
break;
case BrightForegroundGreen:
attr.SetIndexedForeground(BRIGHT_GREEN);
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
break;
case BrightForegroundCyan:
attr.SetIndexedForeground(BRIGHT_CYAN);
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
break;
case BrightForegroundRed:
attr.SetIndexedForeground(BRIGHT_RED);
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
break;
case BrightForegroundMagenta:
attr.SetIndexedForeground(BRIGHT_MAGENTA);
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
break;
case BrightForegroundYellow:
attr.SetIndexedForeground(BRIGHT_YELLOW);
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
break;
case BrightForegroundWhite:
attr.SetIndexedForeground(BRIGHT_WHITE);
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
break;
case BrightBackgroundBlack:
attr.SetIndexedBackground(BRIGHT_BLACK);
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
break;
case BrightBackgroundBlue:
attr.SetIndexedBackground(BRIGHT_BLUE);
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
break;
case BrightBackgroundGreen:
attr.SetIndexedBackground(BRIGHT_GREEN);
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
break;
case BrightBackgroundCyan:
attr.SetIndexedBackground(BRIGHT_CYAN);
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
break;
case BrightBackgroundRed:
attr.SetIndexedBackground(BRIGHT_RED);
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
break;
case BrightBackgroundMagenta:
attr.SetIndexedBackground(BRIGHT_MAGENTA);
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
break;
case BrightBackgroundYellow:
attr.SetIndexedBackground(BRIGHT_YELLOW);
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
break;
case BrightBackgroundWhite:
attr.SetIndexedBackground(BRIGHT_WHITE);
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
break;
case ForegroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);

View File

@ -2901,15 +2901,9 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs()
auto defaultAttrs = si.GetAttributes();
auto conhostGreenAttrs = TextAttribute();
// Conhost and Terminal store attributes in different bits.
// conhostGreenAttrs.SetIndexedAttributes(std::nullopt,
// { static_cast<BYTE>(FOREGROUND_GREEN) });
conhostGreenAttrs.SetIndexedBackground(FOREGROUND_GREEN);
conhostGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN);
auto terminalGreenAttrs = TextAttribute();
// terminalGreenAttrs.SetIndexedAttributes(std::nullopt,
// { static_cast<BYTE>(XTERM_GREEN_ATTR) });
terminalGreenAttrs.SetIndexedBackground(XTERM_GREEN_ATTR);
terminalGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN);
// Use an initial ^[[m to start printing with default-on-default
sm.ProcessString(L"\x1b[m");
@ -2942,7 +2936,7 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs()
auto verifyBuffer = [&](const TextBuffer& tb, const til::rectangle viewport, const bool isTerminal, const bool afterResize) {
const auto width = viewport.width<short>();
// Conhost and Terminal store attributes in different bits.
// Conhost and Terminal attributes are potentially different.
const auto greenAttrs = isTerminal ? terminalGreenAttrs : conhostGreenAttrs;
for (short row = 0; row < tb.GetSize().Height(); row++)
@ -3034,13 +3028,11 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground()
auto defaultAttrs = si.GetAttributes();
auto conhostBlueAttrs = defaultAttrs;
// Conhost and Terminal store attributes in different bits.
conhostBlueAttrs.SetIndexedForeground(FOREGROUND_GREEN);
conhostBlueAttrs.SetIndexedBackground(FOREGROUND_BLUE);
conhostBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN);
conhostBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE);
auto terminalBlueAttrs = TextAttribute();
terminalBlueAttrs.SetIndexedForeground(XTERM_GREEN_ATTR);
terminalBlueAttrs.SetIndexedBackground(XTERM_BLUE_ATTR);
terminalBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN);
terminalBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE);
// We're going to print 4 more rows than the entire height of the viewport,
// causing the buffer to circle 4 times. This is 2 extra iterations of the
@ -3083,7 +3075,7 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground()
const auto width = viewport.width<short>();
const auto isTerminal = viewport.top() != 0;
// Conhost and Terminal store attributes in different bits.
// Conhost and Terminal attributes are potentially different.
const auto blueAttrs = isTerminal ? terminalBlueAttrs : conhostBlueAttrs;
for (short row = 0; row < viewport.bottom<short>() - 2; row++)

View File

@ -1,52 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- conattrs.cpp
Abstract:
- Defines common operations on console attributes, especially in regards to
finding the nearest color from a color table.
Author(s):
- Mike Griese (migrie) 01-Sept-2017
--*/
#include "precomp.h"
#include "../inc/conattrs.hpp"
#include <cmath>
// Function Description:
// - Converts the value of a xterm color table index to the windows color table equivalent.
// Arguments:
// - xtermTableEntry: the xterm color table index
// Return Value:
// - The windows color table equivalent.
WORD XtermToWindowsIndex(const size_t xtermTableEntry) noexcept
{
const bool fRed = WI_IsFlagSet(xtermTableEntry, XTERM_RED_ATTR);
const bool fGreen = WI_IsFlagSet(xtermTableEntry, XTERM_GREEN_ATTR);
const bool fBlue = WI_IsFlagSet(xtermTableEntry, XTERM_BLUE_ATTR);
const bool fBright = WI_IsFlagSet(xtermTableEntry, XTERM_BRIGHT_ATTR);
return (fRed ? WINDOWS_RED_ATTR : 0x0) +
(fGreen ? WINDOWS_GREEN_ATTR : 0x0) +
(fBlue ? WINDOWS_BLUE_ATTR : 0x0) +
(fBright ? WINDOWS_BRIGHT_ATTR : 0x0);
}
// Function Description:
// - Converts the value of a xterm color table index to the windows color table
// equivalent. The range of values is [0, 255], where the lowest 16 are
// mapped to the equivalent Windows index, and the rest of the values are
// passed through.
// Arguments:
// - xtermTableEntry: the xterm color table index
// Return Value:
// - The windows color table equivalent.
WORD Xterm256ToWindowsIndex(const size_t xtermTableEntry) noexcept
{
return xtermTableEntry < 16 ? XtermToWindowsIndex(xtermTableEntry) :
static_cast<WORD>(xtermTableEntry);
}

View File

@ -231,7 +231,7 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
{
const auto fg = GetDefaultForegroundColor();
return fg != INVALID_COLOR ? fg : GetColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
}
// Method Description:
@ -246,23 +246,37 @@ COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
{
const auto bg = GetDefaultBackgroundColor();
return bg != INVALID_COLOR ? bg : GetColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
return bg != INVALID_COLOR ? bg : GetLegacyColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and our configured default attributes.
// Arguments:
// - attr: the TextAttribute to retrieve the foreground color of.
// - attr: the TextAttribute to retrieve the foreground and background color of.
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
{
return LookupAttributeColors(attr, GetDefaultForeground(), GetDefaultBackground());
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and the given default color values.
// Arguments:
// - attr: the TextAttribute to retrieve the foreground and background color of.
// - defaultFg: the COLORREF to use for a default foreground color.
// - defaultBg: the COLORREF to use for a default background color.
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept
{
_blinkingState.RecordBlinkingUsage(attr);
return attr.CalculateRgbColors(
GetColorTable(),
GetDefaultForeground(),
GetDefaultBackground(),
defaultFg,
defaultBg,
IsScreenReversed(),
_blinkingState.IsBlinkingFaint());
}

View File

@ -605,7 +605,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
for (size_t i = 0; i < std::size(data.ColorTable); i++)
{
gci.SetColorTableEntry(i, data.ColorTable[i]);
gci.SetLegacyColorTableEntry(i, data.ColorTable[i]);
}
context.SetDefaultAttributes(TextAttribute{ data.wAttributes }, TextAttribute{ data.wPopupAttributes });
@ -1978,7 +1978,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
value = gci.GetColorTableEntry(::Xterm256ToWindowsIndex(index));
value = gci.GetColorTableEntry(index);
return S_OK;
}
@ -2004,7 +2004,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetColorTableEntry(::Xterm256ToWindowsIndex(index), value);
gci.SetColorTableEntry(index, value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.

View File

@ -7,7 +7,6 @@
<ClCompile Include="..\CommandListPopup.cpp" />
<ClCompile Include="..\CopyFromCharPopup.cpp" />
<ClCompile Include="..\CopyToCharPopup.cpp" />
<ClCompile Include="..\conattrs.cpp" />
<ClCompile Include="..\ConsoleArguments.cpp" />
<ClCompile Include="..\CursorBlinker.cpp" />
<ClCompile Include="..\readDataCooked.cpp" />

View File

@ -138,9 +138,6 @@
<ClCompile Include="..\writeData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\conattrs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\VtInputThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -310,7 +310,7 @@ void Registry::LoadFromRegistry(_In_ PCWSTR const pwszConsoleTitle)
nullptr);
if (NT_SUCCESS(Status))
{
_pSettings->SetColorTableEntry(i, dwValue);
_pSettings->SetLegacyColorTableEntry(i, dwValue);
}
}

View File

@ -110,6 +110,8 @@ void RenderData::UnlockConsole() noexcept
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
_defaultForeground = gci.GetDefaultForeground();
_defaultBackground = gci.GetDefaultBackground();
return gci.GetActiveOutputBuffer().GetAttributes();
}
@ -362,7 +364,7 @@ const std::vector<size_t> RenderData::GetPatternId(const COORD /*location*/) con
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.LookupAttributeColors(attr);
return gci.LookupAttributeColors(attr, _defaultForeground, _defaultBackground);
}
#pragma endregion

View File

@ -15,6 +15,7 @@ Author(s):
#pragma once
#include "../renderer/inc/IRenderData.hpp"
#include "../types/inc/colorTable.hpp"
#include "../types/IUiaData.h"
class RenderData final :
@ -71,4 +72,8 @@ public:
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
const bool IsUiaDataInitialized() const noexcept override { return true; }
#pragma endregion
private:
COLORREF _defaultForeground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 7);
COLORREF _defaultBackground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 0);
};

View File

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

View File

@ -661,13 +661,15 @@ bool Selection::_HandleColorSelection(const INPUT_KEY_INFO* const pInputKeyInfo)
if (fAltPressed || fCtrlPressed)
{
TextAttribute selectionAttr;
const BYTE colorIndex = gsl::narrow_cast<BYTE>(wVirtualKeyCode - '0' + 6);
// The key number corresponds to the Windows color table order, so the value
// need to be transposed to obtain the index in an ANSI-compatible order.
const auto colorIndex = TextColor::TransposeLegacyIndex(wVirtualKeyCode - '0' + 6);
if (fCtrlPressed)
{
// Setting background color. Set fg color to black.
selectionAttr.SetIndexedBackground256(colorIndex);
selectionAttr.SetIndexedForeground256(0);
selectionAttr.SetIndexedForeground256(TextColor::DARK_BLACK);
}
else
{

View File

@ -127,6 +127,7 @@ public:
COLORREF GetDefaultForeground() const noexcept;
COLORREF GetDefaultBackground() const noexcept;
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const noexcept;
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept;
void SetTitle(const std::wstring_view newTitle);
void SetTitlePrefix(const std::wstring_view newTitlePrefix);

View File

@ -82,8 +82,7 @@ Settings::Settings() :
_CursorType = CursorType::Legacy;
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
::Microsoft::Console::Utils::Initialize256ColorTable(tableView);
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
::Microsoft::Console::Utils::InitializeColorTable(tableView);
}
// Routine Description:
@ -122,8 +121,8 @@ void Settings::ApplyDesktopSpecificDefaults()
_uNumberOfHistoryBuffers = 4;
_bHistoryNoDup = FALSE;
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
gsl::span<COLORREF> tableView = { _colorTable.data(), 16 };
::Microsoft::Console::Utils::InitializeColorTable(tableView);
_fTrimLeadingZeros = false;
_fEnableColorSelection = false;
@ -222,7 +221,7 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
_uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers;
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
SetColorTableEntry(i, pStateInfo->ColorTable[i]);
SetLegacyColorTableEntry(i, pStateInfo->ColorTable[i]);
}
_uCodePage = pStateInfo->CodePage;
_bWrapText = !!pStateInfo->fWrapText;
@ -267,7 +266,7 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers;
for (size_t i = 0; i < std::size(csi.ColorTable); i++)
{
csi.ColorTable[i] = GetColorTableEntry(i);
csi.ColorTable[i] = GetLegacyColorTableEntry(i);
}
csi.CodePage = _uCodePage;
csi.fWrapText = !!_bWrapText;
@ -726,11 +725,6 @@ void Settings::SetHistoryNoDup(const bool bHistoryNoDup)
_bHistoryNoDup = bHistoryNoDup;
}
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
{
_colorTable.at(index) = ColorValue;
}
bool Settings::IsStartupTitleIsLinkNameSet() const
{
return WI_IsFlagSet(_dwStartupFlags, STARTF_TITLEISLINKNAME);
@ -746,11 +740,26 @@ void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset)
_dwStartupFlags &= ~dwFlagToUnset;
}
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
{
_colorTable.at(index) = ColorValue;
}
COLORREF Settings::GetColorTableEntry(const size_t index) const
{
return _colorTable.at(index);
}
void Settings::SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue)
{
_colorTable.at(TextColor::TransposeLegacyIndex(index)) = ColorValue;
}
COLORREF Settings::GetLegacyColorTableEntry(const size_t index) const
{
return _colorTable.at(TextColor::TransposeLegacyIndex(index));
}
COLORREF Settings::GetCursorColor() const noexcept
{
return _CursorColor;

View File

@ -167,6 +167,8 @@ public:
void SetColorTableEntry(const size_t index, const COLORREF ColorValue);
COLORREF GetColorTableEntry(const size_t index) const;
void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue);
COLORREF GetLegacyColorTableEntry(const size_t index) const;
COLORREF GetCursorColor() const noexcept;
CursorType GetCursorType() const noexcept;

View File

@ -89,7 +89,6 @@ SOURCES = \
..\utf8ToWideCharParser.cpp \
..\conareainfo.cpp \
..\conimeinfo.cpp \
..\conattrs.cpp \
..\ConsoleArguments.cpp \
..\CommandNumberPopup.cpp \
..\CommandListPopup.cpp \

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
@ -1634,74 +1634,74 @@ void ScreenBufferTests::VtSetColorTable()
L"Process some valid sequences for setting the table"));
stateMachine.ProcessString(L"\x1b]4;0;rgb:1/1/1\x7");
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(0)));
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), gci.GetColorTableEntry(0));
stateMachine.ProcessString(L"\x1b]4;1;rgb:1/23/1\x7");
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(1)));
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x11), gci.GetColorTableEntry(1));
stateMachine.ProcessString(L"\x1b]4;2;rgb:1/23/12\x7");
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(2)));
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x12), gci.GetColorTableEntry(2));
stateMachine.ProcessString(L"\x1b]4;3;rgb:12/23/12\x7");
VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(3)));
VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(3));
stateMachine.ProcessString(L"\x1b]4;4;rgb:ff/a1/1b\x7");
VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(::XtermToWindowsIndex(4)));
VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(4));
stateMachine.ProcessString(L"\x1b]4;5;rgb:ff/a1/1b\x1b\\");
VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(0xff, 0xa1, 0x1b), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"Try a bunch of invalid sequences."));
Log::Comment(NoThrowString().Format(
L"First start by setting an entry to a known value to compare to."));
stateMachine.ProcessString(L"\x1b]4;5;rgb:09/09/09\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: Missing the first component"));
stateMachine.ProcessString(L"\x1b]4;5;rgb:/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: too many components"));
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/1/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: no second component"));
stateMachine.ProcessString(L"\x1b]4;5;rgb:1//1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: no components"));
stateMachine.ProcessString(L"\x1b]4;5;rgb://\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: no third component"));
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/11/\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: rgbi is not a supported color space"));
stateMachine.ProcessString(L"\x1b]4;5;rgbi:1/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: cmyk is not a supported color space"));
stateMachine.ProcessString(L"\x1b]4;5;cmyk:1/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: no table index should do nothing"));
stateMachine.ProcessString(L"\x1b]4;;rgb:1/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
Log::Comment(NoThrowString().Format(
L"invalid: need to specify a color space"));
stateMachine.ProcessString(L"\x1b]4;5;1/1/1\x1b\\");
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(5));
}
void ScreenBufferTests::ResizeTraditionalDoesNotDoubleFreeAttrRows()
@ -1912,8 +1912,8 @@ void ScreenBufferTests::VtEraseAllPersistCursorFillColor()
L"The viewport should be full of dark_red on bright_blue"));
auto expectedAttr = TextAttribute{};
expectedAttr.SetIndexedForeground((BYTE)XtermToWindowsIndex(1));
expectedAttr.SetIndexedBackground((BYTE)XtermToWindowsIndex(12));
expectedAttr.SetIndexedForeground(TextColor::DARK_RED);
expectedAttr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
stateMachine.ProcessString(L"\x1b[31;104m");
VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes());
@ -2256,8 +2256,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
COLORREF magenta = RGB(255, 0, 255);
COLORREF yellow = RGB(255, 255, 0);
COLORREF brightGreen = gci.GetColorTableEntry(::XtermToWindowsIndex(10));
COLORREF darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4));
COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
gci.SetDefaultForegroundColor(yellow);
gci.SetDefaultBackgroundColor(magenta);
@ -2292,8 +2292,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
// See the log comment above for description of these values.
TextAttribute expectedDefaults{};
TextAttribute expectedTwo;
expectedTwo.SetIndexedForeground((BYTE)XtermToWindowsIndex(10));
expectedTwo.SetIndexedBackground((BYTE)XtermToWindowsIndex(4));
expectedTwo.SetIndexedForeground(TextColor::BRIGHT_GREEN);
expectedTwo.SetIndexedBackground(TextColor::DARK_BLUE);
TextAttribute expectedThree = expectedTwo;
expectedThree.SetDefaultForeground();
// Four is the same as Defaults
@ -2705,7 +2705,7 @@ void ScreenBufferTests::SetGlobalColorTable()
VERIFY_SUCCEEDED(mainBuffer.SetViewportOrigin(true, COORD({ 0, 0 }), true));
mainCursor.SetPosition({ 0, 0 });
const COLORREF originalRed = gci.GetColorTableEntry(4);
const COLORREF originalRed = gci.GetColorTableEntry(TextColor::DARK_RED);
const COLORREF testColor = RGB(0x11, 0x22, 0x33);
VERIFY_ARE_NOT_EQUAL(originalRed, testColor);
@ -3209,10 +3209,10 @@ void ScreenBufferTests::DontResetColorsAboveVirtualBottom()
L"cursor=%s", VerifyOutputTraits<COORD>::ToString(cursor.GetPosition()).GetBuffer()));
Log::Comment(NoThrowString().Format(
L"viewport=%s", VerifyOutputTraits<SMALL_RECT>::ToString(si.GetViewport().ToInclusive()).GetBuffer()));
const auto darkRed = gci.GetColorTableEntry(::XtermToWindowsIndex(1));
const auto darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4));
const auto darkBlack = gci.GetColorTableEntry(::XtermToWindowsIndex(0));
const auto darkWhite = gci.GetColorTableEntry(::XtermToWindowsIndex(7));
const auto darkRed = gci.GetColorTableEntry(TextColor::DARK_RED);
const auto darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
const auto darkBlack = gci.GetColorTableEntry(TextColor::DARK_BLACK);
const auto darkWhite = gci.GetColorTableEntry(TextColor::DARK_WHITE);
stateMachine.ProcessString(L"\x1b[31;44m");
stateMachine.ProcessString(L"X");
stateMachine.ProcessString(L"\x1b[m");
@ -6168,8 +6168,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
/* Write red on blue, verify that it comes through */
{
TextAttribute vtRedOnBlueAttribute{};
vtRedOnBlueAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(1)), false });
vtRedOnBlueAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(4)), false });
vtRedOnBlueAttribute.SetForeground(TextColor{ TextColor::DARK_RED, false });
vtRedOnBlueAttribute.SetBackground(TextColor{ TextColor::DARK_BLUE, false });
seq = L"\x1b[31;44m";
seqCb = 2 * seq.size();
@ -6187,8 +6187,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
/* Write white on black, verify that it acts as expected for the quirk mode */
{
TextAttribute vtWhiteOnBlackAttribute{};
vtWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), false });
vtWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), false });
vtWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false });
vtWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false });
const TextAttribute quirkExpectedAttribute{ useQuirk ? defaultAttribute : vtWhiteOnBlackAttribute };
@ -6208,8 +6208,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
/* Write bright white on black, verify that it acts as expected for the quirk mode */
{
TextAttribute vtBrightWhiteOnBlackAttribute{};
vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), false });
vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), false });
vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false });
vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false });
vtBrightWhiteOnBlackAttribute.SetBold(true);
TextAttribute vtBrightWhiteOnDefaultAttribute{ vtBrightWhiteOnBlackAttribute }; // copy the above attribute
@ -6233,8 +6233,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
/* Write a 256-color white on a 256-color black, make sure the quirk does not suppress it */
{
TextAttribute vtWhiteOnBlack256Attribute{};
vtWhiteOnBlack256Attribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), true });
vtWhiteOnBlack256Attribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), true });
vtWhiteOnBlack256Attribute.SetForeground(TextColor{ TextColor::DARK_WHITE, true });
vtWhiteOnBlack256Attribute.SetBackground(TextColor{ TextColor::DARK_BLACK, true });
// reset (disable bold from the last test) before setting both colors
seq = L"\x1b[m\x1b[38;5;7;48;5;0m"; // the quirk should *not* suppress this (!)

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
@ -779,8 +779,8 @@ void TextBufferTests::TestMixedRgbAndLegacyBrightness()
// '\E[m\E[32mX\E[1mX'
// Make sure that the second X is a BRIGHT green, not white.
Log::Comment(L"Case 4 ;\"\\E[m\\E[32mX\\E[1mX\"");
const auto dark_green = gci.GetColorTableEntry(2);
const auto bright_green = gci.GetColorTableEntry(10);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
VERIFY_ARE_NOT_EQUAL(dark_green, bright_green);
wchar_t* sequence = L"\x1b[m\x1b[32mX\x1b[1mX";
@ -887,8 +887,8 @@ void TextBufferTests::TestUnBold()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const auto dark_green = gci.GetColorTableEntry(2);
const auto bright_green = gci.GetColorTableEntry(10);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
Log::Comment(NoThrowString().Format(
L"cursor={X:%d,Y:%d}",
@ -938,8 +938,8 @@ void TextBufferTests::TestUnBoldRgb()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const auto dark_green = gci.GetColorTableEntry(2);
const auto bright_green = gci.GetColorTableEntry(10);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
Log::Comment(NoThrowString().Format(
L"cursor={X:%d,Y:%d}",
@ -997,8 +997,8 @@ void TextBufferTests::TestComplexUnBold()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const auto dark_green = gci.GetColorTableEntry(2);
const auto bright_green = gci.GetColorTableEntry(10);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
Log::Comment(NoThrowString().Format(
L"cursor={X:%d,Y:%d}",
@ -1079,8 +1079,8 @@ void TextBufferTests::CopyAttrs()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const auto dark_blue = gci.GetColorTableEntry(1);
const auto dark_magenta = gci.GetColorTableEntry(5);
const auto dark_blue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
const auto dark_magenta = gci.GetColorTableEntry(TextColor::DARK_MAGENTA);
Log::Comment(NoThrowString().Format(
L"cursor={X:%d,Y:%d}",
@ -1133,7 +1133,7 @@ void TextBufferTests::EmptySgrTest()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const COLORREF darkRed = gci.GetColorTableEntry(4);
const COLORREF darkRed = gci.GetColorTableEntry(TextColor::DARK_RED);
Log::Comment(NoThrowString().Format(
L"cursor={X:%d,Y:%d}",
x,
@ -1192,7 +1192,7 @@ void TextBufferTests::TestReverseReset()
const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y;
const auto dark_green = gci.GetColorTableEntry(2);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const COLORREF rgbColor = RGB(128, 5, 255);
Log::Comment(NoThrowString().Format(
@ -1258,9 +1258,9 @@ void TextBufferTests::CopyLastAttr()
const COLORREF defaultBrightYellow = RGB(249, 241, 165);
const COLORREF defaultBrightCyan = RGB(97, 214, 214);
gci.SetColorTableEntry(8, defaultBrightBlack);
gci.SetColorTableEntry(14, defaultBrightYellow);
gci.SetColorTableEntry(11, defaultBrightCyan);
gci.SetColorTableEntry(TextColor::BRIGHT_BLACK, defaultBrightBlack);
gci.SetColorTableEntry(TextColor::BRIGHT_YELLOW, defaultBrightYellow);
gci.SetColorTableEntry(TextColor::BRIGHT_CYAN, defaultBrightCyan);
// Write (solFg, solBG) X \n
// (solFg, solBG) X (solCyan, solBG) X \n
@ -1405,8 +1405,8 @@ void TextBufferTests::TestResetClearsBoldness()
si.SetAttributes(defaultAttribute);
const auto [defaultFg, defaultBg] = gci.LookupAttributeColors(si.GetAttributes());
const auto dark_green = gci.GetColorTableEntry(2);
const auto bright_green = gci.GetColorTableEntry(10);
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
wchar_t* sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD";
Log::Comment(NoThrowString().Format(sequence));

View File

@ -470,7 +470,7 @@ void VtRendererTest::Xterm256TestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the BG----"));
textAttributes.SetIndexedBackground(FOREGROUND_RED);
textAttributes.SetIndexedBackground(TextColor::DARK_RED);
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -479,7 +479,7 @@ void VtRendererTest::Xterm256TestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the FG----"));
textAttributes.SetIndexedForeground(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
textAttributes.SetIndexedForeground(TextColor::DARK_WHITE);
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -515,7 +515,7 @@ void VtRendererTest::Xterm256TestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the FG to a 256-color index----"));
textAttributes.SetIndexedForeground256(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
textAttributes.SetIndexedForeground256(TextColor::DARK_WHITE);
qExpectedInput.push_back("\x1b[38;5;7m"); // Foreground DARK_WHITE (256-Color Index)
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -524,7 +524,7 @@ void VtRendererTest::Xterm256TestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the BG to a 256-color index----"));
textAttributes.SetIndexedBackground256(FOREGROUND_RED);
textAttributes.SetIndexedBackground256(TextColor::DARK_RED);
qExpectedInput.push_back("\x1b[48;5;1m"); // Background DARK_RED (256-Color Index)
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -859,7 +859,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
Log::Comment(L"----Set Green Foreground----");
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
textAttributes.SetIndexedForeground(TextColor::DARK_GREEN);
qExpectedInput.push_back("\x1b[32m");
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
@ -870,7 +870,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
Log::Comment(L"----Set Green Background----");
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
textAttributes.SetIndexedBackground(TextColor::DARK_GREEN);
qExpectedInput.push_back("\x1b[42m");
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
@ -1104,7 +1104,7 @@ void VtRendererTest::XtermTestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the BG----"));
textAttributes.SetIndexedBackground(FOREGROUND_RED);
textAttributes.SetIndexedBackground(TextColor::DARK_RED);
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -1113,7 +1113,7 @@ void VtRendererTest::XtermTestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the FG----"));
textAttributes.SetIndexedForeground(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
textAttributes.SetIndexedForeground(TextColor::DARK_WHITE);
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -1150,7 +1150,7 @@ void VtRendererTest::XtermTestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the FG to a 256-color index----"));
textAttributes.SetIndexedForeground256(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
textAttributes.SetIndexedForeground256(TextColor::DARK_WHITE);
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -1159,7 +1159,7 @@ void VtRendererTest::XtermTestColors()
Log::Comment(NoThrowString().Format(
L"----Change only the BG to a 256-color index----"));
textAttributes.SetIndexedBackground256(FOREGROUND_RED);
textAttributes.SetIndexedBackground256(TextColor::DARK_RED);
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
&renderData,
@ -1351,7 +1351,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
Log::Comment(L"----Set Green Foreground----");
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
textAttributes.SetIndexedForeground(TextColor::DARK_GREEN);
qExpectedInput.push_back("\x1b[32m");
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
@ -1362,7 +1362,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
Log::Comment(L"----Set Green Background----");
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
textAttributes.SetIndexedBackground(TextColor::DARK_GREEN);
qExpectedInput.push_back("\x1b[42m");
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));

View File

@ -22,20 +22,6 @@ enum class ExtendedAttributes : BYTE
};
DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes);
WORD XtermToWindowsIndex(const size_t index) noexcept;
WORD Xterm256ToWindowsIndex(const size_t index) noexcept;
WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground);
constexpr WORD WINDOWS_RED_ATTR = FOREGROUND_RED;
constexpr WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN;
constexpr WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE;
constexpr WORD WINDOWS_BRIGHT_ATTR = FOREGROUND_INTENSITY;
constexpr WORD XTERM_RED_ATTR = 0x01;
constexpr WORD XTERM_GREEN_ATTR = 0x02;
constexpr WORD XTERM_BLUE_ATTR = 0x04;
constexpr WORD XTERM_BRIGHT_ATTR = 0x08;
enum class CursorType : unsigned int
{
Legacy = 0x0, // uses the cursor's height value to range from underscore-like to full box

View File

@ -208,7 +208,11 @@ void Clipboard::StoreSelectionToClipboard(bool const copyFormatting)
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& buffer = gci.GetActiveOutputBuffer().GetTextBuffer();
const auto GetAttributeColors = std::bind(&CONSOLE_INFORMATION::LookupAttributeColors, &gci, std::placeholders::_1);
const auto defaultForeground = gci.GetDefaultForeground();
const auto defaultBackground = gci.GetDefaultBackground();
const auto GetAttributeColors = [=, &gci](const auto& attr) {
return gci.LookupAttributeColors(attr, defaultForeground, defaultBackground);
};
bool includeCRLF, trimTrailingWhitespace;
if (WI_IsFlagSet(GetKeyState(VK_SHIFT), KEY_PRESSED))

View File

@ -337,7 +337,7 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
pStateInfo->ColorTable[i] = gci.GetColorTableEntry(i);
pStateInfo->ColorTable[i] = gci.GetLegacyColorTableEntry(i);
}
// Create mutable copies of the titles so the propsheet can do something with them.
@ -566,7 +566,7 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
{
gci.SetColorTableEntry(i, pStateInfo->ColorTable[i]);
gci.SetLegacyColorTableEntry(i, pStateInfo->ColorTable[i]);
}
// Ensure that attributes only contain color specification.

View File

@ -199,13 +199,14 @@ using namespace Microsoft::Console::Render;
}
// Method Description:
// - Formats and writes a sequence to change the current text attributes.
// - Formats and writes a sequence to change the current text attributes to an
// indexed color from the 16-color table.
// Arguments:
// - wAttr: Windows color table index to emit as a VT sequence
// - index: color table index to emit as a VT sequence
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition16Color(const WORD wAttr,
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition16Color(const BYTE index,
const bool fIsForeground) noexcept
{
// Always check using the foreground flags, because the bg flags constants
@ -220,28 +221,22 @@ using namespace Microsoft::Console::Render;
// terminals display the bright color when displaying bolded text.
// By specifying the boldness and brightness separately, we'll make sure the
// terminal has an accurate representation of our buffer.
const int vtIndex = 30 +
(fIsForeground ? 0 : 10) +
((WI_IsFlagSet(wAttr, FOREGROUND_INTENSITY)) ? 60 : 0) +
(WI_IsFlagSet(wAttr, FOREGROUND_RED) ? 1 : 0) +
(WI_IsFlagSet(wAttr, FOREGROUND_GREEN) ? 2 : 0) +
(WI_IsFlagSet(wAttr, FOREGROUND_BLUE) ? 4 : 0);
return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), vtIndex);
const auto prefix = WI_IsFlagSet(index, FOREGROUND_INTENSITY) ? (fIsForeground ? 90 : 100) : (fIsForeground ? 30 : 40);
return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), prefix + (index & 7));
}
// Method Description:
// - Formats and writes a sequence to change the current text attributes to an
// indexed color from the 256-color table.
// Arguments:
// - wAttr: Windows color table index to emit as a VT sequence
// - index: color table index to emit as a VT sequence
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const WORD index,
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const BYTE index,
const bool fIsForeground) noexcept
{
return _WriteFormatted(FMT_COMPILE("\x1b[{}8;5;{}m"), fIsForeground ? '3' : '4', ::Xterm256ToWindowsIndex(index));
return _WriteFormatted(FMT_COMPILE("\x1b[{}8;5;{}m"), fIsForeground ? '3' : '4', index);
}
// Method Description:

View File

@ -287,9 +287,10 @@ using namespace Microsoft::Console::Types;
}
// We use the legacy color calculations to generate an approximation of the
// colors in the 16-color table.
auto fgIndex = fg.GetLegacyIndex(0);
auto bgIndex = bg.GetLegacyIndex(0);
// colors in the Windows 16-color table, but we need to transpose those
// values to obtain an index in an ANSI-compatible order.
auto fgIndex = TextColor::TransposeLegacyIndex(fg.GetLegacyIndex(0));
auto bgIndex = TextColor::TransposeLegacyIndex(bg.GetLegacyIndex(0));
// If the bold attribute is set, and the foreground can be brightened, then do so.
const bool brighten = textAttributes.IsBold() && fg.CanBeBrightened();

View File

@ -185,9 +185,9 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT _ClearScreen() noexcept;
[[nodiscard]] HRESULT _ClearScrollback() noexcept;
[[nodiscard]] HRESULT _ChangeTitle(const std::string& title) noexcept;
[[nodiscard]] HRESULT _SetGraphicsRendition16Color(const WORD wAttr,
[[nodiscard]] HRESULT _SetGraphicsRendition16Color(const BYTE index,
const bool fIsForeground) noexcept;
[[nodiscard]] HRESULT _SetGraphicsRendition256Color(const WORD index,
[[nodiscard]] HRESULT _SetGraphicsRendition256Color(const BYTE index,
const bool fIsForeground) noexcept;
[[nodiscard]] HRESULT _SetGraphicsRenditionRGBColor(const COLORREF color,
const bool fIsForeground) noexcept;

View File

@ -2541,13 +2541,13 @@ void AdaptDispatch::_ReportSGRSetting() const
const auto iterator = std::back_insert_iterator(response);
if (color.IsIndex16())
{
const auto index = XtermToWindowsIndex(color.GetIndex());
const auto index = color.GetIndex();
const auto colorParameter = base + (index >= 8 ? 60 : 0) + (index % 8);
fmt::format_to(iterator, FMT_STRING(L";{}"), colorParameter);
}
else if (color.IsIndex256())
{
const auto index = Xterm256ToWindowsIndex(color.GetIndex());
const auto index = color.GetIndex();
fmt::format_to(iterator, FMT_STRING(L";{};5;{}"), base + 8, index);
}
else if (color.IsRgb())

View File

@ -13,29 +13,6 @@
using namespace Microsoft::Console::VirtualTerminal;
using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
// clang-format off
constexpr BYTE BLUE_ATTR = 0x01;
constexpr BYTE GREEN_ATTR = 0x02;
constexpr BYTE RED_ATTR = 0x04;
constexpr BYTE BRIGHT_ATTR = 0x08;
constexpr BYTE DARK_BLACK = 0;
constexpr BYTE DARK_RED = RED_ATTR;
constexpr BYTE DARK_GREEN = GREEN_ATTR;
constexpr BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR;
constexpr BYTE DARK_BLUE = BLUE_ATTR;
constexpr BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR;
constexpr BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR;
constexpr BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR;
constexpr BYTE BRIGHT_BLACK = BRIGHT_ATTR;
constexpr BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR;
constexpr BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR;
constexpr BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR;
constexpr BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR;
constexpr BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR;
constexpr BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR;
constexpr BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR;
// clang-format on
// Routine Description:
// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG)
// These options are followed by either a 2 (RGB) or 5 (xterm index)
@ -72,7 +49,7 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const VTParameters options,
const size_t tableIndex = options.at(1).value_or(0);
if (tableIndex <= 255)
{
const auto adjustedIndex = gsl::narrow_cast<BYTE>(::Xterm256ToWindowsIndex(tableIndex));
const auto adjustedIndex = gsl::narrow_cast<BYTE>(tableIndex);
if (isForeground)
{
attr.SetIndexedForeground256(adjustedIndex);
@ -178,100 +155,100 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options)
attr.SetOverlined(false);
break;
case ForegroundBlack:
attr.SetIndexedForeground(DARK_BLACK);
attr.SetIndexedForeground(TextColor::DARK_BLACK);
break;
case ForegroundBlue:
attr.SetIndexedForeground(DARK_BLUE);
attr.SetIndexedForeground(TextColor::DARK_BLUE);
break;
case ForegroundGreen:
attr.SetIndexedForeground(DARK_GREEN);
attr.SetIndexedForeground(TextColor::DARK_GREEN);
break;
case ForegroundCyan:
attr.SetIndexedForeground(DARK_CYAN);
attr.SetIndexedForeground(TextColor::DARK_CYAN);
break;
case ForegroundRed:
attr.SetIndexedForeground(DARK_RED);
attr.SetIndexedForeground(TextColor::DARK_RED);
break;
case ForegroundMagenta:
attr.SetIndexedForeground(DARK_MAGENTA);
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
break;
case ForegroundYellow:
attr.SetIndexedForeground(DARK_YELLOW);
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
break;
case ForegroundWhite:
attr.SetIndexedForeground(DARK_WHITE);
attr.SetIndexedForeground(TextColor::DARK_WHITE);
break;
case BackgroundBlack:
attr.SetIndexedBackground(DARK_BLACK);
attr.SetIndexedBackground(TextColor::DARK_BLACK);
break;
case BackgroundBlue:
attr.SetIndexedBackground(DARK_BLUE);
attr.SetIndexedBackground(TextColor::DARK_BLUE);
break;
case BackgroundGreen:
attr.SetIndexedBackground(DARK_GREEN);
attr.SetIndexedBackground(TextColor::DARK_GREEN);
break;
case BackgroundCyan:
attr.SetIndexedBackground(DARK_CYAN);
attr.SetIndexedBackground(TextColor::DARK_CYAN);
break;
case BackgroundRed:
attr.SetIndexedBackground(DARK_RED);
attr.SetIndexedBackground(TextColor::DARK_RED);
break;
case BackgroundMagenta:
attr.SetIndexedBackground(DARK_MAGENTA);
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
break;
case BackgroundYellow:
attr.SetIndexedBackground(DARK_YELLOW);
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
break;
case BackgroundWhite:
attr.SetIndexedBackground(DARK_WHITE);
attr.SetIndexedBackground(TextColor::DARK_WHITE);
break;
case BrightForegroundBlack:
attr.SetIndexedForeground(BRIGHT_BLACK);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
break;
case BrightForegroundBlue:
attr.SetIndexedForeground(BRIGHT_BLUE);
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
break;
case BrightForegroundGreen:
attr.SetIndexedForeground(BRIGHT_GREEN);
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
break;
case BrightForegroundCyan:
attr.SetIndexedForeground(BRIGHT_CYAN);
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
break;
case BrightForegroundRed:
attr.SetIndexedForeground(BRIGHT_RED);
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
break;
case BrightForegroundMagenta:
attr.SetIndexedForeground(BRIGHT_MAGENTA);
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
break;
case BrightForegroundYellow:
attr.SetIndexedForeground(BRIGHT_YELLOW);
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
break;
case BrightForegroundWhite:
attr.SetIndexedForeground(BRIGHT_WHITE);
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
break;
case BrightBackgroundBlack:
attr.SetIndexedBackground(BRIGHT_BLACK);
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
break;
case BrightBackgroundBlue:
attr.SetIndexedBackground(BRIGHT_BLUE);
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
break;
case BrightBackgroundGreen:
attr.SetIndexedBackground(BRIGHT_GREEN);
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
break;
case BrightBackgroundCyan:
attr.SetIndexedBackground(BRIGHT_CYAN);
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
break;
case BrightBackgroundRed:
attr.SetIndexedBackground(BRIGHT_RED);
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
break;
case BrightBackgroundMagenta:
attr.SetIndexedBackground(BRIGHT_MAGENTA);
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
break;
case BrightBackgroundYellow:
attr.SetIndexedBackground(BRIGHT_YELLOW);
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
break;
case BrightBackgroundWhite:
attr.SetIndexedBackground(BRIGHT_WHITE);
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
break;
case ForegroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);

View File

@ -1307,49 +1307,49 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Black'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(0);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLACK);
break;
case DispatchTypes::GraphicsOptions::ForegroundBlue:
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
break;
case DispatchTypes::GraphicsOptions::ForegroundGreen:
Log::Comment(L"Testing graphics 'Foreground Color Green'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
break;
case DispatchTypes::GraphicsOptions::ForegroundCyan:
Log::Comment(L"Testing graphics 'Foreground Color Cyan'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN);
break;
case DispatchTypes::GraphicsOptions::ForegroundRed:
Log::Comment(L"Testing graphics 'Foreground Color Red'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
break;
case DispatchTypes::GraphicsOptions::ForegroundMagenta:
Log::Comment(L"Testing graphics 'Foreground Color Magenta'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_MAGENTA);
break;
case DispatchTypes::GraphicsOptions::ForegroundYellow:
Log::Comment(L"Testing graphics 'Foreground Color Yellow'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_YELLOW);
break;
case DispatchTypes::GraphicsOptions::ForegroundWhite:
Log::Comment(L"Testing graphics 'Foreground Color White'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_WHITE);
break;
case DispatchTypes::GraphicsOptions::ForegroundDefault:
Log::Comment(L"Testing graphics 'Foreground Color Default'");
@ -1362,49 +1362,49 @@ public:
Log::Comment(L"Testing graphics 'Background Color Black'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(0);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLACK);
break;
case DispatchTypes::GraphicsOptions::BackgroundBlue:
Log::Comment(L"Testing graphics 'Background Color Blue'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
break;
case DispatchTypes::GraphicsOptions::BackgroundGreen:
Log::Comment(L"Testing graphics 'Background Color Green'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
break;
case DispatchTypes::GraphicsOptions::BackgroundCyan:
Log::Comment(L"Testing graphics 'Background Color Cyan'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_CYAN);
break;
case DispatchTypes::GraphicsOptions::BackgroundRed:
Log::Comment(L"Testing graphics 'Background Color Red'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_RED >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_RED);
break;
case DispatchTypes::GraphicsOptions::BackgroundMagenta:
Log::Comment(L"Testing graphics 'Background Color Magenta'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_MAGENTA);
break;
case DispatchTypes::GraphicsOptions::BackgroundYellow:
Log::Comment(L"Testing graphics 'Background Color Yellow'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_YELLOW);
break;
case DispatchTypes::GraphicsOptions::BackgroundWhite:
Log::Comment(L"Testing graphics 'Background Color White'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_INTENSITY };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_WHITE);
break;
case DispatchTypes::GraphicsOptions::BackgroundDefault:
Log::Comment(L"Testing graphics 'Background Color Default'");
@ -1417,97 +1417,97 @@ public:
Log::Comment(L"Testing graphics 'Bright Foreground Color Black'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLACK);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundBlue:
Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundGreen:
Log::Comment(L"Testing graphics 'Bright Foreground Color Green'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_GREEN);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundCyan:
Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_CYAN);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundRed:
Log::Comment(L"Testing graphics 'Bright Foreground Color Red'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_RED);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundMagenta:
Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundYellow:
Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'");
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
break;
case DispatchTypes::GraphicsOptions::BrightForegroundWhite:
Log::Comment(L"Testing graphics 'Bright Foreground Color White'");
_testGetSet->_attribute = TextAttribute{ 0 };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_WHITE);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundBlack:
Log::Comment(L"Testing graphics 'Bright Background Color Black'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_INTENSITY >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLACK);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundBlue:
Log::Comment(L"Testing graphics 'Bright Background Color Blue'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLUE);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundGreen:
Log::Comment(L"Testing graphics 'Bright Background Color Green'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_GREEN);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundCyan:
Log::Comment(L"Testing graphics 'Bright Background Color Cyan'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_CYAN);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundRed:
Log::Comment(L"Testing graphics 'Bright Background Color Red'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_RED);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta:
Log::Comment(L"Testing graphics 'Bright Background Color Magenta'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundYellow:
Log::Comment(L"Testing graphics 'Bright Background Color Yellow'");
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
break;
case DispatchTypes::GraphicsOptions::BrightBackgroundWhite:
Log::Comment(L"Testing graphics 'Bright Background Color White'");
_testGetSet->_attribute = TextAttribute{ 0 };
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_WHITE);
break;
default:
VERIFY_FAIL(L"Test not implemented yet!");
@ -1545,7 +1545,7 @@ public:
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundCyan;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(3);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
@ -1561,7 +1561,7 @@ public:
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
@ -1572,14 +1572,14 @@ public:
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
// First pop:
cOptions = 0;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
@ -1593,22 +1593,22 @@ public:
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::BoldBright;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetBold(true);
_testGetSet->_expectedAttribute.SetDefaultBackground();
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundBlue;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
_testGetSet->_expectedAttribute.SetBold(true);
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
@ -1624,8 +1624,8 @@ public:
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundGreen;
rgOptions[1] = DispatchTypes::GraphicsOptions::DoublyUnderlined;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetBold(true);
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
@ -1633,24 +1633,24 @@ public:
cOptions = 1;
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetBold(true);
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
rgOptions[0] = DispatchTypes::GraphicsOptions::NotBoldOrFaint;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
// And then restore...
cOptions = 0;
_testGetSet->_expectedAttribute = {};
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
_testGetSet->_expectedAttribute.SetBold(true);
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
}
@ -1672,7 +1672,7 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Enabling brightness");
@ -1683,7 +1683,7 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_TRUE(WI_IsFlagSet(_testGetSet->_attribute.GetLegacyAttributes(), FOREGROUND_GREEN));
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
@ -1698,13 +1698,13 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
Log::Comment(L"Testing graphics 'Foreground Color Blue', brightness of 9x series doesn't persist");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
@ -1717,7 +1717,7 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
@ -1729,19 +1729,19 @@ public:
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
Log::Comment(L"Testing graphics 'Foreground Color Blue, with brightness', brightness of 9x series doesn't affect brightness");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
}
@ -1971,16 +1971,16 @@ public:
Log::Comment(L"Requesting SGR attributes (standard colors).");
_testGetSet->PrepData();
_testGetSet->_attribute = {};
_testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(3));
_testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(6));
_testGetSet->_attribute.SetIndexedForeground(TextColor::DARK_YELLOW);
_testGetSet->_attribute.SetIndexedBackground(TextColor::DARK_CYAN);
requestSetting(L"m");
_testGetSet->ValidateInputEvent(L"\033P1$r0;33;46m\033\\");
Log::Comment(L"Requesting SGR attributes (AIX colors).");
_testGetSet->PrepData();
_testGetSet->_attribute = {};
_testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(14));
_testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(11));
_testGetSet->_attribute.SetIndexedForeground(TextColor::BRIGHT_CYAN);
_testGetSet->_attribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
requestSetting(L"m");
_testGetSet->ValidateInputEvent(L"\033P1$r0;96;103m\033\\");
@ -2297,14 +2297,14 @@ public:
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green
_testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(2));
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
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.SetIndexedBackground256((BYTE)::XtermToWindowsIndex(9));
_testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::BRIGHT_RED);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
Log::Comment(L"Test 3: Change Foreground to RGB color");
@ -2328,7 +2328,7 @@ public:
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
_testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(9));
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::BRIGHT_RED);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
}
@ -2346,14 +2346,14 @@ public:
Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter");
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
_testGetSet->_expectedAttribute.SetIndexedForeground256(0);
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 2 }));
Log::Comment(L"Test 2: Change Indexed Background with default index parameter");
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
rgOptions[2] = {};
_testGetSet->_expectedAttribute.SetIndexedBackground256(0);
_testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 3 }));
Log::Comment(L"Test 3: Change RGB Foreground with all RGB parameters missing");

View File

@ -8,7 +8,7 @@
using namespace Microsoft::Console;
using namespace std::string_view_literals;
static constexpr std::array<til::color, 16> campbellColorTable{
static constexpr std::array<til::color, 256> standard256ColorTable{
til::color{ 0x0C, 0x0C, 0x0C },
til::color{ 0xC5, 0x0F, 0x1F },
til::color{ 0x13, 0xA1, 0x0E },
@ -25,25 +25,6 @@ static constexpr std::array<til::color, 16> campbellColorTable{
til::color{ 0xB4, 0x00, 0x9E },
til::color{ 0x61, 0xD6, 0xD6 },
til::color{ 0xF2, 0xF2, 0xF2 },
};
static constexpr std::array<til::color, 256> standardXterm256ColorTable{
til::color{ 0x00, 0x00, 0x00 },
til::color{ 0x80, 0x00, 0x00 },
til::color{ 0x00, 0x80, 0x00 },
til::color{ 0x80, 0x80, 0x00 },
til::color{ 0x00, 0x00, 0x80 },
til::color{ 0x80, 0x00, 0x80 },
til::color{ 0x00, 0x80, 0x80 },
til::color{ 0xC0, 0xC0, 0xC0 },
til::color{ 0x80, 0x80, 0x80 },
til::color{ 0xFF, 0x00, 0x00 },
til::color{ 0x00, 0xFF, 0x00 },
til::color{ 0xFF, 0xFF, 0x00 },
til::color{ 0x00, 0x00, 0xFF },
til::color{ 0xFF, 0x00, 0xFF },
til::color{ 0x00, 0xFF, 0xFF },
til::color{ 0xFF, 0xFF, 0xFF },
til::color{ 0x00, 0x00, 0x00 },
til::color{ 0x00, 0x00, 0x5F },
til::color{ 0x00, 0x00, 0x87 },
@ -454,73 +435,21 @@ static constexpr til::presorted_static_map xorgAppColorTable{
std::pair{ "yellowgreen"sv, til::color{ 154, 205, 50 } }
};
// Function Description:
// - Fill the first 16 entries of a given color table with the Campbell color
// scheme, in the ANSI/VT RGB order.
// Arguments:
// - table: a color table with at least 16 entries
// Return Value:
// - <none>, throws if the table has less that 16 entries
void Utils::InitializeCampbellColorTable(const gsl::span<COLORREF> table)
{
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
std::copy(campbellColorTable.begin(), campbellColorTable.end(), table.begin());
}
void Utils::InitializeCampbellColorTable(const gsl::span<til::color> table)
{
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
std::copy(campbellColorTable.begin(), campbellColorTable.end(), table.begin());
}
gsl::span<const til::color> Utils::CampbellColorTable()
{
return gsl::make_span(campbellColorTable);
return gsl::make_span(standard256ColorTable).first(16);
}
// Function Description:
// - Fill the first 16 entries of a given color table with the Campbell color
// scheme, in the Windows BGR order.
// - Fill up to 256 entries of a given color table with the default values
// Arguments:
// - table: a color table with at least 16 entries
// - table: a color table to be filled
// Return Value:
// - <none>, throws if the table has less that 16 entries
void Utils::InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table)
// - <none>
void Utils::InitializeColorTable(const gsl::span<COLORREF> table)
{
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
InitializeCampbellColorTable(table);
SwapANSIColorOrderForConhost(table);
}
// Function Description:
// - modifies in-place the given color table from ANSI (RGB) order to Console order (BRG).
// Arguments:
// - table: a color table with at least 16 entries
// Return Value:
// - <none>, throws if the table has less that 16 entries
void Utils::SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table)
{
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
std::swap(til::at(table, 1), til::at(table, 4));
std::swap(til::at(table, 3), til::at(table, 6));
std::swap(til::at(table, 9), til::at(table, 12));
std::swap(til::at(table, 11), til::at(table, 14));
}
// Function Description:
// - Fill the first 255 entries of a given color table with the default values
// of a full 256-color table
// Arguments:
// - table: a color table with at least 256 entries
// Return Value:
// - <none>, throws if the table has less that 256 entries
void Utils::Initialize256ColorTable(const gsl::span<COLORREF> table)
{
THROW_HR_IF(E_INVALIDARG, table.size() < 256);
std::copy(standardXterm256ColorTable.begin(), standardXterm256ColorTable.end(), table.begin());
const auto tableSize = std::min(table.size(), standard256ColorTable.size());
std::copy_n(standard256ColorTable.begin(), tableSize, table.begin());
}
#pragma warning(push)

View File

@ -12,11 +12,7 @@ Abstract:
namespace Microsoft::Console::Utils
{
void InitializeCampbellColorTable(const gsl::span<COLORREF> table);
void InitializeCampbellColorTable(const gsl::span<til::color> table);
void InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table);
void SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table);
void Initialize256ColorTable(const gsl::span<COLORREF> table);
void InitializeColorTable(const gsl::span<COLORREF> table);
gsl::span<const til::color> CampbellColorTable();
std::optional<til::color> ColorFromXOrgAppColorName(const std::wstring_view wstr) noexcept;

View File

@ -20,7 +20,6 @@ class UtilsTests
TEST_CLASS(UtilsTests);
TEST_METHOD(TestClampToShortMax);
TEST_METHOD(TestSwapColorPalette);
TEST_METHOD(TestGuidToString);
TEST_METHOD(TestSplitString);
TEST_METHOD(TestFilterStringForPaste);
@ -55,35 +54,6 @@ void UtilsTests::TestClampToShortMax()
auto withinRangeActual = ClampToShortMax(withinRangeExpected, min);
VERIFY_ARE_EQUAL(withinRangeExpected, withinRangeActual);
}
void UtilsTests::TestSwapColorPalette()
{
std::array<COLORREF, COLOR_TABLE_SIZE> terminalTable;
std::array<COLORREF, COLOR_TABLE_SIZE> consoleTable;
gsl::span<COLORREF> terminalTableView = { &terminalTable[0], terminalTable.size() };
gsl::span<COLORREF> consoleTableView = { &consoleTable[0], consoleTable.size() };
// First set up the colors
InitializeCampbellColorTable(terminalTableView);
InitializeCampbellColorTableForConhost(consoleTableView);
VERIFY_ARE_EQUAL(terminalTable[0], consoleTable[0]);
VERIFY_ARE_EQUAL(terminalTable[1], consoleTable[4]);
VERIFY_ARE_EQUAL(terminalTable[2], consoleTable[2]);
VERIFY_ARE_EQUAL(terminalTable[3], consoleTable[6]);
VERIFY_ARE_EQUAL(terminalTable[4], consoleTable[1]);
VERIFY_ARE_EQUAL(terminalTable[5], consoleTable[5]);
VERIFY_ARE_EQUAL(terminalTable[6], consoleTable[3]);
VERIFY_ARE_EQUAL(terminalTable[7], consoleTable[7]);
VERIFY_ARE_EQUAL(terminalTable[8], consoleTable[8]);
VERIFY_ARE_EQUAL(terminalTable[9], consoleTable[12]);
VERIFY_ARE_EQUAL(terminalTable[10], consoleTable[10]);
VERIFY_ARE_EQUAL(terminalTable[11], consoleTable[14]);
VERIFY_ARE_EQUAL(terminalTable[12], consoleTable[9]);
VERIFY_ARE_EQUAL(terminalTable[13], consoleTable[13]);
VERIFY_ARE_EQUAL(terminalTable[14], consoleTable[11]);
VERIFY_ARE_EQUAL(terminalTable[15], consoleTable[15]);
}
void UtilsTests::TestGuidToString()
{