Merge branch 'dev/migrie/f/non-terminal-content-elevation-warning' into dev/migrie/f/632-on-warning-dialog
This commit is contained in:
commit
370a7aa793
2
.github/actions/spelling/allow/apis.txt
vendored
2
.github/actions/spelling/allow/apis.txt
vendored
|
@ -11,6 +11,7 @@ BUILDBRANCH
|
||||||
BUILDMSG
|
BUILDMSG
|
||||||
BUILDNUMBER
|
BUILDNUMBER
|
||||||
BYPOSITION
|
BYPOSITION
|
||||||
|
BYCOMMAND
|
||||||
charconv
|
charconv
|
||||||
CLASSNOTAVAILABLE
|
CLASSNOTAVAILABLE
|
||||||
cmdletbinding
|
cmdletbinding
|
||||||
|
@ -88,6 +89,7 @@ LSHIFT
|
||||||
MENUCOMMAND
|
MENUCOMMAND
|
||||||
MENUDATA
|
MENUDATA
|
||||||
MENUINFO
|
MENUINFO
|
||||||
|
MENUITEMINFOW
|
||||||
memicmp
|
memicmp
|
||||||
mptt
|
mptt
|
||||||
mov
|
mov
|
||||||
|
|
|
@ -214,7 +214,7 @@ resources useful and interesting:
|
||||||
* Windows Terminal Launch: [Build 2019
|
* Windows Terminal Launch: [Build 2019
|
||||||
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
||||||
* Run As Radio: [Show 645 - Windows Terminal with Richard
|
* Run As Radio: [Show 645 - Windows Terminal with Richard
|
||||||
Turner](http://www.runasradio.com/Shows/Show/645)
|
Turner](https://www.runasradio.com/Shows/Show/645)
|
||||||
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
|
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
|
||||||
on the Windows
|
on the Windows
|
||||||
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
||||||
|
|
|
@ -1478,6 +1478,11 @@
|
||||||
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
|
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"trimPaste": {
|
||||||
|
"default": true,
|
||||||
|
"description": "When enabled, the Terminal will automatically trim trailing whitespace characters when pasting text",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"experimental.detectURLs": {
|
"experimental.detectURLs": {
|
||||||
"default": true,
|
"default": true,
|
||||||
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
||||||
|
|
|
@ -268,7 +268,7 @@ Today, if the deserialization of `CascadiaSettings` encounters any errors, an ex
|
||||||
To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record
|
To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record
|
||||||
any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened.
|
any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened.
|
||||||
The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly
|
The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly
|
||||||
understand whether an error ocurred and how to present that to the user.
|
understand whether an error occurred and how to present that to the user.
|
||||||
|
|
||||||
|
|
||||||
#### TerminalApp: Loading and Reloading Changes
|
#### TerminalApp: Loading and Reloading Changes
|
||||||
|
|
|
@ -12,8 +12,30 @@ static_assert(alignof(TextAttribute) == 2);
|
||||||
// Ensure that we can memcpy() and memmove() the struct for performance.
|
// Ensure that we can memcpy() and memmove() the struct for performance.
|
||||||
static_assert(std::is_trivially_copyable_v<TextAttribute>);
|
static_assert(std::is_trivially_copyable_v<TextAttribute>);
|
||||||
|
|
||||||
BYTE TextAttribute::s_legacyDefaultForeground = 7;
|
namespace
|
||||||
BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
{
|
||||||
|
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:
|
// Routine Description:
|
||||||
// - Sets the legacy attributes which map to and from the default colors.
|
// - Sets the legacy attributes which map to and from the default colors.
|
||||||
|
@ -23,8 +45,22 @@ BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
||||||
// - None
|
// - None
|
||||||
void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept
|
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_legacyDefaultForeground = defaultAttributes & FG_ATTRS;
|
||||||
s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4;
|
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:
|
// Routine Description:
|
||||||
|
@ -55,13 +91,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
|
||||||
const auto bg{ attribute.GetBackground() };
|
const auto bg{ attribute.GetBackground() };
|
||||||
auto copy{ attribute };
|
auto copy{ attribute };
|
||||||
if (fg.IsIndex16() &&
|
if (fg.IsIndex16() &&
|
||||||
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
|
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
|
||||||
fg.GetIndex() == (s_legacyDefaultForeground & ~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.
|
// 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();
|
copy.SetDefaultForeground();
|
||||||
}
|
}
|
||||||
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
|
if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground)
|
||||||
{
|
{
|
||||||
copy.SetDefaultBackground();
|
copy.SetDefaultBackground();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ public:
|
||||||
|
|
||||||
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
|
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
|
||||||
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
||||||
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
|
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
|
||||||
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
|
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
|
||||||
_extendedAttrs{ ExtendedAttributes::Normal },
|
_extendedAttrs{ ExtendedAttributes::Normal },
|
||||||
_hyperlinkId{ 0 }
|
_hyperlinkId{ 0 }
|
||||||
{
|
{
|
||||||
|
@ -167,13 +167,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex)
|
static std::array<TextColor, 16> s_legacyForegroundColorMap;
|
||||||
{
|
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
|
||||||
return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true };
|
|
||||||
}
|
|
||||||
|
|
||||||
static BYTE s_legacyDefaultForeground;
|
|
||||||
static BYTE s_legacyDefaultBackground;
|
|
||||||
|
|
||||||
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
|
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
|
||||||
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2
|
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2
|
||||||
|
|
|
@ -32,7 +32,7 @@ constexpr std::array<BYTE, 256> CompressedRgbToIndex16 = {
|
||||||
// A table mapping indexed colors from the 256-color palette,
|
// A table mapping indexed colors from the 256-color palette,
|
||||||
// down to one of the 16 colors in the legacy palette.
|
// down to one of the 16 colors in the legacy palette.
|
||||||
constexpr std::array<BYTE, 256> Index256ToIndex16 = {
|
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,
|
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,
|
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,
|
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;
|
return defaultIndex;
|
||||||
}
|
}
|
||||||
else if (IsIndex16())
|
else if (IsIndex16() || IsIndex256())
|
||||||
{
|
|
||||||
return GetIndex();
|
|
||||||
}
|
|
||||||
else if (IsIndex256())
|
|
||||||
{
|
{
|
||||||
return til::at(Index256ToIndex16, GetIndex());
|
return til::at(Index256ToIndex16, GetIndex());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,23 @@ enum class ColorType : BYTE
|
||||||
struct TextColor
|
struct TextColor
|
||||||
{
|
{
|
||||||
public:
|
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 :
|
constexpr TextColor() noexcept :
|
||||||
_meta{ ColorType::IsDefault },
|
_meta{ ColorType::IsDefault },
|
||||||
_red{ 0 },
|
_red{ 0 },
|
||||||
|
@ -96,6 +113,16 @@ public:
|
||||||
|
|
||||||
COLORREF GetRGB() const noexcept;
|
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:
|
private:
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,7 +237,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
||||||
Log::Comment(L"Foreground legacy default index should map to default text color.");
|
Log::Comment(L"Foreground legacy default index should map to default text color.");
|
||||||
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
|
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
|
||||||
textAttribute.SetDefaultForeground();
|
textAttribute.SetDefaultForeground();
|
||||||
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
|
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
|
||||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
||||||
|
|
||||||
Log::Comment(L"Default foreground text color should map back to legacy default index.");
|
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.");
|
Log::Comment(L"Background legacy default index should map to default text color.");
|
||||||
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
|
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
|
||||||
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
|
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
|
||||||
textAttribute.SetDefaultBackground();
|
textAttribute.SetDefaultBackground();
|
||||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
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, true));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
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());
|
VERIFY_IS_TRUE(attr.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
|
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");
|
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));
|
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());
|
VERIFY_IS_TRUE(attr.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"background should be unaffected by 'bold is bright'");
|
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");
|
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
||||||
attr.SetBold(true);
|
attr.SetBold(true);
|
||||||
attr.SetIndexedForeground(8);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||||
VERIFY_IS_TRUE(attr.IsBold());
|
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, true));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
|
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
|
||||||
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
|
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
|
||||||
Utils::InitializeCampbellColorTable(campbellSpan);
|
Utils::InitializeColorTable(campbellSpan);
|
||||||
Utils::SetColorTableAlpha(campbellSpan, 0);
|
Utils::SetColorTableAlpha(campbellSpan, 0);
|
||||||
|
|
||||||
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
|
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
|
||||||
|
|
|
@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||||
result = RunOnUIThread([&page]() {
|
result = RunOnUIThread([&page]() {
|
||||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||||
|
@ -526,7 +526,7 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||||
result = RunOnUIThread([&page]() {
|
result = RunOnUIThread([&page]() {
|
||||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||||
|
@ -844,7 +844,7 @@ namespace TerminalAppLocalTests
|
||||||
// | 1 | 2 |
|
// | 1 | 2 |
|
||||||
// | | |
|
// | | |
|
||||||
// -------------------
|
// -------------------
|
||||||
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
|
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||||
secondId = tab->_activePane->Id().value();
|
secondId = tab->_activePane->Id().value();
|
||||||
});
|
});
|
||||||
Sleep(250);
|
Sleep(250);
|
||||||
|
@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
|
||||||
// | 3 | |
|
// | 3 | |
|
||||||
// | | |
|
// | | |
|
||||||
// -------------------
|
// -------------------
|
||||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||||
// Split again to make the 3rd tab
|
// Split again to make the 3rd tab
|
||||||
thirdId = tab->_activePane->Id().value();
|
thirdId = tab->_activePane->Id().value();
|
||||||
|
@ -882,7 +882,7 @@ namespace TerminalAppLocalTests
|
||||||
// | 3 | 4 |
|
// | 3 | 4 |
|
||||||
// | | |
|
// | | |
|
||||||
// -------------------
|
// -------------------
|
||||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||||
fourthId = tab->_activePane->Id().value();
|
fourthId = tab->_activePane->Id().value();
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,23 +45,27 @@
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
FontSize="20"
|
FontSize="20"
|
||||||
FontWeight="Normal"
|
FontWeight="Normal"
|
||||||
|
IsTextSelectionEnabled="True"
|
||||||
TextWrapping="WrapWholeWords" />
|
TextWrapping="WrapWholeWords" />
|
||||||
|
|
||||||
<TextBlock x:Name="PrefixTextBlock"
|
<TextBlock x:Name="PrefixTextBlock"
|
||||||
x:Uid="ApproveCommandlineWarningPrefixTextBlock"
|
x:Uid="ApproveCommandlineWarningPrefixTextBlock"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
IsTextSelectionEnabled="True"
|
||||||
TextWrapping="WrapWholeWords" />
|
TextWrapping="WrapWholeWords" />
|
||||||
|
|
||||||
<TextBlock x:Name="CommandlineText"
|
<TextBlock x:Name="CommandlineText"
|
||||||
Margin="0,16,0,16"
|
Margin="0,16,0,16"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
FontFamily="Cascadia Mono"
|
FontFamily="Cascadia Mono"
|
||||||
|
IsTextSelectionEnabled="True"
|
||||||
Text="{x:Bind Commandline, Mode=OneWay}"
|
Text="{x:Bind Commandline, Mode=OneWay}"
|
||||||
TextWrapping="WrapWholeWords" />
|
TextWrapping="WrapWholeWords" />
|
||||||
|
|
||||||
<TextBlock x:Name="SuffixTextBlock"
|
<TextBlock x:Name="SuffixTextBlock"
|
||||||
x:Uid="ApproveCommandlineWarningSuffixTextBlock"
|
x:Uid="ApproveCommandlineWarningSuffixTextBlock"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
IsTextSelectionEnabled="True"
|
||||||
TextWrapping="WrapWholeWords" />
|
TextWrapping="WrapWholeWords" />
|
||||||
<Grid Margin="0,8,0,8"
|
<Grid Margin="0,8,0,8"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
|
|
|
@ -174,10 +174,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
|
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
|
||||||
{
|
{
|
||||||
_SplitPane(realArgs.SplitDirection(),
|
_SplitPane(realArgs.SplitDirection(),
|
||||||
realArgs.SplitMode(),
|
|
||||||
// This is safe, we're already filtering so the value is (0, 1)
|
// This is safe, we're already filtering so the value is (0, 1)
|
||||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||||
realArgs.TerminalArgs());
|
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||||
args.Handled(true);
|
args.Handled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,18 +133,6 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
|
||||||
return textRun;
|
return textRun;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Returns whether the user is either a member of the Administrators group or
|
|
||||||
// is currently elevated.
|
|
||||||
// - This will return **FALSE** if the user has UAC disabled entirely, because
|
|
||||||
// there's no separation of power between the user and an admin in that case.
|
|
||||||
// Return Value:
|
|
||||||
// - true if the user is an administrator
|
|
||||||
static bool _isUserAdmin() noexcept
|
|
||||||
{
|
|
||||||
return Microsoft::Console::Utils::IsElevated();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace winrt::TerminalApp::implementation
|
namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
// Function Description:
|
// Function Description:
|
||||||
|
@ -196,7 +184,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// The TerminalPage has to be constructed during our construction, to
|
// The TerminalPage has to be constructed during our construction, to
|
||||||
// make sure that there's a terminal page for callers of
|
// make sure that there's a terminal page for callers of
|
||||||
// SetTitleBarContent
|
// SetTitleBarContent
|
||||||
_isElevated = _isUserAdmin();
|
_isElevated = ::Microsoft::Console::Utils::IsElevated();
|
||||||
_root = winrt::make_self<TerminalPage>();
|
_root = winrt::make_self<TerminalPage>();
|
||||||
|
|
||||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||||
|
@ -316,6 +304,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
_RefreshThemeRoutine();
|
_RefreshThemeRoutine();
|
||||||
_ApplyStartupTaskStateChange();
|
_ApplyStartupTaskStateChange();
|
||||||
|
|
||||||
|
auto args = winrt::make_self<SystemMenuChangeArgs>(RS_(L"SettingsMenuItem"), SystemMenuChangeAction::Add, SystemMenuItemHandler(this, &AppLogic::_OpenSettingsUI));
|
||||||
|
_SystemMenuChangeRequestedHandlers(*this, *args);
|
||||||
|
|
||||||
TraceLoggingWrite(
|
TraceLoggingWrite(
|
||||||
g_hTerminalAppProvider,
|
g_hTerminalAppProvider,
|
||||||
"AppCreated",
|
"AppCreated",
|
||||||
|
@ -898,11 +889,20 @@ namespace winrt::TerminalApp::implementation
|
||||||
// actual file you wrote. So listen for that too.
|
// actual file you wrote. So listen for that too.
|
||||||
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
||||||
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||||
// DO NOT create a static reference to
|
// DO NOT create a static reference to ApplicationState::SharedInstance here.
|
||||||
// ApplicationState::SharedInstance here. See
|
//
|
||||||
// https://github.com/microsoft/terminal/pull/11222/files/9ff2775122a496fb8b1bcc7a0b83a64ce5b26c5f#r719627541
|
// ApplicationState::SharedInstance already caches its own
|
||||||
// for why. ApplicationState::SharedInstance already caches it's
|
// static ref. If _we_ keep a static ref to the member in
|
||||||
// own static ref.
|
// AppState, then our reference will keep ApplicationState alive
|
||||||
|
// after the `ActionToStringMap` gets cleaned up. Then, when we
|
||||||
|
// try to persist the actions in the window state, we won't be
|
||||||
|
// able to. We'll try to look up the action and the map just
|
||||||
|
// won't exist. We'll explode, even though the Terminal is
|
||||||
|
// tearing down anyways. So we'll just die, but still inboke
|
||||||
|
// WinDBG's post-mortem debugger, who won't be able to attach to
|
||||||
|
// the process that's already exiting.
|
||||||
|
//
|
||||||
|
// So DON'T ~give a mouse a cookie~ take a static ref here.
|
||||||
|
|
||||||
const winrt::hstring modifiedBasename{ std::filesystem::path{ fileModified }.filename().c_str() };
|
const winrt::hstring modifiedBasename{ std::filesystem::path{ fileModified }.filename().c_str() };
|
||||||
|
|
||||||
|
@ -1037,6 +1037,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
_SettingsChangedHandlers(*this, nullptr);
|
_SettingsChangedHandlers(*this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppLogic::_OpenSettingsUI()
|
||||||
|
{
|
||||||
|
_root->OpenSettingsUI();
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Returns a pointer to the global shared settings.
|
// - Returns a pointer to the global shared settings.
|
||||||
[[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept
|
[[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept
|
||||||
|
@ -1543,6 +1548,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
return _root->IsQuakeWindow();
|
return _root->IsQuakeWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppLogic::RequestExitFullscreen()
|
||||||
|
{
|
||||||
|
_root->SetFullscreen(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool AppLogic::GetMinimizeToNotificationArea()
|
bool AppLogic::GetMinimizeToNotificationArea()
|
||||||
{
|
{
|
||||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "AppLogic.g.h"
|
#include "AppLogic.g.h"
|
||||||
#include "FindTargetWindowResult.g.h"
|
#include "FindTargetWindowResult.g.h"
|
||||||
|
#include "SystemMenuChangeArgs.g.h"
|
||||||
#include "Jumplist.h"
|
#include "Jumplist.h"
|
||||||
#include "LanguageProfileNotifier.h"
|
#include "LanguageProfileNotifier.h"
|
||||||
#include "TerminalPage.h"
|
#include "TerminalPage.h"
|
||||||
|
@ -35,6 +36,17 @@ namespace winrt::TerminalApp::implementation
|
||||||
FindTargetWindowResult(id, L""){};
|
FindTargetWindowResult(id, L""){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
|
||||||
|
{
|
||||||
|
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||||
|
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
|
||||||
|
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
|
||||||
|
_Name{ name }, _Action{ action }, _Handler{ handler } {};
|
||||||
|
};
|
||||||
|
|
||||||
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
|
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -79,6 +91,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void SetPersistedLayoutIdx(const uint32_t idx);
|
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||||
void SetNumberOfOpenWindows(const uint64_t num);
|
void SetNumberOfOpenWindows(const uint64_t num);
|
||||||
bool IsQuakeWindow() const noexcept;
|
bool IsQuakeWindow() const noexcept;
|
||||||
|
void RequestExitFullscreen();
|
||||||
|
|
||||||
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||||
bool CenterOnLaunch();
|
bool CenterOnLaunch();
|
||||||
|
@ -113,6 +126,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// -------------------------------- WinRT Events ---------------------------------
|
// -------------------------------- WinRT Events ---------------------------------
|
||||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
|
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
|
||||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
|
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _isUwp{ false };
|
bool _isUwp{ false };
|
||||||
|
@ -163,6 +177,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void _RegisterSettingsChange();
|
void _RegisterSettingsChange();
|
||||||
fire_and_forget _DispatchReloadSettings();
|
fire_and_forget _DispatchReloadSettings();
|
||||||
void _ReloadSettings();
|
void _ReloadSettings();
|
||||||
|
void _OpenSettingsUI();
|
||||||
|
|
||||||
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
|
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,20 @@ namespace TerminalApp
|
||||||
String WindowName { get; };
|
String WindowName { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
delegate void SystemMenuItemHandler();
|
||||||
|
|
||||||
|
enum SystemMenuChangeAction
|
||||||
|
{
|
||||||
|
Add = 0,
|
||||||
|
Remove = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface] runtimeclass SystemMenuChangeArgs {
|
||||||
|
String Name { get; };
|
||||||
|
SystemMenuChangeAction Action { get; };
|
||||||
|
SystemMenuItemHandler Handler { get; };
|
||||||
|
};
|
||||||
|
|
||||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
|
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
|
||||||
{
|
{
|
||||||
AppLogic();
|
AppLogic();
|
||||||
|
@ -60,6 +74,7 @@ namespace TerminalApp
|
||||||
void SetPersistedLayoutIdx(UInt32 idx);
|
void SetPersistedLayoutIdx(UInt32 idx);
|
||||||
void SetNumberOfOpenWindows(UInt64 num);
|
void SetNumberOfOpenWindows(UInt64 num);
|
||||||
void RenameFailed();
|
void RenameFailed();
|
||||||
|
void RequestExitFullscreen();
|
||||||
Boolean IsQuakeWindow();
|
Boolean IsQuakeWindow();
|
||||||
|
|
||||||
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||||
|
@ -110,5 +125,6 @@ namespace TerminalApp
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -847,14 +847,17 @@ bool Pane::SwapPanes(std::shared_ptr<Pane> first, std::shared_ptr<Pane> second)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
winrt::Windows::UI::Xaml::Controls::UserControl Pane::ReplaceControl(const winrt::Windows::UI::Xaml::Controls::UserControl& control)
|
Controls::UserControl Pane::ReplaceControl(const Controls::UserControl& control)
|
||||||
{
|
{
|
||||||
if (!_IsLeaf())
|
if (!_IsLeaf())
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove old control's event handlers
|
||||||
const auto& oldControl = _control;
|
const auto& oldControl = _control;
|
||||||
|
_gotFocusRevoker.revoke();
|
||||||
|
_lostFocusRevoker.revoke();
|
||||||
if (const auto& oldTermControl{ _control.try_as<TermControl>() })
|
if (const auto& oldTermControl{ _control.try_as<TermControl>() })
|
||||||
{
|
{
|
||||||
oldTermControl.ConnectionStateChanged(_connectionStateChangedToken);
|
oldTermControl.ConnectionStateChanged(_connectionStateChangedToken);
|
||||||
|
@ -862,7 +865,13 @@ winrt::Windows::UI::Xaml::Controls::UserControl Pane::ReplaceControl(const winrt
|
||||||
}
|
}
|
||||||
|
|
||||||
_control = control;
|
_control = control;
|
||||||
|
|
||||||
_borderFirst.Child(_control);
|
_borderFirst.Child(_control);
|
||||||
|
|
||||||
|
// Register an event with the control to have it inform us when it gains focus.
|
||||||
|
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
||||||
|
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
||||||
|
|
||||||
if (const auto& termControl{ _control.try_as<TermControl>() })
|
if (const auto& termControl{ _control.try_as<TermControl>() })
|
||||||
{
|
{
|
||||||
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
||||||
|
@ -2426,35 +2435,32 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Split the focused pane in our tree of panes, and place the given
|
// - The same as above, except this takes in the pane directly instead of a
|
||||||
// UserControl into the newly created pane. If we're the focused pane, then
|
// profile and control to make a pane with
|
||||||
// we'll create two new children, and place them side-by-side in our Grid.
|
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - splitType: what type of split we want to create.
|
// - splitType: what type of split we want to create.
|
||||||
// - profile: The profile to associate with the newly created pane.
|
// - splitSize: the desired size of the split
|
||||||
// - control: A UserControl to use in the new pane.
|
// - newPane: the new pane
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - The two newly created Panes, with the original pane first
|
// - The two newly created Panes, with the original pane first
|
||||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const Profile& profile,
|
std::shared_ptr<Pane> newPane)
|
||||||
const Controls::UserControl& control)
|
|
||||||
{
|
{
|
||||||
if (!_lastActive)
|
if (!_lastActive)
|
||||||
{
|
{
|
||||||
if (_firstChild && _firstChild->_HasFocusedChild())
|
if (_firstChild && _firstChild->_HasFocusedChild())
|
||||||
{
|
{
|
||||||
return _firstChild->Split(splitType, splitSize, profile, control);
|
return _firstChild->Split(splitType, splitSize, newPane);
|
||||||
}
|
}
|
||||||
else if (_secondChild && _secondChild->_HasFocusedChild())
|
else if (_secondChild && _secondChild->_HasFocusedChild())
|
||||||
{
|
{
|
||||||
return _secondChild->Split(splitType, splitSize, profile, control);
|
return _secondChild->Split(splitType, splitSize, newPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { nullptr, nullptr };
|
return { nullptr, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newPane = std::make_shared<Pane>(profile, control);
|
|
||||||
return _Split(splitType, splitSize, newPane);
|
return _Split(splitType, splitSize, newPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,7 @@ public:
|
||||||
|
|
||||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
std::shared_ptr<Pane> pane);
|
||||||
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
|
|
||||||
bool ToggleSplitOrientation();
|
bool ToggleSplitOrientation();
|
||||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||||
|
|
|
@ -77,8 +77,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
// We can't go in the other direction (elevated->unelevated)
|
// We can't go in the other direction (elevated->unelevated)
|
||||||
// unfortunately. This seems to be due to Centennial quirks. It works
|
// unfortunately. This seems to be due to Centennial quirks. It works
|
||||||
// unpackaged, but not packaged.
|
// unpackaged, but not packaged.
|
||||||
|
//
|
||||||
_CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
|
// This call to _MakePane won't return nullptr, we already checked that
|
||||||
|
// case above with the _maybeElevate call.
|
||||||
|
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
|
||||||
|
|
||||||
const uint32_t tabCount = _tabs.Size();
|
const uint32_t tabCount = _tabs.Size();
|
||||||
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
|
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||||
|
@ -250,81 +252,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - pane: The pane to use as the root.
|
// - pane: The pane to use as the root.
|
||||||
void TerminalPage::_CreateNewTabFromPane(std::shared_ptr<Pane> pane)
|
void TerminalPage::_CreateNewTabFromPane(std::shared_ptr<Pane> pane)
|
||||||
{
|
{
|
||||||
auto newTabImpl = winrt::make_self<TerminalTab>(pane);
|
if (pane)
|
||||||
_InitializeTab(newTabImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Creates a new tab with the given settings. If the tab bar is not being
|
|
||||||
// currently displayed, it will be shown.
|
|
||||||
// Arguments:
|
|
||||||
// - profile: profile settings for this connection
|
|
||||||
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
|
||||||
// - existingConnection: optionally receives a connection from the outside world instead of attempting to create one
|
|
||||||
void TerminalPage::_CreateNewTabWithProfileAndSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult settings, TerminalConnection::ITerminalConnection existingConnection)
|
|
||||||
{
|
|
||||||
// Initialize the new tab
|
|
||||||
// Create a connection based on the values in our settings object if we weren't given one.
|
|
||||||
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings());
|
|
||||||
|
|
||||||
// If we had an `existingConnection`, then this is an inbound handoff from somewhere else.
|
|
||||||
// We need to tell it about our size information so it can match the dimensions of what
|
|
||||||
// we are about to present.
|
|
||||||
if (existingConnection)
|
|
||||||
{
|
{
|
||||||
connection.Resize(settings.DefaultSettings().InitialRows(), settings.DefaultSettings().InitialCols());
|
auto newTabImpl = winrt::make_self<TerminalTab>(pane);
|
||||||
}
|
_InitializeTab(newTabImpl);
|
||||||
|
|
||||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
|
||||||
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
|
||||||
{
|
|
||||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
|
||||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
|
||||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
|
||||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
|
||||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
|
||||||
if (bothAltsPressed)
|
|
||||||
{
|
|
||||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give term control a child of the settings so that any overrides go in the child
|
|
||||||
// This way, when we do a settings reload we just update the parent and the overrides remain
|
|
||||||
auto term = _InitControl(settings, connection);
|
|
||||||
WUX::Controls::UserControl controlToAdd{ term };
|
|
||||||
|
|
||||||
const auto& cmdline{ settings.DefaultSettings().Commandline() };
|
|
||||||
const bool doAdminWarning = _shouldPromptForCommandline(cmdline);
|
|
||||||
if (doAdminWarning)
|
|
||||||
{
|
|
||||||
auto warningControl{ winrt::make_self<implementation::AdminWarningPlaceholder>(term, cmdline) };
|
|
||||||
warningControl->PrimaryButtonClicked({ get_weak(), &TerminalPage::_adminWarningPrimaryClicked });
|
|
||||||
warningControl->CancelButtonClicked({ get_weak(), &TerminalPage::_adminWarningCancelClicked });
|
|
||||||
controlToAdd = *warningControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto newTabImpl = winrt::make_self<TerminalTab>(profile, controlToAdd);
|
|
||||||
_RegisterTerminalEvents(term);
|
|
||||||
_InitializeTab(newTabImpl);
|
|
||||||
|
|
||||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
|
||||||
{
|
|
||||||
auto newControl = _InitControl(settings, debugConnection);
|
|
||||||
_RegisterTerminalEvents(newControl);
|
|
||||||
// Split (auto) with the debug tap.
|
|
||||||
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doAdminWarning)
|
|
||||||
{
|
|
||||||
// We know this is safe - we literally just added the
|
|
||||||
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
|
|
||||||
//
|
|
||||||
// Focus the warning here. The LayoutUpdated within the dialog
|
|
||||||
// itself isn't good enough. That, for some reason, fires _before_
|
|
||||||
// the dialog is in the UI tree, which is useless for us.
|
|
||||||
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,28 +328,14 @@ namespace winrt::TerminalApp::implementation
|
||||||
// In the future, it may be preferable to just duplicate the
|
// In the future, it may be preferable to just duplicate the
|
||||||
// current control's live settings (which will include changes
|
// current control's live settings (which will include changes
|
||||||
// made through VT).
|
// made through VT).
|
||||||
|
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||||
|
|
||||||
if (auto profile = tab.GetFocusedProfile())
|
const auto runtimeTabText{ tab.GetTabText() };
|
||||||
|
if (!runtimeTabText.empty())
|
||||||
{
|
{
|
||||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
if (auto newTab{ _GetFocusedTabImpl() })
|
||||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
|
||||||
const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
|
||||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
|
||||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
|
||||||
if (validWorkingDirectory)
|
|
||||||
{
|
{
|
||||||
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
|
newTab->SetTabText(runtimeTabText);
|
||||||
}
|
|
||||||
|
|
||||||
_CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
|
|
||||||
|
|
||||||
const auto runtimeTabText{ tab.GetTabText() };
|
|
||||||
if (!runtimeTabText.empty())
|
|
||||||
{
|
|
||||||
if (auto newTab{ _GetFocusedTabImpl() })
|
|
||||||
{
|
|
||||||
newTab->SetTabText(runtimeTabText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +351,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_SetFocusedTab(tab);
|
_SetFocusedTab(tab);
|
||||||
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
|
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||||
}
|
}
|
||||||
CATCH_LOG();
|
CATCH_LOG();
|
||||||
}
|
}
|
||||||
|
|
|
@ -674,15 +674,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
co_return ContentDialogResult::None;
|
co_return ContentDialogResult::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult> TerminalPage::_ShowCommandlineApproveWarning()
|
|
||||||
{
|
|
||||||
if (auto presenter{ _dialogPresenter.get() })
|
|
||||||
{
|
|
||||||
co_return co_await presenter.ShowDialog(FindName(L"ApproveCommandlineWarning").try_as<WUX::Controls::ContentDialog>());
|
|
||||||
}
|
|
||||||
co_return ContentDialogResult::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Builds the flyout (dropdown) attached to the new tab button, and
|
// - Builds the flyout (dropdown) attached to the new tab button, and
|
||||||
// attaches it to the button. Populates the flyout with one entry per
|
// attaches it to the button. Populates the flyout with one entry per
|
||||||
|
@ -876,14 +867,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||||
|
|
||||||
if (altPressed && !debugTap)
|
if (shiftPressed && !debugTap)
|
||||||
{
|
|
||||||
this->_SplitPane(SplitDirection::Automatic,
|
|
||||||
SplitType::Manual,
|
|
||||||
0.5f,
|
|
||||||
newTerminalArgs);
|
|
||||||
}
|
|
||||||
else if (shiftPressed && !debugTap)
|
|
||||||
{
|
{
|
||||||
// Manually fill in the evaluated profile.
|
// Manually fill in the evaluated profile.
|
||||||
if (newTerminalArgs.ProfileIndex() != nullptr)
|
if (newTerminalArgs.ProfileIndex() != nullptr)
|
||||||
|
@ -899,7 +883,24 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
|
const auto newPane = _MakePane(newTerminalArgs);
|
||||||
|
// If the newTerminalArgs caused us to open an elevated window
|
||||||
|
// instead of creating a pane, it may have returned nullptr. Just do
|
||||||
|
// nothing then.
|
||||||
|
if (!newPane)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (altPressed && !debugTap)
|
||||||
|
{
|
||||||
|
this->_SplitPane(SplitDirection::Automatic,
|
||||||
|
0.5f,
|
||||||
|
newPane);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_CreateNewTabFromPane(newPane);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1510,9 +1511,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - Returns true if this commandline is precisely an executable in
|
// - Returns true if this commandline is a commandline that we know is safe.
|
||||||
// system32. We can use this to bypass the elevated state check, because
|
// Generally, this is true for any executables in system32. We can use
|
||||||
// we're confident that executables in that path won't have been hijacked.
|
// this to bypass the elevated state check, because we're confident that
|
||||||
|
// executables in that path won't have been hijacked.
|
||||||
// - TECHNICALLY a user can take ownership of a file in system32 and
|
// - TECHNICALLY a user can take ownership of a file in system32 and
|
||||||
// replace it as the system administrator. You could say it's OK though
|
// replace it as the system administrator. You could say it's OK though
|
||||||
// because you'd already have to have had admin rights to mess that
|
// because you'd already have to have had admin rights to mess that
|
||||||
|
@ -1520,6 +1522,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - Will attempt to resolve environment strings.
|
// - Will attempt to resolve environment strings.
|
||||||
// - Will also manually allow commandlines as generated for the default WSL
|
// - Will also manually allow commandlines as generated for the default WSL
|
||||||
// distros.
|
// distros.
|
||||||
|
// - Will also trust %ProgramFiles%\Powershell\...\pwsh.exe paths, for
|
||||||
|
// PowerShell Core.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - commandLine: the command to check.
|
// - commandLine: the command to check.
|
||||||
// Return Value (example):
|
// Return Value (example):
|
||||||
|
@ -1528,7 +1532,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - C:\windows\system32\cmd.exe /k echo sneaky sneak -> returns false
|
// - C:\windows\system32\cmd.exe /k echo sneaky sneak -> returns false
|
||||||
// - %SystemRoot%\System32\cmd.exe -> returns true
|
// - %SystemRoot%\System32\cmd.exe -> returns true
|
||||||
// - %SystemRoot%\System32\wsl.exe -d <distro name> -> returns true
|
// - %SystemRoot%\System32\wsl.exe -d <distro name> -> returns true
|
||||||
static bool _isInSystem32(std::wstring_view commandLine)
|
static bool _isTrustedCommandline(std::wstring_view commandLine)
|
||||||
{
|
{
|
||||||
// use C++11 magic statics to make sure we only do this once.
|
// use C++11 magic statics to make sure we only do this once.
|
||||||
static std::wstring systemDirectory = []() -> std::wstring {
|
static std::wstring systemDirectory = []() -> std::wstring {
|
||||||
|
@ -1607,7 +1611,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// Using the string following "-d "...
|
// Using the string following "-d "...
|
||||||
const auto afterDashD{ arguments.substr(dashD + 3) };
|
const auto afterDashD{ arguments.substr(dashD + 3) };
|
||||||
// Find the next space
|
// Find the next space
|
||||||
const auto afterFirstWord = afterDashD.substr(dashD + 3).find(L" ");
|
const auto afterFirstWord = afterDashD.find(L" ");
|
||||||
// if that space _wasn't_ at the end of the commandline, then
|
// if that space _wasn't_ at the end of the commandline, then
|
||||||
// there were some other args. That means it was `wsl -d distro
|
// there were some other args. That means it was `wsl -d distro
|
||||||
// anything`, and we should ask the user.
|
// anything`, and we should ask the user.
|
||||||
|
@ -1620,6 +1624,33 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (executableFilename == L"pwsh" || executableFilename == L"pwsh.exe")
|
||||||
|
{
|
||||||
|
// is does executablePath start with %ProgramFiles%\\PowerShell?
|
||||||
|
const std::filesystem::path powershellCoreRoot
|
||||||
|
{
|
||||||
|
wil::ExpandEnvironmentStringsW<std::wstring>(
|
||||||
|
#if defined(_M_AMD64) || defined(_M_ARM64) // No point in looking for WOW if we're not somewhere it exists
|
||||||
|
L"%ProgramFiles(x86)%\\PowerShell"
|
||||||
|
#elif defined(_M_ARM64) // same with ARM
|
||||||
|
L"%ProgramFiles(Arm)%\\PowerShell"
|
||||||
|
#else
|
||||||
|
L"%ProgramFiles%\\PowerShell"
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the path to the commandline actually exactly one of the
|
||||||
|
// versions that exists in this directory?
|
||||||
|
for (const auto& versionedDir : std::filesystem::directory_iterator(powershellCoreRoot))
|
||||||
|
{
|
||||||
|
const auto versionedPath = versionedDir.path();
|
||||||
|
if (executablePath.parent_path() == versionedPath)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1637,11 +1668,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
// NOTE: For debugging purposes, changing this to `true || IsElevated()`
|
// NOTE: For debugging purposes, changing this to `true || IsElevated()`
|
||||||
// is a handy way of forcing the elevation logic, even when unelevated.
|
// is a handy way of forcing the elevation logic, even when unelevated.
|
||||||
if (IsElevated())
|
if (true || IsElevated())
|
||||||
{
|
{
|
||||||
// If the cmdline is EXACTLY an executable in
|
// If the cmdline is EXACTLY an executable in
|
||||||
// `C:\WINDOWS\System32`, then ignore this check.
|
// `C:\WINDOWS\System32`, then ignore this check.
|
||||||
if (_isInSystem32(cmdline))
|
if (_isTrustedCommandline(cmdline))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1687,11 +1718,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
// Go ahead and allow them. Swap the control into
|
// Go ahead and allow them. Swap the control into
|
||||||
// the pane, which will initialize and start it.
|
// the pane, which will initialize and start it.
|
||||||
pane->ReplaceControl(otherWarning->Control());
|
tabImpl->ReplaceControl(pane, otherWarning->Control());
|
||||||
// Update the title, because replacing the control like
|
|
||||||
// this is a little weird, and doesn't actually trigger
|
|
||||||
// a TitleChanged by itself.
|
|
||||||
tabImpl->UpdateTitle();
|
|
||||||
}
|
}
|
||||||
// Don't return true here. We want to make sure to check
|
// Don't return true here. We want to make sure to check
|
||||||
// all the panes for the same commandline we just
|
// all the panes for the same commandline we just
|
||||||
|
@ -1790,172 +1817,71 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Split the focused pane either horizontally or vertically, and place the
|
// - Split the focused pane either horizontally or vertically, and place the
|
||||||
// given TermControl into the newly created pane.
|
// given pane accordingly in the tree
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
// - newPane: the pane to add to our tree of panes
|
||||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||||
// new pane should be split from its parent.
|
// new pane should be split from its parent.
|
||||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
// - splitSize: the size of the split
|
||||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
|
||||||
// control which profile is created and with possible other
|
|
||||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
|
||||||
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
|
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
|
||||||
const SplitType splitMode,
|
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const NewTerminalArgs& newTerminalArgs)
|
std::shared_ptr<Pane> newPane)
|
||||||
{
|
{
|
||||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||||
|
_SplitPane(*focusedTab, splitDirection, splitSize, newPane);
|
||||||
// Do nothing if no TerminalTab is focused
|
|
||||||
if (!focusedTab)
|
|
||||||
{
|
|
||||||
// GH#632
|
|
||||||
// If there's no tab, but we're requesting a elevated split,
|
|
||||||
// we still want to toss that over to the elevated window. This is
|
|
||||||
// for something like
|
|
||||||
//
|
|
||||||
// `wtd nt -p "elevated cmd" ; sp -p "elevated cmd"`
|
|
||||||
//
|
|
||||||
// We should just make two elevated tabs for that.
|
|
||||||
|
|
||||||
// Note: If the action was a "duplicate pane" action, but there's no
|
|
||||||
// existing tab to duplicate, then we can't resolve the profile from
|
|
||||||
// the existing pane. So in that scenario, we won't be able to toss
|
|
||||||
// anything over to the elevated window.
|
|
||||||
TerminalSettingsCreateResult controlSettings{ TerminalSettings::CreateWithNewTerminalArgs(_settings,
|
|
||||||
newTerminalArgs,
|
|
||||||
*_bindings) };
|
|
||||||
Profile profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
|
||||||
_maybeElevate(newTerminalArgs, controlSettings, profile);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
||||||
// given TermControl into the newly created pane.
|
// given pane accordingly
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - tab: The tab that is going to be split.
|
// - tab: The tab that is going to be split.
|
||||||
|
// - newPane: the pane to add to our tree of panes
|
||||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||||
// new pane should be split from its parent.
|
// new pane should be split from its parent.
|
||||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
// - splitSize: the size of the split
|
||||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
|
||||||
// control which profile is created and with possible other
|
|
||||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
|
||||||
void TerminalPage::_SplitPane(TerminalTab& tab,
|
void TerminalPage::_SplitPane(TerminalTab& tab,
|
||||||
const SplitDirection splitDirection,
|
const SplitDirection splitDirection,
|
||||||
const SplitType splitMode,
|
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const NewTerminalArgs& newTerminalArgs)
|
std::shared_ptr<Pane> newPane)
|
||||||
{
|
{
|
||||||
try
|
// If the caller is calling us with the return value of _MakePane
|
||||||
|
// directly, it's possible that nullptr was returned, if the connections
|
||||||
|
// was supposed to be launched in an elevated window. In that case, do
|
||||||
|
// nothing here. We don't have a pane with which to create the split.
|
||||||
|
if (!newPane)
|
||||||
{
|
{
|
||||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
return;
|
||||||
Profile profile{ nullptr };
|
}
|
||||||
|
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
||||||
|
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||||
|
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||||
|
|
||||||
if (splitMode == SplitType::Duplicate)
|
auto realSplitType = splitDirection;
|
||||||
|
if (realSplitType == SplitDirection::Automatic)
|
||||||
|
{
|
||||||
|
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||||
|
if (!canSplit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_UnZoomIfNeeded();
|
||||||
|
tab.SplitPane(realSplitType, splitSize, newPane);
|
||||||
|
|
||||||
|
// After GH#6586, the control will no longer focus itself
|
||||||
|
// automatically when it's finished being laid out. Manually focus
|
||||||
|
// the control here instead.
|
||||||
|
if (_startupState == StartupState::Initialized)
|
||||||
|
{
|
||||||
|
if (const auto control = _GetActiveControl())
|
||||||
{
|
{
|
||||||
profile = tab.GetFocusedProfile();
|
control.Focus(FocusState::Programmatic);
|
||||||
if (profile)
|
|
||||||
{
|
|
||||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
|
||||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
|
||||||
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
|
||||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
|
||||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
|
||||||
if (validWorkingDirectory)
|
|
||||||
{
|
|
||||||
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: GH#5047 - In the future, we should get the Profile of
|
|
||||||
// the focused pane, and use that to build a new instance of the
|
|
||||||
// settings so we can duplicate this tab/pane.
|
|
||||||
//
|
|
||||||
// Currently, if the profile doesn't exist anymore in our
|
|
||||||
// settings, we'll silently do nothing.
|
|
||||||
//
|
|
||||||
// In the future, it will be preferable to just duplicate the
|
|
||||||
// current control's settings, but we can't do that currently,
|
|
||||||
// because we won't be able to create a new instance of the
|
|
||||||
// connection without keeping an instance of the original Profile
|
|
||||||
// object around.
|
|
||||||
}
|
|
||||||
if (!profile)
|
|
||||||
{
|
|
||||||
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
|
||||||
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to handle auto-elevation
|
|
||||||
if (_maybeElevate(newTerminalArgs, controlSettings, profile))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
|
||||||
|
|
||||||
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
|
||||||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
|
||||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
|
||||||
|
|
||||||
auto realSplitType = splitDirection;
|
|
||||||
if (realSplitType == SplitDirection::Automatic)
|
|
||||||
{
|
|
||||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
|
||||||
if (!canSplit)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto newControl = _InitControl(controlSettings, controlConnection);
|
|
||||||
WUX::Controls::UserControl controlToAdd{ newControl };
|
|
||||||
|
|
||||||
const auto& cmdline{ controlSettings.DefaultSettings().Commandline() };
|
|
||||||
const auto doAdminWarning{ _shouldPromptForCommandline(cmdline) };
|
|
||||||
if (doAdminWarning)
|
|
||||||
{
|
|
||||||
auto warningControl{ winrt::make_self<implementation::AdminWarningPlaceholder>(newControl, cmdline) };
|
|
||||||
warningControl->PrimaryButtonClicked({ get_weak(), &TerminalPage::_adminWarningPrimaryClicked });
|
|
||||||
warningControl->CancelButtonClicked({ get_weak(), &TerminalPage::_adminWarningCancelClicked });
|
|
||||||
controlToAdd = *warningControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hookup our event handlers to the new terminal
|
|
||||||
_RegisterTerminalEvents(newControl);
|
|
||||||
|
|
||||||
_UnZoomIfNeeded();
|
|
||||||
|
|
||||||
tab.SplitPane(realSplitType, splitSize, profile, controlToAdd);
|
|
||||||
|
|
||||||
// After GH#6586, the control will no longer focus itself
|
|
||||||
// automatically when it's finished being laid out. Manually focus
|
|
||||||
// the control here instead.
|
|
||||||
if (_startupState == StartupState::Initialized)
|
|
||||||
{
|
|
||||||
if (const auto& activeControl{ _GetActiveControl() })
|
|
||||||
{
|
|
||||||
activeControl.Focus(FocusState::Programmatic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doAdminWarning)
|
|
||||||
{
|
|
||||||
// We know this is safe - we literally just added the
|
|
||||||
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
|
|
||||||
//
|
|
||||||
// Focus the warning here. The LayoutUpdated within the dialog
|
|
||||||
// itself isn't good enough. That, for some reason, fires _before_
|
|
||||||
// the dialog is in the UI tree, which is useless for us.
|
|
||||||
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CATCH_LOG();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -2463,7 +2389,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
if (target == SettingsTarget::SettingsUI)
|
if (target == SettingsTarget::SettingsUI)
|
||||||
{
|
{
|
||||||
_OpenSettingsUI();
|
OpenSettingsUI();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2540,6 +2466,133 @@ namespace winrt::TerminalApp::implementation
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Creates a pane and returns a shared_ptr to it
|
||||||
|
// - The caller should handle where the pane goes after creation,
|
||||||
|
// either to split an already existing pane or to create a new tab with it
|
||||||
|
// Arguments:
|
||||||
|
// - newTerminalArgs: an object that may contain a blob of parameters to
|
||||||
|
// control which profile is created and with possible other
|
||||||
|
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||||
|
// - duplicate: a boolean to indicate whether the pane we create should be
|
||||||
|
// a duplicate of the currently focused pane
|
||||||
|
// - existingConnection: optionally receives a connection from the outside
|
||||||
|
// world instead of attempting to create one
|
||||||
|
// Return Value:
|
||||||
|
// - If the newTerminalArgs required us to open the pane as a new elevated
|
||||||
|
// connection, then we'll return nullptr. Otherwise, we'll return a new
|
||||||
|
// Pane for this connection.
|
||||||
|
std::shared_ptr<Pane> TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs,
|
||||||
|
const bool duplicate,
|
||||||
|
TerminalConnection::ITerminalConnection existingConnection)
|
||||||
|
{
|
||||||
|
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||||
|
Profile profile{ nullptr };
|
||||||
|
|
||||||
|
if (duplicate)
|
||||||
|
{
|
||||||
|
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||||
|
if (focusedTab)
|
||||||
|
{
|
||||||
|
profile = focusedTab->GetFocusedProfile();
|
||||||
|
if (profile)
|
||||||
|
{
|
||||||
|
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||||
|
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||||
|
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
||||||
|
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
|
||||||
|
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||||
|
if (validWorkingDirectory)
|
||||||
|
{
|
||||||
|
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!profile)
|
||||||
|
{
|
||||||
|
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
||||||
|
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to handle auto-elevation
|
||||||
|
if (_maybeElevate(newTerminalArgs, controlSettings, profile))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
||||||
|
if (existingConnection)
|
||||||
|
{
|
||||||
|
connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols());
|
||||||
|
}
|
||||||
|
|
||||||
|
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||||
|
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
||||||
|
{
|
||||||
|
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||||
|
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||||
|
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||||
|
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||||
|
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||||
|
if (bothAltsPressed)
|
||||||
|
{
|
||||||
|
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto control = _InitControl(controlSettings, connection);
|
||||||
|
_RegisterTerminalEvents(control);
|
||||||
|
|
||||||
|
WUX::Controls::UserControl controlToAdd{ control };
|
||||||
|
|
||||||
|
// Check if we should warn the user about running a new unelevated
|
||||||
|
// commandline.
|
||||||
|
const auto& cmdline{ controlSettings.DefaultSettings().Commandline() };
|
||||||
|
const auto doAdminWarning{ _shouldPromptForCommandline(cmdline) };
|
||||||
|
if (doAdminWarning)
|
||||||
|
{
|
||||||
|
auto warningControl{ winrt::make_self<implementation::AdminWarningPlaceholder>(control, cmdline) };
|
||||||
|
warningControl->PrimaryButtonClicked({ get_weak(), &TerminalPage::_adminWarningPrimaryClicked });
|
||||||
|
warningControl->CancelButtonClicked({ get_weak(), &TerminalPage::_adminWarningCancelClicked });
|
||||||
|
controlToAdd = *warningControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resultPane = std::make_shared<Pane>(profile, controlToAdd);
|
||||||
|
|
||||||
|
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||||
|
{
|
||||||
|
auto newControl = _InitControl(controlSettings, debugConnection);
|
||||||
|
_RegisterTerminalEvents(newControl);
|
||||||
|
// Split (auto) with the debug tap.
|
||||||
|
auto debugPane = std::make_shared<Pane>(profile, newControl);
|
||||||
|
|
||||||
|
// Since we're doing this split directly on the pane (instead of going through TerminalTab,
|
||||||
|
// we need to handle the panes 'active' states
|
||||||
|
|
||||||
|
// Set the pane we're splitting to active (otherwise Split will not do anything)
|
||||||
|
resultPane->SetActive();
|
||||||
|
auto [original, _] = resultPane->Split(SplitDirection::Automatic, 0.5f, debugPane);
|
||||||
|
|
||||||
|
// Set the non-debug pane as active
|
||||||
|
resultPane->ClearActive();
|
||||||
|
original->SetActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doAdminWarning)
|
||||||
|
{
|
||||||
|
// We know this is safe - we literally just added the
|
||||||
|
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
|
||||||
|
//
|
||||||
|
// Focus the warning here. The LayoutUpdated within the dialog
|
||||||
|
// itself isn't good enough. That, for some reason, fires _before_
|
||||||
|
// the dialog is in the UI tree, which is useless for us.
|
||||||
|
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultPane;
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Hook up keybindings, and refresh the UI of the terminal.
|
// - Hook up keybindings, and refresh the UI of the terminal.
|
||||||
// This includes update the settings of all the tabs according
|
// This includes update the settings of all the tabs according
|
||||||
|
@ -2849,9 +2902,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::ToggleFullscreen()
|
void TerminalPage::ToggleFullscreen()
|
||||||
{
|
{
|
||||||
_isFullscreen = !_isFullscreen;
|
SetFullscreen(!_isFullscreen);
|
||||||
_UpdateTabView();
|
|
||||||
_FullscreenChangedHandlers(*this, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -3068,6 +3119,17 @@ namespace winrt::TerminalApp::implementation
|
||||||
return _isAlwaysOnTop;
|
return _isAlwaysOnTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalPage::SetFullscreen(bool newFullscreen)
|
||||||
|
{
|
||||||
|
if (_isFullscreen == newFullscreen)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isFullscreen = newFullscreen;
|
||||||
|
_UpdateTabView();
|
||||||
|
_FullscreenChangedHandlers(*this, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection)
|
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection)
|
||||||
{
|
{
|
||||||
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
||||||
|
@ -3095,7 +3157,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||||
|
|
||||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
|
||||||
|
|
||||||
// Request a summon of this window to the foreground
|
// Request a summon of this window to the foreground
|
||||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||||
|
@ -3111,7 +3173,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::_OpenSettingsUI()
|
void TerminalPage::OpenSettingsUI()
|
||||||
{
|
{
|
||||||
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
|
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
|
||||||
if (!_settingsTab)
|
if (!_settingsTab)
|
||||||
|
@ -3786,7 +3848,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||||
|
|
||||||
_OpenSettingsUI();
|
OpenSettingsUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool FocusMode() const;
|
bool FocusMode() const;
|
||||||
bool Fullscreen() const;
|
bool Fullscreen() const;
|
||||||
bool AlwaysOnTop() const;
|
bool AlwaysOnTop() const;
|
||||||
|
void SetFullscreen(bool);
|
||||||
|
|
||||||
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
||||||
|
|
||||||
|
@ -121,6 +122,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool IsQuakeWindow() const noexcept;
|
bool IsQuakeWindow() const noexcept;
|
||||||
bool IsElevated() const noexcept;
|
bool IsElevated() const noexcept;
|
||||||
|
|
||||||
|
void OpenSettingsUI();
|
||||||
|
|
||||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||||
|
|
||||||
// -------------------------------- WinRT Events ---------------------------------
|
// -------------------------------- WinRT Events ---------------------------------
|
||||||
|
@ -210,7 +213,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
void _OpenNewTabDropdown();
|
void _OpenNewTabDropdown();
|
||||||
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||||
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
|
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
|
||||||
void _CreateNewTabWithProfileAndSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
|
||||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
|
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
|
||||||
|
|
||||||
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
|
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
|
||||||
|
@ -298,14 +300,12 @@ namespace winrt::TerminalApp::implementation
|
||||||
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
|
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
|
||||||
|
|
||||||
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
const float splitSize,
|
||||||
const float splitSize = 0.5f,
|
std::shared_ptr<Pane> newPane);
|
||||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
|
||||||
void _SplitPane(TerminalTab& tab,
|
void _SplitPane(TerminalTab& tab,
|
||||||
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
const float splitSize,
|
||||||
const float splitSize = 0.5f,
|
std::shared_ptr<Pane> newPane);
|
||||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
|
||||||
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||||
void _ToggleSplitOrientation();
|
void _ToggleSplitOrientation();
|
||||||
|
|
||||||
|
@ -352,6 +352,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||||
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
|
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
|
||||||
|
|
||||||
|
std::shared_ptr<Pane> _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr,
|
||||||
|
const bool duplicate = false,
|
||||||
|
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||||
|
|
||||||
void _RefreshUIForSettingsReload();
|
void _RefreshUIForSettingsReload();
|
||||||
|
|
||||||
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
|
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
|
||||||
|
@ -367,8 +371,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
void _UnZoomIfNeeded();
|
void _UnZoomIfNeeded();
|
||||||
|
|
||||||
void _OpenSettingsUI();
|
|
||||||
|
|
||||||
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
|
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
|
||||||
static uint32_t _ReadSystemRowsToScroll();
|
static uint32_t _ReadSystemRowsToScroll();
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
|
|
||||||
<local:CommandPalette x:Name="CommandPalette"
|
<local:CommandPalette x:Name="CommandPalette"
|
||||||
Grid.Row="1"
|
Grid.Row="2"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
PreviewKeyDown="_KeyDownHandler"
|
PreviewKeyDown="_KeyDownHandler"
|
||||||
Visibility="Collapsed" />
|
Visibility="Collapsed" />
|
||||||
|
|
|
@ -25,18 +25,6 @@ namespace winrt
|
||||||
|
|
||||||
namespace winrt::TerminalApp::implementation
|
namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
TerminalTab::TerminalTab(const Profile& profile, const WUX::Controls::UserControl& control)
|
|
||||||
{
|
|
||||||
_rootPane = std::make_shared<Pane>(profile, control, true);
|
|
||||||
|
|
||||||
_rootPane->Id(_nextPaneId);
|
|
||||||
_activePane = _rootPane;
|
|
||||||
_mruPanes.insert(_mruPanes.begin(), _nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
|
|
||||||
_Setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminalTab::TerminalTab(std::shared_ptr<Pane> rootPane)
|
TerminalTab::TerminalTab(std::shared_ptr<Pane> rootPane)
|
||||||
{
|
{
|
||||||
_rootPane = rootPane;
|
_rootPane = rootPane;
|
||||||
|
@ -64,8 +52,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
// focus the first one.
|
// focus the first one.
|
||||||
if (_activePane == nullptr)
|
if (_activePane == nullptr)
|
||||||
{
|
{
|
||||||
_rootPane->FocusPane(firstId);
|
const auto firstPane = _rootPane->FindPane(firstId);
|
||||||
_activePane = _rootPane->GetActivePane();
|
firstPane->SetActive();
|
||||||
|
_activePane = firstPane;
|
||||||
}
|
}
|
||||||
// If the focused pane is a leaf, add it to the MRU panes
|
// If the focused pane is a leaf, add it to the MRU panes
|
||||||
if (const auto id = _activePane->Id())
|
if (const auto id = _activePane->Id())
|
||||||
|
@ -506,42 +495,52 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Split the focused pane in our tree of panes, and place the
|
// - Split the focused pane in our tree of panes, and place the
|
||||||
// given TermControl into the newly created pane.
|
// given pane into the tree of panes according to the split
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - splitType: The type of split we want to create.
|
// - splitType: The type of split we want to create
|
||||||
// - profile: The profile GUID to associate with the newly created pane.
|
// - splitSize: The size of the split we want to create
|
||||||
// - control: A TermControl to use in the new pane.
|
// - pane: The new pane to add to the tree of panes; note that this pane
|
||||||
|
// could itself be a parent pane/the root node of a tree of panes
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalTab::SplitPane(SplitDirection splitType,
|
void TerminalTab::SplitPane(SplitDirection splitType,
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const Profile& profile,
|
std::shared_ptr<Pane> pane)
|
||||||
const WUX::Controls::UserControl& control)
|
|
||||||
{
|
{
|
||||||
|
// Add the new event handlers to the new pane(s)
|
||||||
|
// and update their ids.
|
||||||
|
pane->WalkTree([&](auto p) {
|
||||||
|
_AttachEventHandlersToPane(p);
|
||||||
|
if (p->_IsLeaf())
|
||||||
|
{
|
||||||
|
p->Id(_nextPaneId);
|
||||||
|
if (auto termControl{ p->_control.try_as<TermControl>() })
|
||||||
|
{
|
||||||
|
_AttachEventHandlersToControl(p->Id().value(), termControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
_nextPaneId++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||||
const auto activePaneId = _activePane->Id();
|
const auto activePaneId = _activePane->Id();
|
||||||
// Depending on which direction will be split, the new pane can be
|
// Depending on which direction will be split, the new pane can be
|
||||||
// either the first or second child, but this will always return the
|
// either the first or second child, but this will always return the
|
||||||
// original pane first.
|
// original pane first.
|
||||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
auto [original, newPane] = _activePane->Split(splitType, splitSize, pane);
|
||||||
|
|
||||||
// The active pane has an id if it is a leaf
|
// The active pane has an id if it is a leaf
|
||||||
if (activePaneId)
|
if (activePaneId)
|
||||||
{
|
{
|
||||||
original->Id(activePaneId.value());
|
original->Id(activePaneId.value());
|
||||||
}
|
}
|
||||||
newPane->Id(_nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
|
|
||||||
_activePane = original;
|
_activePane = original;
|
||||||
|
|
||||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||||
// gains focus, we'll mark it as the new active pane.
|
// gains focus, we'll mark it as the new active pane.
|
||||||
const auto& termControl{ control.try_as<TermControl>() };
|
|
||||||
// _AttachEventHandlersToControl will immediately bail if the provided
|
|
||||||
// control is null (READ: if the pane didn't have a TermControl)
|
|
||||||
_AttachEventHandlersToControl(newPane->Id().value(), termControl);
|
|
||||||
_AttachEventHandlersToPane(original);
|
_AttachEventHandlersToPane(original);
|
||||||
_AttachEventHandlersToPane(newPane);
|
|
||||||
|
|
||||||
// Immediately update our tracker of the focused pane now. If we're
|
// Immediately update our tracker of the focused pane now. If we're
|
||||||
// splitting panes during startup (from a commandline), then it's
|
// splitting panes during startup (from a commandline), then it's
|
||||||
|
@ -1756,6 +1755,19 @@ namespace winrt::TerminalApp::implementation
|
||||||
return Title();
|
return Title();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalTab::ReplaceControl(std::shared_ptr<Pane> pane, const Controls::UserControl& control)
|
||||||
|
{
|
||||||
|
pane->ReplaceControl(control);
|
||||||
|
|
||||||
|
if (auto termControl{ pane->_control.try_as<TermControl>() })
|
||||||
|
{
|
||||||
|
_AttachEventHandlersToControl(pane->Id().value(), termControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the title manually.
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_EVENT(TerminalTab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
DEFINE_EVENT(TerminalTab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
||||||
DEFINE_EVENT(TerminalTab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
DEFINE_EVENT(TerminalTab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
||||||
DEFINE_EVENT(TerminalTab, ColorCleared, _colorCleared, winrt::delegate<>);
|
DEFINE_EVENT(TerminalTab, ColorCleared, _colorCleared, winrt::delegate<>);
|
||||||
|
|
|
@ -21,8 +21,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
|
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
|
||||||
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
|
|
||||||
TerminalTab(std::shared_ptr<Pane> rootPane);
|
TerminalTab(std::shared_ptr<Pane> rootPane);
|
||||||
|
|
||||||
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
||||||
|
@ -41,8 +39,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
std::shared_ptr<Pane> newPane);
|
||||||
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
|
|
||||||
|
|
||||||
void ToggleSplitOrientation();
|
void ToggleSplitOrientation();
|
||||||
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
||||||
|
@ -96,6 +93,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
std::shared_ptr<Pane> GetRootPane() const { return _rootPane; }
|
std::shared_ptr<Pane> GetRootPane() const { return _rootPane; }
|
||||||
|
|
||||||
|
void ReplaceControl(std::shared_ptr<Pane> pane,
|
||||||
|
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
|
||||||
|
|
||||||
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
||||||
{
|
{
|
||||||
return _tabStatus;
|
return _tabStatus;
|
||||||
|
|
|
@ -429,8 +429,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
// EXIT POINT
|
// EXIT POINT
|
||||||
const auto hr = wil::ResultFromCaughtException();
|
const auto hr = wil::ResultFromCaughtException();
|
||||||
|
|
||||||
|
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||||
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
|
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
|
||||||
fmt::format(_errorFormat, hr),
|
fmt::format(_errorFormat, static_cast<unsigned int>(hr)),
|
||||||
_commandline) };
|
_commandline) };
|
||||||
_TerminalOutputHandlers(failureText);
|
_TerminalOutputHandlers(failureText);
|
||||||
|
|
||||||
|
@ -457,6 +458,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||||
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
|
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
|
||||||
_TerminalOutputHandlers(L"\r\n");
|
_TerminalOutputHandlers(L"\r\n");
|
||||||
_TerminalOutputHandlers(exitText);
|
_TerminalOutputHandlers(exitText);
|
||||||
|
|
|
@ -1210,9 +1210,7 @@ try
|
||||||
{
|
{
|
||||||
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
||||||
// First set up the basic 256 colors
|
// First set up the basic 256 colors
|
||||||
Utils::Initialize256ColorTable(tableView);
|
Utils::InitializeColorTable(tableView);
|
||||||
// Then use fill the first 16 values with the Campbell scheme
|
|
||||||
Utils::InitializeCampbellColorTable(tableView);
|
|
||||||
// Then make sure all the values have an alpha of 255
|
// Then make sure all the values have an alpha of 255
|
||||||
Utils::SetColorTableAlpha(tableView, 0xff);
|
Utils::SetColorTableAlpha(tableView, 0xff);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,29 +7,6 @@
|
||||||
using namespace Microsoft::Console::VirtualTerminal;
|
using namespace Microsoft::Console::VirtualTerminal;
|
||||||
using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
|
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:
|
// Routine Description:
|
||||||
// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG)
|
// - 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)
|
// 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);
|
attr.SetOverlined(false);
|
||||||
break;
|
break;
|
||||||
case ForegroundBlack:
|
case ForegroundBlack:
|
||||||
attr.SetIndexedForeground(DARK_BLACK);
|
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case ForegroundBlue:
|
case ForegroundBlue:
|
||||||
attr.SetIndexedForeground(DARK_BLUE);
|
attr.SetIndexedForeground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case ForegroundGreen:
|
case ForegroundGreen:
|
||||||
attr.SetIndexedForeground(DARK_GREEN);
|
attr.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case ForegroundCyan:
|
case ForegroundCyan:
|
||||||
attr.SetIndexedForeground(DARK_CYAN);
|
attr.SetIndexedForeground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case ForegroundRed:
|
case ForegroundRed:
|
||||||
attr.SetIndexedForeground(DARK_RED);
|
attr.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case ForegroundMagenta:
|
case ForegroundMagenta:
|
||||||
attr.SetIndexedForeground(DARK_MAGENTA);
|
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case ForegroundYellow:
|
case ForegroundYellow:
|
||||||
attr.SetIndexedForeground(DARK_YELLOW);
|
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case ForegroundWhite:
|
case ForegroundWhite:
|
||||||
attr.SetIndexedForeground(DARK_WHITE);
|
attr.SetIndexedForeground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case BackgroundBlack:
|
case BackgroundBlack:
|
||||||
attr.SetIndexedBackground(DARK_BLACK);
|
attr.SetIndexedBackground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case BackgroundBlue:
|
case BackgroundBlue:
|
||||||
attr.SetIndexedBackground(DARK_BLUE);
|
attr.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case BackgroundGreen:
|
case BackgroundGreen:
|
||||||
attr.SetIndexedBackground(DARK_GREEN);
|
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case BackgroundCyan:
|
case BackgroundCyan:
|
||||||
attr.SetIndexedBackground(DARK_CYAN);
|
attr.SetIndexedBackground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case BackgroundRed:
|
case BackgroundRed:
|
||||||
attr.SetIndexedBackground(DARK_RED);
|
attr.SetIndexedBackground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case BackgroundMagenta:
|
case BackgroundMagenta:
|
||||||
attr.SetIndexedBackground(DARK_MAGENTA);
|
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BackgroundYellow:
|
case BackgroundYellow:
|
||||||
attr.SetIndexedBackground(DARK_YELLOW);
|
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BackgroundWhite:
|
case BackgroundWhite:
|
||||||
attr.SetIndexedBackground(DARK_WHITE);
|
attr.SetIndexedBackground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundBlack:
|
case BrightForegroundBlack:
|
||||||
attr.SetIndexedForeground(BRIGHT_BLACK);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundBlue:
|
case BrightForegroundBlue:
|
||||||
attr.SetIndexedForeground(BRIGHT_BLUE);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundGreen:
|
case BrightForegroundGreen:
|
||||||
attr.SetIndexedForeground(BRIGHT_GREEN);
|
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundCyan:
|
case BrightForegroundCyan:
|
||||||
attr.SetIndexedForeground(BRIGHT_CYAN);
|
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundRed:
|
case BrightForegroundRed:
|
||||||
attr.SetIndexedForeground(BRIGHT_RED);
|
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundMagenta:
|
case BrightForegroundMagenta:
|
||||||
attr.SetIndexedForeground(BRIGHT_MAGENTA);
|
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundYellow:
|
case BrightForegroundYellow:
|
||||||
attr.SetIndexedForeground(BRIGHT_YELLOW);
|
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundWhite:
|
case BrightForegroundWhite:
|
||||||
attr.SetIndexedForeground(BRIGHT_WHITE);
|
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundBlack:
|
case BrightBackgroundBlack:
|
||||||
attr.SetIndexedBackground(BRIGHT_BLACK);
|
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundBlue:
|
case BrightBackgroundBlue:
|
||||||
attr.SetIndexedBackground(BRIGHT_BLUE);
|
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundGreen:
|
case BrightBackgroundGreen:
|
||||||
attr.SetIndexedBackground(BRIGHT_GREEN);
|
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundCyan:
|
case BrightBackgroundCyan:
|
||||||
attr.SetIndexedBackground(BRIGHT_CYAN);
|
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundRed:
|
case BrightBackgroundRed:
|
||||||
attr.SetIndexedBackground(BRIGHT_RED);
|
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundMagenta:
|
case BrightBackgroundMagenta:
|
||||||
attr.SetIndexedBackground(BRIGHT_MAGENTA);
|
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundYellow:
|
case BrightBackgroundYellow:
|
||||||
attr.SetIndexedBackground(BRIGHT_YELLOW);
|
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundWhite:
|
case BrightBackgroundWhite:
|
||||||
attr.SetIndexedBackground(BRIGHT_WHITE);
|
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
case ForegroundExtended:
|
case ForegroundExtended:
|
||||||
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
|
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
|
||||||
|
|
|
@ -86,8 +86,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
|
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
|
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, ForceFullRepaintRendering);
|
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, SoftwareRendering);
|
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
|
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
||||||
|
|
|
@ -53,8 +53,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ForceFullRepaintRendering);
|
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SoftwareRendering);
|
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
|
||||||
|
|
|
@ -16,17 +16,6 @@ static constexpr std::string_view ForegroundKey{ "foreground" };
|
||||||
static constexpr std::string_view BackgroundKey{ "background" };
|
static constexpr std::string_view BackgroundKey{ "background" };
|
||||||
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
||||||
static constexpr std::string_view CursorColorKey{ "cursorColor" };
|
static constexpr std::string_view CursorColorKey{ "cursorColor" };
|
||||||
static constexpr std::string_view CursorShapeKey{ "cursorShape" };
|
|
||||||
static constexpr std::string_view CursorHeightKey{ "cursorHeight" };
|
|
||||||
static constexpr std::string_view BackgroundImageKey{ "backgroundImage" };
|
|
||||||
static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
|
|
||||||
static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" };
|
|
||||||
static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImageStretchMode" };
|
|
||||||
static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" };
|
|
||||||
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
|
|
||||||
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
|
|
||||||
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
|
|
||||||
static constexpr std::string_view AdjustIndistinguishableColorsKey{ "adjustIndistinguishableColors" };
|
|
||||||
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
|
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
|
||||||
static constexpr std::string_view OpacityKey{ "opacity" };
|
static constexpr std::string_view OpacityKey{ "opacity" };
|
||||||
|
|
||||||
|
@ -38,22 +27,17 @@ AppearanceConfig::AppearanceConfig(winrt::weak_ref<Profile> sourceProfile) :
|
||||||
winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||||
{
|
{
|
||||||
auto appearance{ winrt::make_self<AppearanceConfig>(std::move(sourceProfile)) };
|
auto appearance{ winrt::make_self<AppearanceConfig>(std::move(sourceProfile)) };
|
||||||
appearance->_BackgroundImagePath = source->_BackgroundImagePath;
|
|
||||||
appearance->_BackgroundImageOpacity = source->_BackgroundImageOpacity;
|
|
||||||
appearance->_BackgroundImageStretchMode = source->_BackgroundImageStretchMode;
|
|
||||||
appearance->_ColorSchemeName = source->_ColorSchemeName;
|
|
||||||
appearance->_Foreground = source->_Foreground;
|
appearance->_Foreground = source->_Foreground;
|
||||||
appearance->_Background = source->_Background;
|
appearance->_Background = source->_Background;
|
||||||
appearance->_SelectionBackground = source->_SelectionBackground;
|
appearance->_SelectionBackground = source->_SelectionBackground;
|
||||||
appearance->_CursorColor = source->_CursorColor;
|
appearance->_CursorColor = source->_CursorColor;
|
||||||
appearance->_CursorShape = source->_CursorShape;
|
|
||||||
appearance->_CursorHeight = source->_CursorHeight;
|
|
||||||
appearance->_BackgroundImageAlignment = source->_BackgroundImageAlignment;
|
|
||||||
appearance->_RetroTerminalEffect = source->_RetroTerminalEffect;
|
|
||||||
appearance->_PixelShaderPath = source->_PixelShaderPath;
|
|
||||||
appearance->_IntenseTextStyle = source->_IntenseTextStyle;
|
|
||||||
appearance->_Opacity = source->_Opacity;
|
appearance->_Opacity = source->_Opacity;
|
||||||
appearance->_AdjustIndistinguishableColors = source->_AdjustIndistinguishableColors;
|
|
||||||
|
#define APPEARANCE_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||||
|
appearance->_##name = source->_##name;
|
||||||
|
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_COPY)
|
||||||
|
#undef APPEARANCE_SETTINGS_COPY
|
||||||
|
|
||||||
return appearance;
|
return appearance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +49,13 @@ Json::Value AppearanceConfig::ToJson() const
|
||||||
JsonUtils::SetValueForKey(json, BackgroundKey, _Background);
|
JsonUtils::SetValueForKey(json, BackgroundKey, _Background);
|
||||||
JsonUtils::SetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
JsonUtils::SetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
||||||
JsonUtils::SetValueForKey(json, CursorColorKey, _CursorColor);
|
JsonUtils::SetValueForKey(json, CursorColorKey, _CursorColor);
|
||||||
JsonUtils::SetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
|
|
||||||
JsonUtils::SetValueForKey(json, CursorHeightKey, _CursorHeight);
|
|
||||||
JsonUtils::SetValueForKey(json, CursorShapeKey, _CursorShape);
|
|
||||||
JsonUtils::SetValueForKey(json, BackgroundImageKey, _BackgroundImagePath);
|
|
||||||
JsonUtils::SetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity);
|
|
||||||
JsonUtils::SetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode);
|
|
||||||
JsonUtils::SetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment);
|
|
||||||
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
|
||||||
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
|
||||||
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
|
||||||
JsonUtils::SetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors);
|
|
||||||
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||||
|
|
||||||
|
#define APPEARANCE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||||
|
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||||
|
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_TO_JSON)
|
||||||
|
#undef APPEARANCE_SETTINGS_TO_JSON
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,19 +76,14 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
|
||||||
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
|
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
|
||||||
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
||||||
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
|
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
|
||||||
JsonUtils::GetValueForKey(json, CursorHeightKey, _CursorHeight);
|
|
||||||
JsonUtils::GetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
|
|
||||||
JsonUtils::GetValueForKey(json, CursorShapeKey, _CursorShape);
|
|
||||||
JsonUtils::GetValueForKey(json, BackgroundImageKey, _BackgroundImagePath);
|
|
||||||
JsonUtils::GetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity);
|
|
||||||
JsonUtils::GetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode);
|
|
||||||
JsonUtils::GetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment);
|
|
||||||
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
|
||||||
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
|
||||||
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
|
||||||
JsonUtils::GetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors);
|
|
||||||
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
|
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
|
||||||
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||||
|
|
||||||
|
#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||||
|
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||||
|
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON)
|
||||||
|
#undef APPEARANCE_SETTINGS_LAYER_JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
|
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
|
||||||
|
|
|
@ -19,6 +19,7 @@ Author(s):
|
||||||
#include "AppearanceConfig.g.h"
|
#include "AppearanceConfig.g.h"
|
||||||
#include "JsonUtils.h"
|
#include "JsonUtils.h"
|
||||||
#include "IInheritable.h"
|
#include "IInheritable.h"
|
||||||
|
#include "MTSMSettings.h"
|
||||||
#include <DefaultSettings.h>
|
#include <DefaultSettings.h>
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
@ -35,26 +36,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
winrt::hstring ExpandedBackgroundImagePath();
|
winrt::hstring ExpandedBackgroundImagePath();
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, ConvergedAlignment, BackgroundImageAlignment, ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, ColorSchemeName, L"Campbell");
|
|
||||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Foreground, nullptr);
|
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Foreground, nullptr);
|
||||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Background, nullptr);
|
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Background, nullptr);
|
||||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, SelectionBackground, nullptr);
|
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, SelectionBackground, nullptr);
|
||||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, CursorColor, nullptr);
|
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, CursorColor, nullptr);
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::CursorStyle, CursorShape, Microsoft::Terminal::Core::CursorStyle::Bar);
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, BackgroundImagePath);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, BackgroundImageOpacity, 1.0);
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch::UniformToFill);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false);
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L"");
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
|
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, AdjustIndistinguishableColors, true);
|
#define APPEARANCE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||||
|
INHERITABLE_SETTING(Model::IAppearanceConfig, type, name, ##__VA_ARGS__)
|
||||||
|
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_INITIALIZE)
|
||||||
|
#undef APPEARANCE_SETTINGS_INITIALIZE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
winrt::weak_ref<Profile> _sourceProfile;
|
winrt::weak_ref<Profile> _sourceProfile;
|
||||||
|
|
|
@ -287,8 +287,6 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source)
|
||||||
DUPLICATE_SETTING_MACRO(Commandline);
|
DUPLICATE_SETTING_MACRO(Commandline);
|
||||||
DUPLICATE_SETTING_MACRO(StartingDirectory);
|
DUPLICATE_SETTING_MACRO(StartingDirectory);
|
||||||
DUPLICATE_SETTING_MACRO(AntialiasingMode);
|
DUPLICATE_SETTING_MACRO(AntialiasingMode);
|
||||||
DUPLICATE_SETTING_MACRO(ForceFullRepaintRendering);
|
|
||||||
DUPLICATE_SETTING_MACRO(SoftwareRendering);
|
|
||||||
DUPLICATE_SETTING_MACRO(HistorySize);
|
DUPLICATE_SETTING_MACRO(HistorySize);
|
||||||
DUPLICATE_SETTING_MACRO(SnapOnInput);
|
DUPLICATE_SETTING_MACRO(SnapOnInput);
|
||||||
DUPLICATE_SETTING_MACRO(AltGrAliasing);
|
DUPLICATE_SETTING_MACRO(AltGrAliasing);
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <WtExeUtils.h>
|
#include <WtExeUtils.h>
|
||||||
|
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
#include <wil/token_helpers.h>
|
||||||
|
|
||||||
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
|
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
|
||||||
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
||||||
|
@ -41,72 +43,43 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
return baseSettingsPath;
|
return baseSettingsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _hasExpectedPermissions(const std::filesystem::path& path)
|
// Function Description:
|
||||||
|
// - Checks the permissions on this file, to make sure it can only be opened
|
||||||
|
// for writing by admins. We will be checking to see if the file is owned
|
||||||
|
// by the Builtin\Administrators group. If it's not, then it was likely
|
||||||
|
// tampered with.
|
||||||
|
// Arguments:
|
||||||
|
// - path: the path to the file to check
|
||||||
|
// Return Value:
|
||||||
|
// - true if it had the expected permissions. False otherwise.
|
||||||
|
static bool _hasElevatedOnlyPermissions(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
// If we want to only open the file if it's elevated, check the
|
// If the file is owned by the administrators group, trust the
|
||||||
// permissions on this file. We want to make sure that:
|
// administrators instead of checking the DACL permissions. It's simpler
|
||||||
// * Everyone has permission to read
|
// and more flexible.
|
||||||
// * admins can do anything
|
|
||||||
// * no one else can do anything.
|
|
||||||
PACL pAcl{ nullptr }; // This doesn't need to be cleanup up apparently
|
|
||||||
|
|
||||||
auto status = GetNamedSecurityInfo(path.c_str(),
|
wil::unique_hlocal_security_descriptor sd;
|
||||||
SE_FILE_OBJECT,
|
PSID psidOwner{ nullptr };
|
||||||
DACL_SECURITY_INFORMATION,
|
// The psidOwner pointer references the security descriptor, so it
|
||||||
nullptr,
|
// doesn't have to be freed separate from sd.
|
||||||
nullptr,
|
const auto status = GetNamedSecurityInfoW(path.c_str(),
|
||||||
&pAcl,
|
SE_FILE_OBJECT,
|
||||||
nullptr,
|
OWNER_SECURITY_INFORMATION,
|
||||||
nullptr);
|
&psidOwner,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
wil::out_param_ptr<PSECURITY_DESCRIPTOR*>(sd));
|
||||||
THROW_IF_WIN32_ERROR(status);
|
THROW_IF_WIN32_ERROR(status);
|
||||||
|
|
||||||
PEXPLICIT_ACCESS pEA{ nullptr };
|
wil::unique_any_psid psidAdmins{ nullptr };
|
||||||
DWORD count = 0;
|
THROW_IF_WIN32_BOOL_FALSE(
|
||||||
status = GetExplicitEntriesFromAcl(pAcl, &count, &pEA);
|
ConvertStringSidToSidW(L"BA", wil::out_param_ptr<PSID*>(psidAdmins)));
|
||||||
THROW_IF_WIN32_ERROR(status);
|
|
||||||
|
|
||||||
auto explicitAccessCleanup = wil::scope_exit([&]() { ::LocalFree(pEA); });
|
// Compare the owner SID to the administrators SID via
|
||||||
|
// EqualSid(psidOwner, psidAdmins). This does a low-level memory
|
||||||
if (count != 2)
|
// comparison of the SIDs.
|
||||||
{
|
return EqualSid(psidOwner, psidAdmins.get());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, get the Everyone and Admins SIDS so we can make sure they're
|
|
||||||
// the ones in this file.
|
|
||||||
|
|
||||||
wil::unique_sid everyoneSid;
|
|
||||||
wil::unique_sid adminGroupSid;
|
|
||||||
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
|
|
||||||
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
|
|
||||||
|
|
||||||
// Create a SID for the BUILTIN\Administrators group.
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroupSid));
|
|
||||||
|
|
||||||
// Create a well-known SID for the Everyone group.
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid));
|
|
||||||
|
|
||||||
bool hadExpectedPermissions = true;
|
|
||||||
|
|
||||||
// Check that the permissions are what we'd expect them to be if only
|
|
||||||
// admins can write to the file. This is basically a mirror of what we
|
|
||||||
// set up in `WriteUTF8File`.
|
|
||||||
|
|
||||||
// For grfAccessPermissions, GENERIC_ALL turns into STANDARD_RIGHTS_ALL,
|
|
||||||
// and GENERIC_READ -> READ_CONTROL
|
|
||||||
hadExpectedPermissions &= WI_AreAllFlagsSet(pEA[0].grfAccessPermissions, STANDARD_RIGHTS_ALL);
|
|
||||||
hadExpectedPermissions &= pEA[0].grfInheritance == NO_INHERITANCE;
|
|
||||||
hadExpectedPermissions &= pEA[0].Trustee.TrusteeForm == TRUSTEE_IS_SID;
|
|
||||||
// SIDs are void*'s that happen to convert to a wchar_t
|
|
||||||
hadExpectedPermissions &= *(pEA[0].Trustee.ptstrName) == *(LPWSTR)(adminGroupSid.get());
|
|
||||||
|
|
||||||
// Now check the other EXPLICIT_ACCESS
|
|
||||||
hadExpectedPermissions &= WI_IsFlagSet(pEA[1].grfAccessPermissions, READ_CONTROL);
|
|
||||||
hadExpectedPermissions &= pEA[1].grfInheritance == NO_INHERITANCE;
|
|
||||||
hadExpectedPermissions &= pEA[1].Trustee.TrusteeForm == TRUSTEE_IS_SID;
|
|
||||||
hadExpectedPermissions &= *(pEA[1].Trustee.ptstrName) == *(LPWSTR)(everyoneSid.get());
|
|
||||||
|
|
||||||
return hadExpectedPermissions;
|
|
||||||
}
|
}
|
||||||
// Tries to read a file somewhat atomically without locking it.
|
// Tries to read a file somewhat atomically without locking it.
|
||||||
// Strips the UTF8 BOM if it exists.
|
// Strips the UTF8 BOM if it exists.
|
||||||
|
@ -114,7 +87,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
{
|
{
|
||||||
if (elevatedOnly)
|
if (elevatedOnly)
|
||||||
{
|
{
|
||||||
const bool hadExpectedPermissions{ _hasExpectedPermissions(path) };
|
const bool hadExpectedPermissions{ _hasElevatedOnlyPermissions(path) };
|
||||||
if (!hadExpectedPermissions)
|
if (!hadExpectedPermissions)
|
||||||
{
|
{
|
||||||
// delete the file. It's been compromised.
|
// delete the file. It's been compromised.
|
||||||
|
@ -192,61 +165,56 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
const bool elevatedOnly)
|
const bool elevatedOnly)
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
// stash the security descriptor here, so it will stay in context until
|
||||||
|
// after the call to CreateFile. If it gets cleaned up before that, then
|
||||||
|
// CreateFile will fail
|
||||||
|
wil::unique_hlocal_security_descriptor sd;
|
||||||
if (elevatedOnly)
|
if (elevatedOnly)
|
||||||
{
|
{
|
||||||
// This is very vaguely taken from
|
// Initialize the security descriptor so only admins can write the
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c--
|
// file. We'll initialize the SECURITY_DESCRIPTOR with a
|
||||||
// With using https://docs.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
|
// single entry (ACE) -- a mandatory label (i.e. a
|
||||||
// to find out that
|
// LABEL_SECURITY_INFORMATION) that sets the file integrity level to
|
||||||
// * SECURITY_NT_AUTHORITY+SECURITY_LOCAL_SYSTEM_RID == NT AUTHORITY\SYSTEM
|
// "high", with a no-write-up policy.
|
||||||
// * SECURITY_NT_AUTHORITY+SECURITY_BUILTIN_DOMAIN_RID+DOMAIN_ALIAS_RID_ADMINS == BUILTIN\Administrators
|
|
||||||
// * SECURITY_WORLD_SID_AUTHORITY+SECURITY_WORLD_RID == Everyone
|
|
||||||
//
|
//
|
||||||
// Raymond Chen recommended that I make this file only writable by
|
// When accessed from a security context at a lower integrity level,
|
||||||
// SYSTEM, but if I did that, then even we can't write the file
|
// the no-write-up policy filters out rights that aren't in the
|
||||||
// while elevated, which isn't what we want.
|
// object type's generic read and execute set (for the file type,
|
||||||
|
// that's FILE_GENERIC_READ | FILE_GENERIC_EXECUTE).
|
||||||
|
//
|
||||||
|
// Another option we considered here was manually setting the ACLs
|
||||||
|
// on this file such that Builtin\Admins could read&write the file,
|
||||||
|
// and all users could only read.
|
||||||
|
//
|
||||||
|
// Big thanks to @eryksun in GH#11222 for helping with this. This
|
||||||
|
// alternative method was chosen because it's considerably simpler.
|
||||||
|
|
||||||
wil::unique_sid everyoneSid;
|
// The required security descriptor can be created easily from the
|
||||||
wil::unique_sid adminGroupSid;
|
// SDDL string: "S:(ML;;NW;;;HI)"
|
||||||
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
|
// (i.e. SACL:mandatory label;;no write up;;;high integrity level)
|
||||||
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
|
unsigned long cb;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(
|
||||||
// Create a SID for the BUILTIN\Administrators group.
|
ConvertStringSecurityDescriptorToSecurityDescriptor(L"S:(ML;;NW;;;HI)",
|
||||||
THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroupSid));
|
SDDL_REVISION_1,
|
||||||
|
wil::out_param_ptr<PSECURITY_DESCRIPTOR*>(sd),
|
||||||
// Create a well-known SID for the Everyone group.
|
&cb));
|
||||||
THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid));
|
|
||||||
|
|
||||||
EXPLICIT_ACCESS ea[2]{};
|
|
||||||
|
|
||||||
// Grant Admins all permissions on this file
|
|
||||||
ea[0].grfAccessPermissions = GENERIC_ALL;
|
|
||||||
ea[0].grfAccessMode = SET_ACCESS;
|
|
||||||
ea[0].grfInheritance = NO_INHERITANCE;
|
|
||||||
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
|
||||||
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
|
||||||
ea[0].Trustee.ptstrName = (LPWSTR)(adminGroupSid.get());
|
|
||||||
|
|
||||||
// Grant Everyone the permission or read this file
|
|
||||||
ea[1].grfAccessPermissions = GENERIC_READ;
|
|
||||||
ea[1].grfAccessMode = SET_ACCESS;
|
|
||||||
ea[1].grfInheritance = NO_INHERITANCE;
|
|
||||||
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
|
||||||
ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
|
||||||
ea[1].Trustee.ptstrName = (LPWSTR)(everyoneSid.get());
|
|
||||||
|
|
||||||
ACL acl;
|
|
||||||
PACL pAcl = &acl;
|
|
||||||
THROW_IF_WIN32_ERROR(SetEntriesInAcl(2, ea, nullptr, &pAcl));
|
|
||||||
|
|
||||||
SECURITY_DESCRIPTOR sd;
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(SetSecurityDescriptorDacl(&sd, true, pAcl, false));
|
|
||||||
|
|
||||||
// Initialize a security attributes structure.
|
// Initialize a security attributes structure.
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
sa.lpSecurityDescriptor = &sd;
|
sa.lpSecurityDescriptor = sd.get();
|
||||||
sa.bInheritHandle = false;
|
sa.bInheritHandle = false;
|
||||||
|
|
||||||
|
// If we're running in an elevated context, when this file is
|
||||||
|
// created, it will automatically be owned by
|
||||||
|
// Builtin\Administrators, which will pass the above
|
||||||
|
// _hasElevatedOnlyPermissions check.
|
||||||
|
//
|
||||||
|
// Programs running in an elevated context will be free to write the
|
||||||
|
// file, and unelevated processes will be able to read the file. An
|
||||||
|
// unelevated process could always delete the file and rename a new
|
||||||
|
// file in it's place (a la the way `vim.exe` saves files), but if
|
||||||
|
// they do that, the new file _won't_ be owned by Administrators,
|
||||||
|
// failing the above check.
|
||||||
}
|
}
|
||||||
|
|
||||||
wil::unique_hfile file{ CreateFileW(path.c_str(),
|
wil::unique_hfile file{ CreateFileW(path.c_str(),
|
||||||
|
|
|
@ -12,11 +12,6 @@ using namespace Microsoft::Terminal::Settings::Model;
|
||||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||||
|
|
||||||
static constexpr std::string_view FontInfoKey{ "font" };
|
static constexpr std::string_view FontInfoKey{ "font" };
|
||||||
static constexpr std::string_view FontFaceKey{ "face" };
|
|
||||||
static constexpr std::string_view FontSizeKey{ "size" };
|
|
||||||
static constexpr std::string_view FontWeightKey{ "weight" };
|
|
||||||
static constexpr std::string_view FontFeaturesKey{ "features" };
|
|
||||||
static constexpr std::string_view FontAxesKey{ "axes" };
|
|
||||||
static constexpr std::string_view LegacyFontFaceKey{ "fontFace" };
|
static constexpr std::string_view LegacyFontFaceKey{ "fontFace" };
|
||||||
static constexpr std::string_view LegacyFontSizeKey{ "fontSize" };
|
static constexpr std::string_view LegacyFontSizeKey{ "fontSize" };
|
||||||
static constexpr std::string_view LegacyFontWeightKey{ "fontWeight" };
|
static constexpr std::string_view LegacyFontWeightKey{ "fontWeight" };
|
||||||
|
@ -29,11 +24,12 @@ winrt::Microsoft::Terminal::Settings::Model::implementation::FontConfig::FontCon
|
||||||
winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||||
{
|
{
|
||||||
auto fontInfo{ winrt::make_self<FontConfig>(std::move(sourceProfile)) };
|
auto fontInfo{ winrt::make_self<FontConfig>(std::move(sourceProfile)) };
|
||||||
fontInfo->_FontFace = source->_FontFace;
|
|
||||||
fontInfo->_FontSize = source->_FontSize;
|
#define FONT_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||||
fontInfo->_FontWeight = source->_FontWeight;
|
fontInfo->_##name = source->_##name;
|
||||||
fontInfo->_FontAxes = source->_FontAxes;
|
MTSM_FONT_SETTINGS(FONT_SETTINGS_COPY)
|
||||||
fontInfo->_FontFeatures = source->_FontFeatures;
|
#undef FONT_SETTINGS_COPY
|
||||||
|
|
||||||
return fontInfo;
|
return fontInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +37,10 @@ Json::Value FontConfig::ToJson() const
|
||||||
{
|
{
|
||||||
Json::Value json{ Json::ValueType::objectValue };
|
Json::Value json{ Json::ValueType::objectValue };
|
||||||
|
|
||||||
JsonUtils::SetValueForKey(json, FontFaceKey, _FontFace);
|
#define FONT_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||||
JsonUtils::SetValueForKey(json, FontSizeKey, _FontSize);
|
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||||
JsonUtils::SetValueForKey(json, FontWeightKey, _FontWeight);
|
MTSM_FONT_SETTINGS(FONT_SETTINGS_TO_JSON)
|
||||||
JsonUtils::SetValueForKey(json, FontAxesKey, _FontAxes);
|
#undef FONT_SETTINGS_TO_JSON
|
||||||
JsonUtils::SetValueForKey(json, FontFeaturesKey, _FontFeatures);
|
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -69,11 +64,10 @@ void FontConfig::LayerJson(const Json::Value& json)
|
||||||
{
|
{
|
||||||
// A font object is defined, use that
|
// A font object is defined, use that
|
||||||
const auto fontInfoJson = json[JsonKey(FontInfoKey)];
|
const auto fontInfoJson = json[JsonKey(FontInfoKey)];
|
||||||
JsonUtils::GetValueForKey(fontInfoJson, FontFaceKey, _FontFace);
|
#define FONT_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||||
JsonUtils::GetValueForKey(fontInfoJson, FontSizeKey, _FontSize);
|
JsonUtils::GetValueForKey(fontInfoJson, jsonKey, _##name);
|
||||||
JsonUtils::GetValueForKey(fontInfoJson, FontWeightKey, _FontWeight);
|
MTSM_FONT_SETTINGS(FONT_SETTINGS_LAYER_JSON)
|
||||||
JsonUtils::GetValueForKey(fontInfoJson, FontFeaturesKey, _FontFeatures);
|
#undef FONT_SETTINGS_LAYER_JSON
|
||||||
JsonUtils::GetValueForKey(fontInfoJson, FontAxesKey, _FontAxes);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ Author(s):
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "FontConfig.g.h"
|
#include "FontConfig.g.h"
|
||||||
#include "JsonUtils.h"
|
#include "JsonUtils.h"
|
||||||
|
#include "MTSMSettings.h"
|
||||||
#include "../inc/cppwinrt_utils.h"
|
#include "../inc/cppwinrt_utils.h"
|
||||||
#include "IInheritable.h"
|
#include "IInheritable.h"
|
||||||
#include <DefaultSettings.h>
|
#include <DefaultSettings.h>
|
||||||
|
@ -39,11 +40,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
Model::Profile SourceProfile();
|
Model::Profile SourceProfile();
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::FontConfig, hstring, FontFace, DEFAULT_FONT_FACE);
|
#define FONT_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||||
INHERITABLE_SETTING(Model::FontConfig, int32_t, FontSize, DEFAULT_FONT_SIZE);
|
INHERITABLE_SETTING(Model::FontConfig, type, name, ##__VA_ARGS__)
|
||||||
INHERITABLE_SETTING(Model::FontConfig, Windows::UI::Text::FontWeight, FontWeight, DEFAULT_FONT_WEIGHT);
|
MTSM_FONT_SETTINGS(FONT_SETTINGS_INITIALIZE)
|
||||||
INHERITABLE_SETTING(Model::FontConfig, IFontAxesMap, FontAxes);
|
#undef FONT_SETTINGS_INITIALIZE
|
||||||
INHERITABLE_SETTING(Model::FontConfig, IFontFeatureMap, FontFeatures);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
winrt::weak_ref<Profile> _sourceProfile;
|
winrt::weak_ref<Profile> _sourceProfile;
|
||||||
|
|
|
@ -18,48 +18,7 @@ using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||||
static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" };
|
static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" };
|
||||||
static constexpr std::string_view ActionsKey{ "actions" };
|
static constexpr std::string_view ActionsKey{ "actions" };
|
||||||
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
|
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
|
||||||
static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" };
|
|
||||||
static constexpr std::string_view InitialRowsKey{ "initialRows" };
|
|
||||||
static constexpr std::string_view InitialColsKey{ "initialCols" };
|
|
||||||
static constexpr std::string_view InitialPositionKey{ "initialPosition" };
|
|
||||||
static constexpr std::string_view CenterOnLaunchKey{ "centerOnLaunch" };
|
|
||||||
static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" };
|
|
||||||
static constexpr std::string_view LanguageKey{ "language" };
|
|
||||||
static constexpr std::string_view ThemeKey{ "theme" };
|
|
||||||
static constexpr std::string_view TabWidthModeKey{ "tabWidthMode" };
|
|
||||||
static constexpr std::string_view UseAcrylicInTabRowKey{ "useAcrylicInTabRow" };
|
|
||||||
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
|
|
||||||
static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" };
|
|
||||||
static constexpr std::string_view InputServiceWarningKey{ "inputServiceWarning" };
|
|
||||||
static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" };
|
|
||||||
static constexpr std::string_view CopyFormattingKey{ "copyFormatting" };
|
|
||||||
static constexpr std::string_view WarnAboutLargePasteKey{ "largePasteWarning" };
|
|
||||||
static constexpr std::string_view WarnAboutMultiLinePasteKey{ "multiLinePasteWarning" };
|
|
||||||
static constexpr std::string_view TrimPasteKey{ "trimPaste" };
|
|
||||||
static constexpr std::string_view LaunchModeKey{ "launchMode" };
|
|
||||||
static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" };
|
|
||||||
static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" };
|
|
||||||
static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" };
|
|
||||||
static constexpr std::string_view FirstWindowPreferenceKey{ "firstWindowPreference" };
|
|
||||||
static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" };
|
|
||||||
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
|
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
|
||||||
static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" };
|
|
||||||
static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" };
|
|
||||||
static constexpr std::string_view StartupActionsKey{ "startupActions" };
|
|
||||||
static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" };
|
|
||||||
static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" };
|
|
||||||
static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
|
|
||||||
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
|
|
||||||
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
|
|
||||||
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
|
|
||||||
static constexpr std::string_view ShowAdminShieldKey{ "showAdminShield" };
|
|
||||||
|
|
||||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
|
||||||
|
|
||||||
static constexpr std::string_view ForceFullRepaintRenderingKey{ "experimental.rendering.forceFullRepaint" };
|
|
||||||
static constexpr std::string_view SoftwareRenderingKey{ "experimental.rendering.software" };
|
|
||||||
static constexpr std::string_view ForceVTInputKey{ "experimental.input.forceVT" };
|
|
||||||
static constexpr std::string_view DetectURLsKey{ "experimental.detectURLs" };
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Copies any extraneous data from the parent before completing a CreateChild call
|
// - Copies any extraneous data from the parent before completing a CreateChild call
|
||||||
|
@ -86,45 +45,6 @@ void GlobalAppSettings::_FinalizeInheritance()
|
||||||
winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||||
{
|
{
|
||||||
auto globals{ winrt::make_self<GlobalAppSettings>() };
|
auto globals{ winrt::make_self<GlobalAppSettings>() };
|
||||||
globals->_InitialRows = _InitialRows;
|
|
||||||
globals->_InitialCols = _InitialCols;
|
|
||||||
globals->_AlwaysShowTabs = _AlwaysShowTabs;
|
|
||||||
globals->_ShowTitleInTitlebar = _ShowTitleInTitlebar;
|
|
||||||
globals->_ConfirmCloseAllTabs = _ConfirmCloseAllTabs;
|
|
||||||
globals->_Language = _Language;
|
|
||||||
globals->_Theme = _Theme;
|
|
||||||
globals->_TabWidthMode = _TabWidthMode;
|
|
||||||
globals->_UseAcrylicInTabRow = _UseAcrylicInTabRow;
|
|
||||||
globals->_ShowTabsInTitlebar = _ShowTabsInTitlebar;
|
|
||||||
globals->_WordDelimiters = _WordDelimiters;
|
|
||||||
globals->_InputServiceWarning = _InputServiceWarning;
|
|
||||||
globals->_CopyOnSelect = _CopyOnSelect;
|
|
||||||
globals->_CopyFormatting = _CopyFormatting;
|
|
||||||
globals->_WarnAboutLargePaste = _WarnAboutLargePaste;
|
|
||||||
globals->_WarnAboutMultiLinePaste = _WarnAboutMultiLinePaste;
|
|
||||||
globals->_TrimPaste = _TrimPaste;
|
|
||||||
globals->_InitialPosition = _InitialPosition;
|
|
||||||
globals->_CenterOnLaunch = _CenterOnLaunch;
|
|
||||||
globals->_LaunchMode = _LaunchMode;
|
|
||||||
globals->_SnapToGridOnResize = _SnapToGridOnResize;
|
|
||||||
globals->_ForceFullRepaintRendering = _ForceFullRepaintRendering;
|
|
||||||
globals->_SoftwareRendering = _SoftwareRendering;
|
|
||||||
globals->_ForceVTInput = _ForceVTInput;
|
|
||||||
globals->_DebugFeaturesEnabled = _DebugFeaturesEnabled;
|
|
||||||
globals->_StartOnUserLogin = _StartOnUserLogin;
|
|
||||||
globals->_FirstWindowPreference = _FirstWindowPreference;
|
|
||||||
globals->_AlwaysOnTop = _AlwaysOnTop;
|
|
||||||
globals->_TabSwitcherMode = _TabSwitcherMode;
|
|
||||||
globals->_DisableAnimations = _DisableAnimations;
|
|
||||||
globals->_StartupActions = _StartupActions;
|
|
||||||
globals->_FocusFollowMouse = _FocusFollowMouse;
|
|
||||||
globals->_WindowingBehavior = _WindowingBehavior;
|
|
||||||
globals->_TrimBlockSelection = _TrimBlockSelection;
|
|
||||||
globals->_DetectURLs = _DetectURLs;
|
|
||||||
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
|
|
||||||
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
|
|
||||||
globals->_DisabledProfileSources = _DisabledProfileSources;
|
|
||||||
globals->_ShowAdminShield = _ShowAdminShield;
|
|
||||||
|
|
||||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||||
|
|
||||||
|
@ -132,6 +52,11 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||||
globals->_actionMap = _actionMap->Copy();
|
globals->_actionMap = _actionMap->Copy();
|
||||||
globals->_keybindingsWarnings = _keybindingsWarnings;
|
globals->_keybindingsWarnings = _keybindingsWarnings;
|
||||||
|
|
||||||
|
#define GLOBAL_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||||
|
globals->_##name = _##name;
|
||||||
|
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_COPY)
|
||||||
|
#undef GLOBAL_SETTINGS_COPY
|
||||||
|
|
||||||
if (_colorSchemes)
|
if (_colorSchemes)
|
||||||
{
|
{
|
||||||
for (auto kv : _colorSchemes)
|
for (auto kv : _colorSchemes)
|
||||||
|
@ -189,51 +114,15 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::FromJson(const Json::Value&
|
||||||
void GlobalAppSettings::LayerJson(const Json::Value& json)
|
void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||||
{
|
{
|
||||||
JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
||||||
JsonUtils::GetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs);
|
|
||||||
JsonUtils::GetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs);
|
|
||||||
JsonUtils::GetValueForKey(json, InitialRowsKey, _InitialRows);
|
|
||||||
JsonUtils::GetValueForKey(json, InitialColsKey, _InitialCols);
|
|
||||||
JsonUtils::GetValueForKey(json, InitialPositionKey, _InitialPosition);
|
|
||||||
JsonUtils::GetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch);
|
|
||||||
JsonUtils::GetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar);
|
|
||||||
JsonUtils::GetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar);
|
|
||||||
JsonUtils::GetValueForKey(json, WordDelimitersKey, _WordDelimiters);
|
|
||||||
JsonUtils::GetValueForKey(json, CopyOnSelectKey, _CopyOnSelect);
|
|
||||||
JsonUtils::GetValueForKey(json, InputServiceWarningKey, _InputServiceWarning);
|
|
||||||
JsonUtils::GetValueForKey(json, CopyFormattingKey, _CopyFormatting);
|
|
||||||
JsonUtils::GetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste);
|
|
||||||
JsonUtils::GetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste);
|
|
||||||
JsonUtils::GetValueForKey(json, TrimPasteKey, _TrimPaste);
|
|
||||||
JsonUtils::GetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference);
|
|
||||||
JsonUtils::GetValueForKey(json, LaunchModeKey, _LaunchMode);
|
|
||||||
JsonUtils::GetValueForKey(json, LanguageKey, _Language);
|
|
||||||
JsonUtils::GetValueForKey(json, ThemeKey, _Theme);
|
|
||||||
JsonUtils::GetValueForKey(json, TabWidthModeKey, _TabWidthMode);
|
|
||||||
JsonUtils::GetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow);
|
|
||||||
JsonUtils::GetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
|
||||||
// GetValueForKey will only override the current value if the key exists
|
|
||||||
JsonUtils::GetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
|
||||||
JsonUtils::GetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
|
||||||
JsonUtils::GetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering);
|
|
||||||
JsonUtils::GetValueForKey(json, ForceVTInputKey, _ForceVTInput);
|
|
||||||
JsonUtils::GetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin);
|
|
||||||
JsonUtils::GetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop);
|
|
||||||
// GH#8076 - when adding enum values to this key, we also changed it from
|
// GH#8076 - when adding enum values to this key, we also changed it from
|
||||||
// "useTabSwitcher" to "tabSwitcherMode". Continue supporting
|
// "useTabSwitcher" to "tabSwitcherMode". Continue supporting
|
||||||
// "useTabSwitcher", but prefer "tabSwitcherMode"
|
// "useTabSwitcher", but prefer "tabSwitcherMode"
|
||||||
JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode);
|
JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode);
|
||||||
JsonUtils::GetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode);
|
|
||||||
JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
|
|
||||||
JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions);
|
|
||||||
JsonUtils::GetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse);
|
|
||||||
JsonUtils::GetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
|
||||||
JsonUtils::GetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
|
||||||
JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs);
|
|
||||||
JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
|
||||||
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
|
||||||
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
|
||||||
|
|
||||||
JsonUtils::GetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
|
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||||
|
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||||
|
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_LAYER_JSON)
|
||||||
|
#undef GLOBAL_SETTINGS_LAYER_JSON
|
||||||
|
|
||||||
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
|
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
|
||||||
for (const auto& jsonKey : bindingsKeys)
|
for (const auto& jsonKey : bindingsKeys)
|
||||||
|
@ -293,48 +182,12 @@ Json::Value GlobalAppSettings::ToJson() const
|
||||||
{
|
{
|
||||||
Json::Value json{ Json::ValueType::objectValue };
|
Json::Value json{ Json::ValueType::objectValue };
|
||||||
|
|
||||||
// clang-format off
|
JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
||||||
JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
|
||||||
JsonUtils::SetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs);
|
#define GLOBAL_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||||
JsonUtils::SetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs);
|
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||||
JsonUtils::SetValueForKey(json, InitialRowsKey, _InitialRows);
|
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_TO_JSON)
|
||||||
JsonUtils::SetValueForKey(json, InitialColsKey, _InitialCols);
|
#undef GLOBAL_SETTINGS_TO_JSON
|
||||||
JsonUtils::SetValueForKey(json, InitialPositionKey, _InitialPosition);
|
|
||||||
JsonUtils::SetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch);
|
|
||||||
JsonUtils::SetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar);
|
|
||||||
JsonUtils::SetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar);
|
|
||||||
JsonUtils::SetValueForKey(json, WordDelimitersKey, _WordDelimiters);
|
|
||||||
JsonUtils::SetValueForKey(json, InputServiceWarningKey, _InputServiceWarning);
|
|
||||||
JsonUtils::SetValueForKey(json, CopyOnSelectKey, _CopyOnSelect);
|
|
||||||
JsonUtils::SetValueForKey(json, CopyFormattingKey, _CopyFormatting);
|
|
||||||
JsonUtils::SetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste);
|
|
||||||
JsonUtils::SetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste);
|
|
||||||
JsonUtils::SetValueForKey(json, TrimPasteKey, _TrimPaste);
|
|
||||||
JsonUtils::SetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference);
|
|
||||||
JsonUtils::SetValueForKey(json, LaunchModeKey, _LaunchMode);
|
|
||||||
JsonUtils::SetValueForKey(json, LanguageKey, _Language);
|
|
||||||
JsonUtils::SetValueForKey(json, ThemeKey, _Theme);
|
|
||||||
JsonUtils::SetValueForKey(json, TabWidthModeKey, _TabWidthMode);
|
|
||||||
JsonUtils::SetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow);
|
|
||||||
JsonUtils::SetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
|
||||||
JsonUtils::SetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
|
||||||
JsonUtils::SetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
|
||||||
JsonUtils::SetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering);
|
|
||||||
JsonUtils::SetValueForKey(json, ForceVTInputKey, _ForceVTInput);
|
|
||||||
JsonUtils::SetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin);
|
|
||||||
JsonUtils::SetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop);
|
|
||||||
JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode);
|
|
||||||
JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
|
|
||||||
JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions);
|
|
||||||
JsonUtils::SetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse);
|
|
||||||
JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
|
||||||
JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
|
||||||
JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs);
|
|
||||||
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
|
||||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
|
||||||
JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
|
||||||
JsonUtils::SetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
||||||
return json;
|
return json;
|
||||||
|
|
|
@ -17,6 +17,7 @@ Author(s):
|
||||||
|
|
||||||
#include "GlobalAppSettings.g.h"
|
#include "GlobalAppSettings.g.h"
|
||||||
#include "IInheritable.h"
|
#include "IInheritable.h"
|
||||||
|
#include "MTSMSettings.h"
|
||||||
|
|
||||||
#include "ActionMap.h"
|
#include "ActionMap.h"
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
@ -61,46 +62,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
DisableAnimations(!invertedDisableAnimationsValue);
|
DisableAnimations(!invertedDisableAnimationsValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialRows, DEFAULT_ROWS);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialCols, DEFAULT_COLS);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowTabs, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTitleInTitlebar, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ConfirmCloseAllTabs, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, Language);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::UI::Xaml::ElementTheme, Theme, winrt::Windows::UI::Xaml::ElementTheme::Default);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, UseAcrylicInTabRow, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTabsInTitlebar, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CopyOnSelect, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, InputServiceWarning, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutLargePaste, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutMultiLinePaste, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimPaste, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchPosition, InitialPosition, nullptr, nullptr);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CenterOnLaunch, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::FirstWindowPreference, FirstWindowPreference, FirstWindowPreference::DefaultProfile);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchMode, LaunchMode, LaunchMode::DefaultMode);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SnapToGridOnResize, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceFullRepaintRendering, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SoftwareRendering, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceVTInput, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DebugFeaturesEnabled, debugFeaturesDefault);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, StartOnUserLogin, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysOnTop, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DisableAnimations, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, StartupActions, L"");
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, FocusFollowMouse, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::WindowingMode, WindowingBehavior, Model::WindowingMode::UseNew);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimBlockSelection, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr);
|
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
|
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
|
||||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowAdminShield, true);
|
|
||||||
|
#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||||
|
INHERITABLE_SETTING(Model::GlobalAppSettings, type, name, ##__VA_ARGS__)
|
||||||
|
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_INITIALIZE)
|
||||||
|
#undef GLOBAL_SETTINGS_INITIALIZE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
|
97
src/cascadia/TerminalSettingsModel/MTSMSettings.h
Normal file
97
src/cascadia/TerminalSettingsModel/MTSMSettings.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
- MTSMSettings.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- Contains most of the settings within Terminal Settings Model (global, profile, font, appearance)
|
||||||
|
- To add a new setting to any one of those classes, simply add it to the respective list below, following the macro format
|
||||||
|
|
||||||
|
Author(s):
|
||||||
|
- Pankaj Bhojwani - October 2021
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Macro format (defaultArgs are optional):
|
||||||
|
// (type, name, jsonKey, defaultArgs)
|
||||||
|
|
||||||
|
#define MTSM_GLOBAL_SETTINGS(X) \
|
||||||
|
X(int32_t, InitialRows, "initialRows", 30) \
|
||||||
|
X(int32_t, InitialCols, "initialCols", 80) \
|
||||||
|
X(hstring, WordDelimiters, "wordDelimiters", DEFAULT_WORD_DELIMITERS) \
|
||||||
|
X(bool, CopyOnSelect, "copyOnSelect", false) \
|
||||||
|
X(bool, FocusFollowMouse, "focusFollowMouse", false) \
|
||||||
|
X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \
|
||||||
|
X(bool, SoftwareRendering, "experimental.rendering.software", false) \
|
||||||
|
X(bool, ForceVTInput, "experimental.input.forceVT", false) \
|
||||||
|
X(bool, TrimBlockSelection, "trimBlockSelection", false) \
|
||||||
|
X(bool, DetectURLs, "experimental.detectURLs", true) \
|
||||||
|
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
|
||||||
|
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
|
||||||
|
X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \
|
||||||
|
X(hstring, Language, "language") \
|
||||||
|
X(winrt::Windows::UI::Xaml::ElementTheme, Theme, "theme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
|
||||||
|
X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \
|
||||||
|
X(bool, UseAcrylicInTabRow, "useAcrylicInTabRow", false) \
|
||||||
|
X(bool, ShowTabsInTitlebar, "showTabsInTitlebar", true) \
|
||||||
|
X(bool, InputServiceWarning, "inputServiceWarning", true) \
|
||||||
|
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, "copyFormatting", 0) \
|
||||||
|
X(bool, WarnAboutLargePaste, "largePasteWarning", true) \
|
||||||
|
X(bool, WarnAboutMultiLinePaste, "multiLinePasteWarning", true) \
|
||||||
|
X(Model::LaunchPosition, InitialPosition, "initialPosition", nullptr, nullptr) \
|
||||||
|
X(bool, CenterOnLaunch, "centerOnLaunch", false) \
|
||||||
|
X(Model::FirstWindowPreference, FirstWindowPreference, "firstWindowPreference", FirstWindowPreference::DefaultProfile) \
|
||||||
|
X(Model::LaunchMode, LaunchMode, "launchMode", LaunchMode::DefaultMode) \
|
||||||
|
X(bool, SnapToGridOnResize, "snapToGridOnResize", true) \
|
||||||
|
X(bool, DebugFeaturesEnabled, "debugFeatures", debugFeaturesDefault) \
|
||||||
|
X(bool, StartOnUserLogin, "startOnUserLogin", false) \
|
||||||
|
X(bool, AlwaysOnTop, "alwaysOnTop", false) \
|
||||||
|
X(Model::TabSwitcherMode, TabSwitcherMode, "tabSwitcherMode", Model::TabSwitcherMode::InOrder) \
|
||||||
|
X(bool, DisableAnimations, "disableAnimations", false) \
|
||||||
|
X(hstring, StartupActions, "startupActions", L"") \
|
||||||
|
X(Model::WindowingMode, WindowingBehavior, "windowingBehavior", Model::WindowingMode::UseNew) \
|
||||||
|
X(bool, MinimizeToNotificationArea, "minimizeToNotificationArea", false) \
|
||||||
|
X(bool, AlwaysShowNotificationIcon, "alwaysShowNotificationIcon", false) \
|
||||||
|
X(winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, "disabledProfileSources", nullptr) \
|
||||||
|
X(bool, ShowAdminShield, "showAdminShield", true) \
|
||||||
|
X(bool, TrimPaste, "trimPaste", true)
|
||||||
|
|
||||||
|
#define MTSM_PROFILE_SETTINGS(X) \
|
||||||
|
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
|
||||||
|
X(bool, SnapOnInput, "snapOnInput", true) \
|
||||||
|
X(bool, AltGrAliasing, "altGrAliasing", true) \
|
||||||
|
X(bool, UseAcrylic, "useAcrylic", false) \
|
||||||
|
X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \
|
||||||
|
X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||||
|
X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||||
|
X(hstring, StartingDirectory, "startingDirectory") \
|
||||||
|
X(bool, SuppressApplicationTitle, "suppressApplicationTitle", false) \
|
||||||
|
X(guid, ConnectionType, "connectionType") \
|
||||||
|
X(hstring, Icon, "icon", L"\uE756") \
|
||||||
|
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \
|
||||||
|
X(hstring, TabTitle, "tabTitle") \
|
||||||
|
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
|
||||||
|
X(bool, Elevate, "elevate", false)
|
||||||
|
|
||||||
|
#define MTSM_FONT_SETTINGS(X) \
|
||||||
|
X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \
|
||||||
|
X(int32_t, FontSize, "size", DEFAULT_FONT_SIZE) \
|
||||||
|
X(winrt::Windows::UI::Text::FontWeight, FontWeight, "weight", DEFAULT_FONT_WEIGHT) \
|
||||||
|
X(IFontAxesMap, FontAxes, "axes") \
|
||||||
|
X(IFontFeatureMap, FontFeatures, "features")
|
||||||
|
|
||||||
|
#define MTSM_APPEARANCE_SETTINGS(X) \
|
||||||
|
X(Core::CursorStyle, CursorShape, "cursorShape", Core::CursorStyle::Bar) \
|
||||||
|
X(uint32_t, CursorHeight, "cursorHeight", DEFAULT_CURSOR_HEIGHT) \
|
||||||
|
X(double, BackgroundImageOpacity, "backgroundImageOpacity", 1.0) \
|
||||||
|
X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, "backgroundImageStretchMode", winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \
|
||||||
|
X(bool, RetroTerminalEffect, "experimental.retroTerminalEffect", false) \
|
||||||
|
X(hstring, PixelShaderPath, "experimental.pixelShaderPath") \
|
||||||
|
X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center) \
|
||||||
|
X(hstring, ColorSchemeName, "colorScheme", L"Campbell") \
|
||||||
|
X(hstring, BackgroundImagePath, "backgroundImage") \
|
||||||
|
X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \
|
||||||
|
X(bool, AdjustIndistinguishableColors, "adjustIndistinguishableColors", true)
|
|
@ -50,6 +50,7 @@
|
||||||
<DependentUpon>GlobalAppSettings.idl</DependentUpon>
|
<DependentUpon>GlobalAppSettings.idl</DependentUpon>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="IInheritable.h" />
|
<ClInclude Include="IInheritable.h" />
|
||||||
|
<ClInclude Include="MTSMSettings.h" />
|
||||||
<ClInclude Include="IDynamicProfileGenerator.h" />
|
<ClInclude Include="IDynamicProfileGenerator.h" />
|
||||||
<ClInclude Include="JsonUtils.h" />
|
<ClInclude Include="JsonUtils.h" />
|
||||||
<ClInclude Include="HashUtils.h" />
|
<ClInclude Include="HashUtils.h" />
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
<Filter>json</Filter>
|
<Filter>json</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="IInheritable.h" />
|
<ClInclude Include="IInheritable.h" />
|
||||||
|
<ClInclude Include="MTSMSettings.h" />
|
||||||
<ClInclude Include="IconPathConverter.h" />
|
<ClInclude Include="IconPathConverter.h" />
|
||||||
<ClInclude Include="DefaultTerminal.h" />
|
<ClInclude Include="DefaultTerminal.h" />
|
||||||
<ClInclude Include="FileUtils.h" />
|
<ClInclude Include="FileUtils.h" />
|
||||||
|
|
|
@ -26,24 +26,9 @@ static constexpr std::string_view GuidKey{ "guid" };
|
||||||
static constexpr std::string_view SourceKey{ "source" };
|
static constexpr std::string_view SourceKey{ "source" };
|
||||||
static constexpr std::string_view HiddenKey{ "hidden" };
|
static constexpr std::string_view HiddenKey{ "hidden" };
|
||||||
|
|
||||||
static constexpr std::string_view TabTitleKey{ "tabTitle" };
|
|
||||||
static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" };
|
|
||||||
static constexpr std::string_view HistorySizeKey{ "historySize" };
|
|
||||||
static constexpr std::string_view SnapOnInputKey{ "snapOnInput" };
|
|
||||||
static constexpr std::string_view AltGrAliasingKey{ "altGrAliasing" };
|
|
||||||
|
|
||||||
static constexpr std::string_view ConnectionTypeKey{ "connectionType" };
|
|
||||||
static constexpr std::string_view CommandlineKey{ "commandline" };
|
|
||||||
static constexpr std::string_view FontInfoKey{ "font" };
|
static constexpr std::string_view FontInfoKey{ "font" };
|
||||||
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
|
|
||||||
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
|
|
||||||
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
|
|
||||||
static constexpr std::string_view PaddingKey{ "padding" };
|
static constexpr std::string_view PaddingKey{ "padding" };
|
||||||
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
|
|
||||||
static constexpr std::string_view IconKey{ "icon" };
|
|
||||||
static constexpr std::string_view AntialiasingModeKey{ "antialiasingMode" };
|
|
||||||
static constexpr std::string_view TabColorKey{ "tabColor" };
|
static constexpr std::string_view TabColorKey{ "tabColor" };
|
||||||
static constexpr std::string_view BellStyleKey{ "bellStyle" };
|
|
||||||
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
|
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
|
||||||
static constexpr std::string_view ElevateKey{ "elevate" };
|
static constexpr std::string_view ElevateKey{ "elevate" };
|
||||||
|
|
||||||
|
@ -118,28 +103,17 @@ winrt::com_ptr<Profile> Profile::CopySettings() const
|
||||||
profile->_Name = _Name;
|
profile->_Name = _Name;
|
||||||
profile->_Source = _Source;
|
profile->_Source = _Source;
|
||||||
profile->_Hidden = _Hidden;
|
profile->_Hidden = _Hidden;
|
||||||
profile->_Icon = _Icon;
|
|
||||||
profile->_CloseOnExit = _CloseOnExit;
|
|
||||||
profile->_TabTitle = _TabTitle;
|
|
||||||
profile->_TabColor = _TabColor;
|
profile->_TabColor = _TabColor;
|
||||||
profile->_SuppressApplicationTitle = _SuppressApplicationTitle;
|
|
||||||
profile->_UseAcrylic = _UseAcrylic;
|
|
||||||
profile->_ScrollState = _ScrollState;
|
|
||||||
profile->_Padding = _Padding;
|
profile->_Padding = _Padding;
|
||||||
profile->_Commandline = _Commandline;
|
|
||||||
profile->_StartingDirectory = _StartingDirectory;
|
|
||||||
profile->_AntialiasingMode = _AntialiasingMode;
|
|
||||||
profile->_ForceFullRepaintRendering = _ForceFullRepaintRendering;
|
|
||||||
profile->_SoftwareRendering = _SoftwareRendering;
|
|
||||||
profile->_HistorySize = _HistorySize;
|
|
||||||
profile->_SnapOnInput = _SnapOnInput;
|
|
||||||
profile->_AltGrAliasing = _AltGrAliasing;
|
|
||||||
profile->_BellStyle = _BellStyle;
|
|
||||||
profile->_ConnectionType = _ConnectionType;
|
|
||||||
profile->_Origin = _Origin;
|
profile->_Origin = _Origin;
|
||||||
profile->_FontInfo = *fontInfo;
|
profile->_FontInfo = *fontInfo;
|
||||||
profile->_DefaultAppearance = *defaultAppearance;
|
profile->_DefaultAppearance = *defaultAppearance;
|
||||||
|
|
||||||
|
#define PROFILE_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||||
|
profile->_##name = _##name;
|
||||||
|
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_COPY)
|
||||||
|
#undef PROFILE_SETTINGS_COPY
|
||||||
|
|
||||||
if (_UnfocusedAppearance)
|
if (_UnfocusedAppearance)
|
||||||
{
|
{
|
||||||
Model::AppearanceConfig unfocused{ nullptr };
|
Model::AppearanceConfig unfocused{ nullptr };
|
||||||
|
@ -197,32 +171,16 @@ void Profile::LayerJson(const Json::Value& json)
|
||||||
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
|
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
|
||||||
JsonUtils::GetValueForKey(json, SourceKey, _Source);
|
JsonUtils::GetValueForKey(json, SourceKey, _Source);
|
||||||
|
|
||||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
|
||||||
JsonUtils::GetValueForKey(json, HistorySizeKey, _HistorySize);
|
|
||||||
JsonUtils::GetValueForKey(json, SnapOnInputKey, _SnapOnInput);
|
|
||||||
JsonUtils::GetValueForKey(json, AltGrAliasingKey, _AltGrAliasing);
|
|
||||||
JsonUtils::GetValueForKey(json, TabTitleKey, _TabTitle);
|
|
||||||
|
|
||||||
// Control Settings
|
|
||||||
JsonUtils::GetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
|
||||||
JsonUtils::GetValueForKey(json, CommandlineKey, _Commandline);
|
|
||||||
JsonUtils::GetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
|
||||||
JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
|
||||||
JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
|
||||||
|
|
||||||
// Padding was never specified as an integer, but it was a common working mistake.
|
// Padding was never specified as an integer, but it was a common working mistake.
|
||||||
// Allow it to be permissive.
|
// Allow it to be permissive.
|
||||||
JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter<hstring, JsonUtils::PermissiveStringConverter<std::wstring>>{});
|
JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter<hstring, JsonUtils::PermissiveStringConverter<std::wstring>>{});
|
||||||
|
|
||||||
JsonUtils::GetValueForKey(json, ScrollbarStateKey, _ScrollState);
|
|
||||||
|
|
||||||
JsonUtils::GetValueForKey(json, StartingDirectoryKey, _StartingDirectory);
|
|
||||||
|
|
||||||
JsonUtils::GetValueForKey(json, IconKey, _Icon);
|
|
||||||
JsonUtils::GetValueForKey(json, AntialiasingModeKey, _AntialiasingMode);
|
|
||||||
JsonUtils::GetValueForKey(json, TabColorKey, _TabColor);
|
JsonUtils::GetValueForKey(json, TabColorKey, _TabColor);
|
||||||
JsonUtils::GetValueForKey(json, BellStyleKey, _BellStyle);
|
|
||||||
JsonUtils::GetValueForKey(json, ElevateKey, _Elevate);
|
#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||||
|
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||||
|
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON)
|
||||||
|
#undef PROFILE_SETTINGS_LAYER_JSON
|
||||||
|
|
||||||
if (json.isMember(JsonKey(UnfocusedAppearanceKey)))
|
if (json.isMember(JsonKey(UnfocusedAppearanceKey)))
|
||||||
{
|
{
|
||||||
|
@ -354,28 +312,15 @@ Json::Value Profile::ToJson() const
|
||||||
JsonUtils::SetValueForKey(json, HiddenKey, writeBasicSettings ? Hidden() : _Hidden);
|
JsonUtils::SetValueForKey(json, HiddenKey, writeBasicSettings ? Hidden() : _Hidden);
|
||||||
JsonUtils::SetValueForKey(json, SourceKey, writeBasicSettings ? Source() : _Source);
|
JsonUtils::SetValueForKey(json, SourceKey, writeBasicSettings ? Source() : _Source);
|
||||||
|
|
||||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
|
||||||
JsonUtils::SetValueForKey(json, HistorySizeKey, _HistorySize);
|
|
||||||
JsonUtils::SetValueForKey(json, SnapOnInputKey, _SnapOnInput);
|
|
||||||
JsonUtils::SetValueForKey(json, AltGrAliasingKey, _AltGrAliasing);
|
|
||||||
JsonUtils::SetValueForKey(json, TabTitleKey, _TabTitle);
|
|
||||||
|
|
||||||
// Control Settings
|
|
||||||
JsonUtils::SetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
|
||||||
JsonUtils::SetValueForKey(json, CommandlineKey, _Commandline);
|
|
||||||
JsonUtils::SetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
|
||||||
JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
|
||||||
JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
|
||||||
|
|
||||||
// PermissiveStringConverter is unnecessary for serialization
|
// PermissiveStringConverter is unnecessary for serialization
|
||||||
JsonUtils::SetValueForKey(json, PaddingKey, _Padding);
|
JsonUtils::SetValueForKey(json, PaddingKey, _Padding);
|
||||||
|
|
||||||
JsonUtils::SetValueForKey(json, ScrollbarStateKey, _ScrollState);
|
|
||||||
JsonUtils::SetValueForKey(json, StartingDirectoryKey, _StartingDirectory);
|
|
||||||
JsonUtils::SetValueForKey(json, IconKey, _Icon);
|
|
||||||
JsonUtils::SetValueForKey(json, AntialiasingModeKey, _AntialiasingMode);
|
|
||||||
JsonUtils::SetValueForKey(json, TabColorKey, _TabColor);
|
JsonUtils::SetValueForKey(json, TabColorKey, _TabColor);
|
||||||
JsonUtils::SetValueForKey(json, BellStyleKey, _BellStyle);
|
|
||||||
|
#define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||||
|
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||||
|
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_TO_JSON)
|
||||||
|
#undef PROFILE_SETTINGS_TO_JSON
|
||||||
|
|
||||||
// Font settings
|
// Font settings
|
||||||
const auto fontInfoImpl = winrt::get_self<FontConfig>(_FontInfo);
|
const auto fontInfoImpl = winrt::get_self<FontConfig>(_FontInfo);
|
||||||
|
|
|
@ -46,6 +46,7 @@ Author(s):
|
||||||
|
|
||||||
#include "Profile.g.h"
|
#include "Profile.g.h"
|
||||||
#include "IInheritable.h"
|
#include "IInheritable.h"
|
||||||
|
#include "MTSMSettings.h"
|
||||||
|
|
||||||
#include "../inc/cppwinrt_utils.h"
|
#include "../inc/cppwinrt_utils.h"
|
||||||
#include "JsonUtils.h"
|
#include "JsonUtils.h"
|
||||||
|
@ -102,44 +103,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
void _FinalizeInheritance() override;
|
void _FinalizeInheritance() override;
|
||||||
|
|
||||||
|
// Special fields
|
||||||
WINRT_PROPERTY(bool, Deleted, false);
|
WINRT_PROPERTY(bool, Deleted, false);
|
||||||
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
|
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
|
||||||
|
|
||||||
WINRT_PROPERTY(guid, Updates);
|
WINRT_PROPERTY(guid, Updates);
|
||||||
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
|
|
||||||
|
// Nullable/optional settings
|
||||||
|
INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr);
|
||||||
|
INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr);
|
||||||
|
|
||||||
|
// Settings that cannot be put in the macro because of how they are handled in ToJson/LayerJson
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default");
|
INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default");
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, Source);
|
INHERITABLE_SETTING(Model::Profile, hstring, Source);
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
|
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
|
||||||
INHERITABLE_SETTING(Model::Profile, guid, ConnectionType);
|
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
|
||||||
|
|
||||||
// Default Icon: Segoe MDL2 CommandPrompt icon
|
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, Icon, L"\uE756");
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, TabTitle);
|
|
||||||
INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, SuppressApplicationTitle, false);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, UseAcrylic, false);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
|
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, Commandline, L"%SystemRoot%\\System32\\cmd.exe");
|
#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||||
INHERITABLE_SETTING(Model::Profile, hstring, StartingDirectory);
|
INHERITABLE_SETTING(Model::Profile, type, name, ##__VA_ARGS__)
|
||||||
|
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_INITIALIZE)
|
||||||
INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
#undef PROFILE_SETTINGS_INITIALIZE
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, ForceFullRepaintRendering, false);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, SoftwareRendering, false);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, SnapOnInput, true);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, AltGrAliasing, true);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, Model::BellStyle, BellStyle, BellStyle::Audible);
|
|
||||||
INHERITABLE_SETTING(Model::Profile, bool, Elevate, false);
|
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
|
Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
|
||||||
|
|
|
@ -74,8 +74,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
INHERITABLE_PROFILE_SETTING(IAppearanceConfig, UnfocusedAppearance);
|
INHERITABLE_PROFILE_SETTING(IAppearanceConfig, UnfocusedAppearance);
|
||||||
|
|
||||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||||
INHERITABLE_PROFILE_SETTING(Boolean, ForceFullRepaintRendering);
|
|
||||||
INHERITABLE_PROFILE_SETTING(Boolean, SoftwareRendering);
|
|
||||||
|
|
||||||
INHERITABLE_PROFILE_SETTING(Int32, HistorySize);
|
INHERITABLE_PROFILE_SETTING(Int32, HistorySize);
|
||||||
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||||
|
|
|
@ -2901,15 +2901,9 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs()
|
||||||
|
|
||||||
auto defaultAttrs = si.GetAttributes();
|
auto defaultAttrs = si.GetAttributes();
|
||||||
auto conhostGreenAttrs = TextAttribute();
|
auto conhostGreenAttrs = TextAttribute();
|
||||||
|
conhostGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
// Conhost and Terminal store attributes in different bits.
|
|
||||||
// conhostGreenAttrs.SetIndexedAttributes(std::nullopt,
|
|
||||||
// { static_cast<BYTE>(FOREGROUND_GREEN) });
|
|
||||||
conhostGreenAttrs.SetIndexedBackground(FOREGROUND_GREEN);
|
|
||||||
auto terminalGreenAttrs = TextAttribute();
|
auto terminalGreenAttrs = TextAttribute();
|
||||||
// terminalGreenAttrs.SetIndexedAttributes(std::nullopt,
|
terminalGreenAttrs.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
// { static_cast<BYTE>(XTERM_GREEN_ATTR) });
|
|
||||||
terminalGreenAttrs.SetIndexedBackground(XTERM_GREEN_ATTR);
|
|
||||||
|
|
||||||
// Use an initial ^[[m to start printing with default-on-default
|
// Use an initial ^[[m to start printing with default-on-default
|
||||||
sm.ProcessString(L"\x1b[m");
|
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) {
|
auto verifyBuffer = [&](const TextBuffer& tb, const til::rectangle viewport, const bool isTerminal, const bool afterResize) {
|
||||||
const auto width = viewport.width<short>();
|
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;
|
const auto greenAttrs = isTerminal ? terminalGreenAttrs : conhostGreenAttrs;
|
||||||
|
|
||||||
for (short row = 0; row < tb.GetSize().Height(); row++)
|
for (short row = 0; row < tb.GetSize().Height(); row++)
|
||||||
|
@ -3034,13 +3028,11 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground()
|
||||||
|
|
||||||
auto defaultAttrs = si.GetAttributes();
|
auto defaultAttrs = si.GetAttributes();
|
||||||
auto conhostBlueAttrs = defaultAttrs;
|
auto conhostBlueAttrs = defaultAttrs;
|
||||||
|
conhostBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
// Conhost and Terminal store attributes in different bits.
|
conhostBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
conhostBlueAttrs.SetIndexedForeground(FOREGROUND_GREEN);
|
|
||||||
conhostBlueAttrs.SetIndexedBackground(FOREGROUND_BLUE);
|
|
||||||
auto terminalBlueAttrs = TextAttribute();
|
auto terminalBlueAttrs = TextAttribute();
|
||||||
terminalBlueAttrs.SetIndexedForeground(XTERM_GREEN_ATTR);
|
terminalBlueAttrs.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
terminalBlueAttrs.SetIndexedBackground(XTERM_BLUE_ATTR);
|
terminalBlueAttrs.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
|
|
||||||
// We're going to print 4 more rows than the entire height of the viewport,
|
// 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
|
// 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 width = viewport.width<short>();
|
||||||
const auto isTerminal = viewport.top() != 0;
|
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;
|
const auto blueAttrs = isTerminal ? terminalBlueAttrs : conhostBlueAttrs;
|
||||||
|
|
||||||
for (short row = 0; row < viewport.bottom<short>() - 2; row++)
|
for (short row = 0; row < viewport.bottom<short>() - 2; row++)
|
||||||
|
|
|
@ -84,6 +84,7 @@ AppHost::AppHost() noexcept :
|
||||||
_window->WindowMoved({ this, &AppHost::_WindowMoved });
|
_window->WindowMoved({ this, &AppHost::_WindowMoved });
|
||||||
_window->HotkeyPressed({ this, &AppHost::_GlobalHotkeyPressed });
|
_window->HotkeyPressed({ this, &AppHost::_GlobalHotkeyPressed });
|
||||||
_window->SetAlwaysOnTop(_logic.GetInitialAlwaysOnTop());
|
_window->SetAlwaysOnTop(_logic.GetInitialAlwaysOnTop());
|
||||||
|
_window->ShouldExitFullscreen({ &_logic, &winrt::TerminalApp::AppLogic::RequestExitFullscreen });
|
||||||
_window->MakeWindow();
|
_window->MakeWindow();
|
||||||
|
|
||||||
_GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) {
|
_GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) {
|
||||||
|
@ -325,6 +326,7 @@ void AppHost::Initialize()
|
||||||
_logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged });
|
_logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged });
|
||||||
_logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged });
|
_logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged });
|
||||||
_logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell });
|
_logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell });
|
||||||
|
_logic.SystemMenuChangeRequested({ this, &AppHost::_SystemMenuChangeRequested });
|
||||||
|
|
||||||
_logic.Create();
|
_logic.Create();
|
||||||
|
|
||||||
|
@ -1276,6 +1278,27 @@ void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&,
|
||||||
_window->OpenSystemMenu(std::nullopt, std::nullopt);
|
_window->OpenSystemMenu(std::nullopt, std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppHost::_SystemMenuChangeRequested(const winrt::Windows::Foundation::IInspectable&, const winrt::TerminalApp::SystemMenuChangeArgs& args)
|
||||||
|
{
|
||||||
|
switch (args.Action())
|
||||||
|
{
|
||||||
|
case winrt::TerminalApp::SystemMenuChangeAction::Add:
|
||||||
|
{
|
||||||
|
auto handler = args.Handler();
|
||||||
|
_window->AddToSystemMenu(args.Name(), [handler]() { handler(); });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case winrt::TerminalApp::SystemMenuChangeAction::Remove:
|
||||||
|
{
|
||||||
|
_window->RemoveFromSystemMenu(args.Name());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Creates a Notification Icon and hooks up its handlers
|
// - Creates a Notification Icon and hooks up its handlers
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
|
|
@ -96,6 +96,9 @@ private:
|
||||||
void _OpenSystemMenu(const winrt::Windows::Foundation::IInspectable& sender,
|
void _OpenSystemMenu(const winrt::Windows::Foundation::IInspectable& sender,
|
||||||
const winrt::Windows::Foundation::IInspectable& args);
|
const winrt::Windows::Foundation::IInspectable& args);
|
||||||
|
|
||||||
|
void _SystemMenuChangeRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||||
|
const winrt::TerminalApp::SystemMenuChangeArgs& args);
|
||||||
|
|
||||||
winrt::fire_and_forget _QuitRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
winrt::fire_and_forget _QuitRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||||
const winrt::Windows::Foundation::IInspectable& args);
|
const winrt::Windows::Foundation::IInspectable& args);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ using namespace ::Microsoft::Console::Types;
|
||||||
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
|
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
|
||||||
|
|
||||||
#define XAML_HOSTING_WINDOW_CLASS_NAME L"CASCADIA_HOSTING_WINDOW_CLASS"
|
#define XAML_HOSTING_WINDOW_CLASS_NAME L"CASCADIA_HOSTING_WINDOW_CLASS"
|
||||||
|
#define IDM_SYSTEM_MENU_BEGIN 0x1000
|
||||||
|
|
||||||
const UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
|
const UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
|
||||||
|
|
||||||
|
@ -321,6 +322,8 @@ void IslandWindow::Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_systemMenuNextItemId = IDM_SYSTEM_MENU_BEGIN;
|
||||||
|
|
||||||
// Enable vintage opacity by removing the XAML emergency backstop, GH#603.
|
// Enable vintage opacity by removing the XAML emergency backstop, GH#603.
|
||||||
// We don't really care if this failed or not.
|
// We don't really care if this failed or not.
|
||||||
TerminalTrySetTransparentBackground(true);
|
TerminalTrySetTransparentBackground(true);
|
||||||
|
@ -608,6 +611,20 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
||||||
_NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
_NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case WM_SYSCOMMAND:
|
||||||
|
{
|
||||||
|
if (wparam == SC_RESTORE && _fullscreen)
|
||||||
|
{
|
||||||
|
_ShouldExitFullscreenHandlers();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto search = _systemMenuItems.find(LOWORD(wparam));
|
||||||
|
if (search != _systemMenuItems.end())
|
||||||
|
{
|
||||||
|
search->second.callback();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// We'll want to receive this message when explorer.exe restarts
|
// We'll want to receive this message when explorer.exe restarts
|
||||||
// so that we can re-add our icon to the notification area.
|
// so that we can re-add our icon to the notification area.
|
||||||
|
@ -1717,5 +1734,50 @@ void IslandWindow::OpenSystemMenu(const std::optional<int> mouseX, const std::op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IslandWindow::AddToSystemMenu(const winrt::hstring& itemLabel, winrt::delegate<void()> callback)
|
||||||
|
{
|
||||||
|
const HMENU systemMenu = GetSystemMenu(_window.get(), FALSE);
|
||||||
|
UINT wID = _systemMenuNextItemId;
|
||||||
|
|
||||||
|
MENUITEMINFOW item;
|
||||||
|
item.cbSize = sizeof(MENUITEMINFOW);
|
||||||
|
item.fMask = MIIM_STATE | MIIM_ID | MIIM_STRING;
|
||||||
|
item.fState = MF_ENABLED;
|
||||||
|
item.wID = wID;
|
||||||
|
item.dwTypeData = const_cast<LPWSTR>(itemLabel.c_str());
|
||||||
|
item.cch = static_cast<UINT>(itemLabel.size());
|
||||||
|
|
||||||
|
if (LOG_LAST_ERROR_IF(!InsertMenuItemW(systemMenu, wID, FALSE, &item)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_systemMenuItems.insert({ wID, { itemLabel, callback } });
|
||||||
|
_systemMenuNextItemId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IslandWindow::RemoveFromSystemMenu(const winrt::hstring& itemLabel)
|
||||||
|
{
|
||||||
|
const HMENU systemMenu = GetSystemMenu(_window.get(), FALSE);
|
||||||
|
int itemCount = GetMenuItemCount(systemMenu);
|
||||||
|
if (LOG_LAST_ERROR_IF(itemCount == -1))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = std::find_if(_systemMenuItems.begin(), _systemMenuItems.end(), [&itemLabel](const std::pair<UINT, SystemMenuItemInfo>& elem) {
|
||||||
|
return elem.second.label == itemLabel;
|
||||||
|
});
|
||||||
|
if (it == _systemMenuItems.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOG_LAST_ERROR_IF(!DeleteMenu(systemMenu, it->first, MF_BYCOMMAND)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_systemMenuItems.erase(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||||
DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
|
DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
|
|
||||||
void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept;
|
void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept;
|
||||||
|
|
||||||
|
struct SystemMenuItemInfo
|
||||||
|
{
|
||||||
|
winrt::hstring label;
|
||||||
|
winrt::delegate<void()> callback;
|
||||||
|
};
|
||||||
|
|
||||||
class IslandWindow :
|
class IslandWindow :
|
||||||
public BaseWindow<IslandWindow>
|
public BaseWindow<IslandWindow>
|
||||||
{
|
{
|
||||||
|
@ -54,6 +60,8 @@ public:
|
||||||
void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept;
|
void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept;
|
||||||
|
|
||||||
void OpenSystemMenu(const std::optional<int> mouseX, const std::optional<int> mouseY) const noexcept;
|
void OpenSystemMenu(const std::optional<int> mouseX, const std::optional<int> mouseY) const noexcept;
|
||||||
|
void AddToSystemMenu(const winrt::hstring& itemLabel, winrt::delegate<void()> callback);
|
||||||
|
void RemoveFromSystemMenu(const winrt::hstring& itemLabel);
|
||||||
|
|
||||||
DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||||
DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
|
DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
|
||||||
|
@ -65,6 +73,7 @@ public:
|
||||||
WINRT_CALLBACK(NotifyShowNotificationIconContextMenu, winrt::delegate<void(til::point)>);
|
WINRT_CALLBACK(NotifyShowNotificationIconContextMenu, winrt::delegate<void(til::point)>);
|
||||||
WINRT_CALLBACK(NotifyNotificationIconMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
WINRT_CALLBACK(NotifyNotificationIconMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
||||||
WINRT_CALLBACK(NotifyReAddNotificationIcon, winrt::delegate<void()>);
|
WINRT_CALLBACK(NotifyReAddNotificationIcon, winrt::delegate<void()>);
|
||||||
|
WINRT_CALLBACK(ShouldExitFullscreen, winrt::delegate<void()>);
|
||||||
|
|
||||||
WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
|
WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
|
||||||
|
|
||||||
|
@ -131,6 +140,9 @@ protected:
|
||||||
|
|
||||||
bool _minimizeToNotificationArea{ false };
|
bool _minimizeToNotificationArea{ false };
|
||||||
|
|
||||||
|
std::unordered_map<UINT, SystemMenuItemInfo> _systemMenuItems;
|
||||||
|
UINT _systemMenuNextItemId;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This minimum width allows for width the tabs fit
|
// This minimum width allows for width the tabs fit
|
||||||
static constexpr long minimumWidth = 460L;
|
static constexpr long minimumWidth = 460L;
|
||||||
|
|
|
@ -843,7 +843,11 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
|
||||||
HPAINTBUFFER buf = BeginBufferedPaint(hdc.get(), &rcRest, BPBF_TOPDOWNDIB, ¶ms, &opaqueDc);
|
HPAINTBUFFER buf = BeginBufferedPaint(hdc.get(), &rcRest, BPBF_TOPDOWNDIB, ¶ms, &opaqueDc);
|
||||||
if (!buf || !opaqueDc)
|
if (!buf || !opaqueDc)
|
||||||
{
|
{
|
||||||
winrt::throw_last_error();
|
// MSFT:34673647 - BeginBufferedPaint can fail, but it probably
|
||||||
|
// shouldn't bring the whole Terminal down with it. So don't
|
||||||
|
// throw_last_error here.
|
||||||
|
LOG_LAST_ERROR();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
::FillRect(opaqueDc, &rcRest, _backgroundBrush.get());
|
::FillRect(opaqueDc, &rcRest, _backgroundBrush.get());
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -231,7 +231,7 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
|
||||||
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
|
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
|
||||||
{
|
{
|
||||||
const auto fg = GetDefaultForegroundColor();
|
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:
|
// Method Description:
|
||||||
|
@ -246,23 +246,37 @@ COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
|
||||||
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
|
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
|
||||||
{
|
{
|
||||||
const auto bg = GetDefaultBackgroundColor();
|
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:
|
// Method Description:
|
||||||
// - Get the colors of a particular text attribute, using our color table,
|
// - Get the colors of a particular text attribute, using our color table,
|
||||||
// and our configured default attributes.
|
// and our configured default attributes.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - attr: the TextAttribute to retrieve the foreground color of.
|
// - attr: the TextAttribute to retrieve the foreground and background color of.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - The color values of the attribute's foreground and background.
|
// - The color values of the attribute's foreground and background.
|
||||||
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
|
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);
|
_blinkingState.RecordBlinkingUsage(attr);
|
||||||
return attr.CalculateRgbColors(
|
return attr.CalculateRgbColors(
|
||||||
GetColorTable(),
|
GetColorTable(),
|
||||||
GetDefaultForeground(),
|
defaultFg,
|
||||||
GetDefaultBackground(),
|
defaultBg,
|
||||||
IsScreenReversed(),
|
IsScreenReversed(),
|
||||||
_blinkingState.IsBlinkingFaint());
|
_blinkingState.IsBlinkingFaint());
|
||||||
}
|
}
|
||||||
|
|
|
@ -605,7 +605,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||||
|
|
||||||
for (size_t i = 0; i < std::size(data.ColorTable); i++)
|
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 });
|
context.SetDefaultAttributes(TextAttribute{ data.wAttributes }, TextAttribute{ data.wPopupAttributes });
|
||||||
|
@ -1978,7 +1978,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
Globals& g = ServiceLocator::LocateGlobals();
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
||||||
|
|
||||||
value = gci.GetColorTableEntry(::Xterm256ToWindowsIndex(index));
|
value = gci.GetColorTableEntry(index);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -2004,7 +2004,7 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
Globals& g = ServiceLocator::LocateGlobals();
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
||||||
|
|
||||||
gci.SetColorTableEntry(::Xterm256ToWindowsIndex(index), value);
|
gci.SetColorTableEntry(index, value);
|
||||||
|
|
||||||
// Update the screen colors if we're not a pty
|
// Update the screen colors if we're not a pty
|
||||||
// No need to force a redraw in pty mode.
|
// No need to force a redraw in pty mode.
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<ClCompile Include="..\CommandListPopup.cpp" />
|
<ClCompile Include="..\CommandListPopup.cpp" />
|
||||||
<ClCompile Include="..\CopyFromCharPopup.cpp" />
|
<ClCompile Include="..\CopyFromCharPopup.cpp" />
|
||||||
<ClCompile Include="..\CopyToCharPopup.cpp" />
|
<ClCompile Include="..\CopyToCharPopup.cpp" />
|
||||||
<ClCompile Include="..\conattrs.cpp" />
|
|
||||||
<ClCompile Include="..\ConsoleArguments.cpp" />
|
<ClCompile Include="..\ConsoleArguments.cpp" />
|
||||||
<ClCompile Include="..\CursorBlinker.cpp" />
|
<ClCompile Include="..\CursorBlinker.cpp" />
|
||||||
<ClCompile Include="..\readDataCooked.cpp" />
|
<ClCompile Include="..\readDataCooked.cpp" />
|
||||||
|
|
|
@ -138,9 +138,6 @@
|
||||||
<ClCompile Include="..\writeData.cpp">
|
<ClCompile Include="..\writeData.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\conattrs.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\VtInputThread.cpp">
|
<ClCompile Include="..\VtInputThread.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -310,7 +310,7 @@ void Registry::LoadFromRegistry(_In_ PCWSTR const pwszConsoleTitle)
|
||||||
nullptr);
|
nullptr);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
_pSettings->SetColorTableEntry(i, dwValue);
|
_pSettings->SetLegacyColorTableEntry(i, dwValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,8 @@ void RenderData::UnlockConsole() noexcept
|
||||||
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
|
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
|
||||||
{
|
{
|
||||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
|
_defaultForeground = gci.GetDefaultForeground();
|
||||||
|
_defaultBackground = gci.GetDefaultBackground();
|
||||||
return gci.GetActiveOutputBuffer().GetAttributes();
|
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
|
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept
|
||||||
{
|
{
|
||||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
return gci.LookupAttributeColors(attr);
|
return gci.LookupAttributeColors(attr, _defaultForeground, _defaultBackground);
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ Author(s):
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../renderer/inc/IRenderData.hpp"
|
#include "../renderer/inc/IRenderData.hpp"
|
||||||
|
#include "../types/inc/colorTable.hpp"
|
||||||
#include "../types/IUiaData.h"
|
#include "../types/IUiaData.h"
|
||||||
|
|
||||||
class RenderData final :
|
class RenderData final :
|
||||||
|
@ -71,4 +72,8 @@ public:
|
||||||
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
|
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
|
||||||
const bool IsUiaDataInitialized() const noexcept override { return true; }
|
const bool IsUiaDataInitialized() const noexcept override { return true; }
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
private:
|
||||||
|
COLORREF _defaultForeground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 7);
|
||||||
|
COLORREF _defaultBackground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
// 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++)
|
for (size_t i = 0; i < COLOR_TABLE_SIZE; i++)
|
||||||
{
|
{
|
||||||
lpColorTable[i] = gci.GetColorTableEntry(i);
|
lpColorTable[i] = gci.GetLegacyColorTableEntry(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
*pcoordMaximumWindowSize = GetMaxWindowSizeInCharacters();
|
*pcoordMaximumWindowSize = GetMaxWindowSizeInCharacters();
|
||||||
|
|
|
@ -661,13 +661,15 @@ bool Selection::_HandleColorSelection(const INPUT_KEY_INFO* const pInputKeyInfo)
|
||||||
if (fAltPressed || fCtrlPressed)
|
if (fAltPressed || fCtrlPressed)
|
||||||
{
|
{
|
||||||
TextAttribute selectionAttr;
|
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)
|
if (fCtrlPressed)
|
||||||
{
|
{
|
||||||
// Setting background color. Set fg color to black.
|
// Setting background color. Set fg color to black.
|
||||||
selectionAttr.SetIndexedBackground256(colorIndex);
|
selectionAttr.SetIndexedBackground256(colorIndex);
|
||||||
selectionAttr.SetIndexedForeground256(0);
|
selectionAttr.SetIndexedForeground256(TextColor::DARK_BLACK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,6 +127,7 @@ public:
|
||||||
COLORREF GetDefaultForeground() const noexcept;
|
COLORREF GetDefaultForeground() const noexcept;
|
||||||
COLORREF GetDefaultBackground() 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 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 SetTitle(const std::wstring_view newTitle);
|
||||||
void SetTitlePrefix(const std::wstring_view newTitlePrefix);
|
void SetTitlePrefix(const std::wstring_view newTitlePrefix);
|
||||||
|
|
|
@ -82,8 +82,7 @@ Settings::Settings() :
|
||||||
_CursorType = CursorType::Legacy;
|
_CursorType = CursorType::Legacy;
|
||||||
|
|
||||||
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
||||||
::Microsoft::Console::Utils::Initialize256ColorTable(tableView);
|
::Microsoft::Console::Utils::InitializeColorTable(tableView);
|
||||||
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -122,8 +121,8 @@ void Settings::ApplyDesktopSpecificDefaults()
|
||||||
_uNumberOfHistoryBuffers = 4;
|
_uNumberOfHistoryBuffers = 4;
|
||||||
_bHistoryNoDup = FALSE;
|
_bHistoryNoDup = FALSE;
|
||||||
|
|
||||||
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
gsl::span<COLORREF> tableView = { _colorTable.data(), 16 };
|
||||||
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
|
::Microsoft::Console::Utils::InitializeColorTable(tableView);
|
||||||
|
|
||||||
_fTrimLeadingZeros = false;
|
_fTrimLeadingZeros = false;
|
||||||
_fEnableColorSelection = false;
|
_fEnableColorSelection = false;
|
||||||
|
@ -222,7 +221,7 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
|
||||||
_uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers;
|
_uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers;
|
||||||
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
|
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
|
||||||
{
|
{
|
||||||
SetColorTableEntry(i, pStateInfo->ColorTable[i]);
|
SetLegacyColorTableEntry(i, pStateInfo->ColorTable[i]);
|
||||||
}
|
}
|
||||||
_uCodePage = pStateInfo->CodePage;
|
_uCodePage = pStateInfo->CodePage;
|
||||||
_bWrapText = !!pStateInfo->fWrapText;
|
_bWrapText = !!pStateInfo->fWrapText;
|
||||||
|
@ -267,7 +266,7 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
|
||||||
csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers;
|
csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers;
|
||||||
for (size_t i = 0; i < std::size(csi.ColorTable); i++)
|
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.CodePage = _uCodePage;
|
||||||
csi.fWrapText = !!_bWrapText;
|
csi.fWrapText = !!_bWrapText;
|
||||||
|
@ -726,11 +725,6 @@ void Settings::SetHistoryNoDup(const bool bHistoryNoDup)
|
||||||
_bHistoryNoDup = bHistoryNoDup;
|
_bHistoryNoDup = bHistoryNoDup;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
|
|
||||||
{
|
|
||||||
_colorTable.at(index) = ColorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Settings::IsStartupTitleIsLinkNameSet() const
|
bool Settings::IsStartupTitleIsLinkNameSet() const
|
||||||
{
|
{
|
||||||
return WI_IsFlagSet(_dwStartupFlags, STARTF_TITLEISLINKNAME);
|
return WI_IsFlagSet(_dwStartupFlags, STARTF_TITLEISLINKNAME);
|
||||||
|
@ -746,11 +740,26 @@ void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset)
|
||||||
_dwStartupFlags &= ~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
|
COLORREF Settings::GetColorTableEntry(const size_t index) const
|
||||||
{
|
{
|
||||||
return _colorTable.at(index);
|
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
|
COLORREF Settings::GetCursorColor() const noexcept
|
||||||
{
|
{
|
||||||
return _CursorColor;
|
return _CursorColor;
|
||||||
|
|
|
@ -167,6 +167,8 @@ public:
|
||||||
|
|
||||||
void SetColorTableEntry(const size_t index, const COLORREF ColorValue);
|
void SetColorTableEntry(const size_t index, const COLORREF ColorValue);
|
||||||
COLORREF GetColorTableEntry(const size_t index) const;
|
COLORREF GetColorTableEntry(const size_t index) const;
|
||||||
|
void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue);
|
||||||
|
COLORREF GetLegacyColorTableEntry(const size_t index) const;
|
||||||
|
|
||||||
COLORREF GetCursorColor() const noexcept;
|
COLORREF GetCursorColor() const noexcept;
|
||||||
CursorType GetCursorType() const noexcept;
|
CursorType GetCursorType() const noexcept;
|
||||||
|
|
|
@ -89,7 +89,6 @@ SOURCES = \
|
||||||
..\utf8ToWideCharParser.cpp \
|
..\utf8ToWideCharParser.cpp \
|
||||||
..\conareainfo.cpp \
|
..\conareainfo.cpp \
|
||||||
..\conimeinfo.cpp \
|
..\conimeinfo.cpp \
|
||||||
..\conattrs.cpp \
|
|
||||||
..\ConsoleArguments.cpp \
|
..\ConsoleArguments.cpp \
|
||||||
..\CommandNumberPopup.cpp \
|
..\CommandNumberPopup.cpp \
|
||||||
..\CommandListPopup.cpp \
|
..\CommandListPopup.cpp \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -1634,74 +1634,74 @@ void ScreenBufferTests::VtSetColorTable()
|
||||||
L"Process some valid sequences for setting the table"));
|
L"Process some valid sequences for setting the table"));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;0;rgb:1/1/1\x7");
|
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");
|
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");
|
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");
|
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");
|
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\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"Try a bunch of invalid sequences."));
|
L"Try a bunch of invalid sequences."));
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"First start by setting an entry to a known value to compare to."));
|
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\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: Missing the first component"));
|
L"invalid: Missing the first component"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:/1/1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: too many components"));
|
L"invalid: too many components"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/1/1/1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: no second component"));
|
L"invalid: no second component"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:1//1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: no components"));
|
L"invalid: no components"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb://\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: no third component"));
|
L"invalid: no third component"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/11/\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: rgbi is not a supported color space"));
|
L"invalid: rgbi is not a supported color space"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgbi:1/1/1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: cmyk is not a supported color space"));
|
L"invalid: cmyk is not a supported color space"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;cmyk:1/1/1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: no table index should do nothing"));
|
L"invalid: no table index should do nothing"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;;rgb:1/1/1\x1b\\");
|
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(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: need to specify a color space"));
|
L"invalid: need to specify a color space"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;1/1/1\x1b\\");
|
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()
|
void ScreenBufferTests::ResizeTraditionalDoesNotDoubleFreeAttrRows()
|
||||||
|
@ -1912,8 +1912,8 @@ void ScreenBufferTests::VtEraseAllPersistCursorFillColor()
|
||||||
L"The viewport should be full of dark_red on bright_blue"));
|
L"The viewport should be full of dark_red on bright_blue"));
|
||||||
|
|
||||||
auto expectedAttr = TextAttribute{};
|
auto expectedAttr = TextAttribute{};
|
||||||
expectedAttr.SetIndexedForeground((BYTE)XtermToWindowsIndex(1));
|
expectedAttr.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
expectedAttr.SetIndexedBackground((BYTE)XtermToWindowsIndex(12));
|
expectedAttr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
|
||||||
stateMachine.ProcessString(L"\x1b[31;104m");
|
stateMachine.ProcessString(L"\x1b[31;104m");
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes());
|
VERIFY_ARE_EQUAL(expectedAttr, si.GetAttributes());
|
||||||
|
@ -2256,8 +2256,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
|
||||||
|
|
||||||
COLORREF magenta = RGB(255, 0, 255);
|
COLORREF magenta = RGB(255, 0, 255);
|
||||||
COLORREF yellow = RGB(255, 255, 0);
|
COLORREF yellow = RGB(255, 255, 0);
|
||||||
COLORREF brightGreen = gci.GetColorTableEntry(::XtermToWindowsIndex(10));
|
COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
COLORREF darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4));
|
COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
|
||||||
|
|
||||||
gci.SetDefaultForegroundColor(yellow);
|
gci.SetDefaultForegroundColor(yellow);
|
||||||
gci.SetDefaultBackgroundColor(magenta);
|
gci.SetDefaultBackgroundColor(magenta);
|
||||||
|
@ -2292,8 +2292,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
|
||||||
// See the log comment above for description of these values.
|
// See the log comment above for description of these values.
|
||||||
TextAttribute expectedDefaults{};
|
TextAttribute expectedDefaults{};
|
||||||
TextAttribute expectedTwo;
|
TextAttribute expectedTwo;
|
||||||
expectedTwo.SetIndexedForeground((BYTE)XtermToWindowsIndex(10));
|
expectedTwo.SetIndexedForeground(TextColor::BRIGHT_GREEN);
|
||||||
expectedTwo.SetIndexedBackground((BYTE)XtermToWindowsIndex(4));
|
expectedTwo.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
TextAttribute expectedThree = expectedTwo;
|
TextAttribute expectedThree = expectedTwo;
|
||||||
expectedThree.SetDefaultForeground();
|
expectedThree.SetDefaultForeground();
|
||||||
// Four is the same as Defaults
|
// Four is the same as Defaults
|
||||||
|
@ -2705,7 +2705,7 @@ void ScreenBufferTests::SetGlobalColorTable()
|
||||||
VERIFY_SUCCEEDED(mainBuffer.SetViewportOrigin(true, COORD({ 0, 0 }), true));
|
VERIFY_SUCCEEDED(mainBuffer.SetViewportOrigin(true, COORD({ 0, 0 }), true));
|
||||||
mainCursor.SetPosition({ 0, 0 });
|
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);
|
const COLORREF testColor = RGB(0x11, 0x22, 0x33);
|
||||||
VERIFY_ARE_NOT_EQUAL(originalRed, testColor);
|
VERIFY_ARE_NOT_EQUAL(originalRed, testColor);
|
||||||
|
|
||||||
|
@ -3209,10 +3209,10 @@ void ScreenBufferTests::DontResetColorsAboveVirtualBottom()
|
||||||
L"cursor=%s", VerifyOutputTraits<COORD>::ToString(cursor.GetPosition()).GetBuffer()));
|
L"cursor=%s", VerifyOutputTraits<COORD>::ToString(cursor.GetPosition()).GetBuffer()));
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"viewport=%s", VerifyOutputTraits<SMALL_RECT>::ToString(si.GetViewport().ToInclusive()).GetBuffer()));
|
L"viewport=%s", VerifyOutputTraits<SMALL_RECT>::ToString(si.GetViewport().ToInclusive()).GetBuffer()));
|
||||||
const auto darkRed = gci.GetColorTableEntry(::XtermToWindowsIndex(1));
|
const auto darkRed = gci.GetColorTableEntry(TextColor::DARK_RED);
|
||||||
const auto darkBlue = gci.GetColorTableEntry(::XtermToWindowsIndex(4));
|
const auto darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
|
||||||
const auto darkBlack = gci.GetColorTableEntry(::XtermToWindowsIndex(0));
|
const auto darkBlack = gci.GetColorTableEntry(TextColor::DARK_BLACK);
|
||||||
const auto darkWhite = gci.GetColorTableEntry(::XtermToWindowsIndex(7));
|
const auto darkWhite = gci.GetColorTableEntry(TextColor::DARK_WHITE);
|
||||||
stateMachine.ProcessString(L"\x1b[31;44m");
|
stateMachine.ProcessString(L"\x1b[31;44m");
|
||||||
stateMachine.ProcessString(L"X");
|
stateMachine.ProcessString(L"X");
|
||||||
stateMachine.ProcessString(L"\x1b[m");
|
stateMachine.ProcessString(L"\x1b[m");
|
||||||
|
@ -6168,8 +6168,8 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
|
||||||
/* Write red on blue, verify that it comes through */
|
/* Write red on blue, verify that it comes through */
|
||||||
{
|
{
|
||||||
TextAttribute vtRedOnBlueAttribute{};
|
TextAttribute vtRedOnBlueAttribute{};
|
||||||
vtRedOnBlueAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(1)), false });
|
vtRedOnBlueAttribute.SetForeground(TextColor{ TextColor::DARK_RED, false });
|
||||||
vtRedOnBlueAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(4)), false });
|
vtRedOnBlueAttribute.SetBackground(TextColor{ TextColor::DARK_BLUE, false });
|
||||||
|
|
||||||
seq = L"\x1b[31;44m";
|
seq = L"\x1b[31;44m";
|
||||||
seqCb = 2 * seq.size();
|
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 */
|
/* Write white on black, verify that it acts as expected for the quirk mode */
|
||||||
{
|
{
|
||||||
TextAttribute vtWhiteOnBlackAttribute{};
|
TextAttribute vtWhiteOnBlackAttribute{};
|
||||||
vtWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), false });
|
vtWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false });
|
||||||
vtWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), false });
|
vtWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false });
|
||||||
|
|
||||||
const TextAttribute quirkExpectedAttribute{ useQuirk ? defaultAttribute : vtWhiteOnBlackAttribute };
|
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 */
|
/* Write bright white on black, verify that it acts as expected for the quirk mode */
|
||||||
{
|
{
|
||||||
TextAttribute vtBrightWhiteOnBlackAttribute{};
|
TextAttribute vtBrightWhiteOnBlackAttribute{};
|
||||||
vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), false });
|
vtBrightWhiteOnBlackAttribute.SetForeground(TextColor{ TextColor::DARK_WHITE, false });
|
||||||
vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), false });
|
vtBrightWhiteOnBlackAttribute.SetBackground(TextColor{ TextColor::DARK_BLACK, false });
|
||||||
vtBrightWhiteOnBlackAttribute.SetBold(true);
|
vtBrightWhiteOnBlackAttribute.SetBold(true);
|
||||||
|
|
||||||
TextAttribute vtBrightWhiteOnDefaultAttribute{ vtBrightWhiteOnBlackAttribute }; // copy the above attribute
|
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 */
|
/* Write a 256-color white on a 256-color black, make sure the quirk does not suppress it */
|
||||||
{
|
{
|
||||||
TextAttribute vtWhiteOnBlack256Attribute{};
|
TextAttribute vtWhiteOnBlack256Attribute{};
|
||||||
vtWhiteOnBlack256Attribute.SetForeground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(7)), true });
|
vtWhiteOnBlack256Attribute.SetForeground(TextColor{ TextColor::DARK_WHITE, true });
|
||||||
vtWhiteOnBlack256Attribute.SetBackground(TextColor{ gsl::narrow_cast<BYTE>(XtermToWindowsIndex(0)), true });
|
vtWhiteOnBlack256Attribute.SetBackground(TextColor{ TextColor::DARK_BLACK, true });
|
||||||
|
|
||||||
// reset (disable bold from the last test) before setting both colors
|
// 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 (!)
|
seq = L"\x1b[m\x1b[38;5;7;48;5;0m"; // the quirk should *not* suppress this (!)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -779,8 +779,8 @@ void TextBufferTests::TestMixedRgbAndLegacyBrightness()
|
||||||
// '\E[m\E[32mX\E[1mX'
|
// '\E[m\E[32mX\E[1mX'
|
||||||
// Make sure that the second X is a BRIGHT green, not white.
|
// Make sure that the second X is a BRIGHT green, not white.
|
||||||
Log::Comment(L"Case 4 ;\"\\E[m\\E[32mX\\E[1mX\"");
|
Log::Comment(L"Case 4 ;\"\\E[m\\E[32mX\\E[1mX\"");
|
||||||
const auto dark_green = gci.GetColorTableEntry(2);
|
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
|
||||||
const auto bright_green = gci.GetColorTableEntry(10);
|
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
VERIFY_ARE_NOT_EQUAL(dark_green, bright_green);
|
VERIFY_ARE_NOT_EQUAL(dark_green, bright_green);
|
||||||
|
|
||||||
wchar_t* sequence = L"\x1b[m\x1b[32mX\x1b[1mX";
|
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 x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
const auto y = cursor.GetPosition().Y;
|
||||||
const auto dark_green = gci.GetColorTableEntry(2);
|
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
|
||||||
const auto bright_green = gci.GetColorTableEntry(10);
|
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"cursor={X:%d,Y:%d}",
|
L"cursor={X:%d,Y:%d}",
|
||||||
|
@ -938,8 +938,8 @@ void TextBufferTests::TestUnBoldRgb()
|
||||||
|
|
||||||
const auto x = cursor.GetPosition().X;
|
const auto x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
const auto y = cursor.GetPosition().Y;
|
||||||
const auto dark_green = gci.GetColorTableEntry(2);
|
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
|
||||||
const auto bright_green = gci.GetColorTableEntry(10);
|
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"cursor={X:%d,Y:%d}",
|
L"cursor={X:%d,Y:%d}",
|
||||||
|
@ -997,8 +997,8 @@ void TextBufferTests::TestComplexUnBold()
|
||||||
|
|
||||||
const auto x = cursor.GetPosition().X;
|
const auto x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
const auto y = cursor.GetPosition().Y;
|
||||||
const auto dark_green = gci.GetColorTableEntry(2);
|
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
|
||||||
const auto bright_green = gci.GetColorTableEntry(10);
|
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"cursor={X:%d,Y:%d}",
|
L"cursor={X:%d,Y:%d}",
|
||||||
|
@ -1079,8 +1079,8 @@ void TextBufferTests::CopyAttrs()
|
||||||
|
|
||||||
const auto x = cursor.GetPosition().X;
|
const auto x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
const auto y = cursor.GetPosition().Y;
|
||||||
const auto dark_blue = gci.GetColorTableEntry(1);
|
const auto dark_blue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
|
||||||
const auto dark_magenta = gci.GetColorTableEntry(5);
|
const auto dark_magenta = gci.GetColorTableEntry(TextColor::DARK_MAGENTA);
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"cursor={X:%d,Y:%d}",
|
L"cursor={X:%d,Y:%d}",
|
||||||
|
@ -1133,7 +1133,7 @@ void TextBufferTests::EmptySgrTest()
|
||||||
|
|
||||||
const auto x = cursor.GetPosition().X;
|
const auto x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
const auto y = cursor.GetPosition().Y;
|
||||||
const COLORREF darkRed = gci.GetColorTableEntry(4);
|
const COLORREF darkRed = gci.GetColorTableEntry(TextColor::DARK_RED);
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"cursor={X:%d,Y:%d}",
|
L"cursor={X:%d,Y:%d}",
|
||||||
x,
|
x,
|
||||||
|
@ -1192,7 +1192,7 @@ void TextBufferTests::TestReverseReset()
|
||||||
|
|
||||||
const auto x = cursor.GetPosition().X;
|
const auto x = cursor.GetPosition().X;
|
||||||
const auto y = cursor.GetPosition().Y;
|
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);
|
const COLORREF rgbColor = RGB(128, 5, 255);
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
|
@ -1258,9 +1258,9 @@ void TextBufferTests::CopyLastAttr()
|
||||||
const COLORREF defaultBrightYellow = RGB(249, 241, 165);
|
const COLORREF defaultBrightYellow = RGB(249, 241, 165);
|
||||||
const COLORREF defaultBrightCyan = RGB(97, 214, 214);
|
const COLORREF defaultBrightCyan = RGB(97, 214, 214);
|
||||||
|
|
||||||
gci.SetColorTableEntry(8, defaultBrightBlack);
|
gci.SetColorTableEntry(TextColor::BRIGHT_BLACK, defaultBrightBlack);
|
||||||
gci.SetColorTableEntry(14, defaultBrightYellow);
|
gci.SetColorTableEntry(TextColor::BRIGHT_YELLOW, defaultBrightYellow);
|
||||||
gci.SetColorTableEntry(11, defaultBrightCyan);
|
gci.SetColorTableEntry(TextColor::BRIGHT_CYAN, defaultBrightCyan);
|
||||||
|
|
||||||
// Write (solFg, solBG) X \n
|
// Write (solFg, solBG) X \n
|
||||||
// (solFg, solBG) X (solCyan, solBG) X \n
|
// (solFg, solBG) X (solCyan, solBG) X \n
|
||||||
|
@ -1405,8 +1405,8 @@ void TextBufferTests::TestResetClearsBoldness()
|
||||||
si.SetAttributes(defaultAttribute);
|
si.SetAttributes(defaultAttribute);
|
||||||
|
|
||||||
const auto [defaultFg, defaultBg] = gci.LookupAttributeColors(si.GetAttributes());
|
const auto [defaultFg, defaultBg] = gci.LookupAttributeColors(si.GetAttributes());
|
||||||
const auto dark_green = gci.GetColorTableEntry(2);
|
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
|
||||||
const auto bright_green = gci.GetColorTableEntry(10);
|
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
|
||||||
|
|
||||||
wchar_t* sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD";
|
wchar_t* sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD";
|
||||||
Log::Comment(NoThrowString().Format(sequence));
|
Log::Comment(NoThrowString().Format(sequence));
|
||||||
|
|
|
@ -470,7 +470,7 @@ void VtRendererTest::Xterm256TestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the BG----"));
|
L"----Change only the BG----"));
|
||||||
textAttributes.SetIndexedBackground(FOREGROUND_RED);
|
textAttributes.SetIndexedBackground(TextColor::DARK_RED);
|
||||||
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -479,7 +479,7 @@ void VtRendererTest::Xterm256TestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the FG----"));
|
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
|
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -515,7 +515,7 @@ void VtRendererTest::Xterm256TestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the FG to a 256-color index----"));
|
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)
|
qExpectedInput.push_back("\x1b[38;5;7m"); // Foreground DARK_WHITE (256-Color Index)
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -524,7 +524,7 @@ void VtRendererTest::Xterm256TestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the BG to a 256-color index----"));
|
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)
|
qExpectedInput.push_back("\x1b[48;5;1m"); // Background DARK_RED (256-Color Index)
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -859,7 +859,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
Log::Comment(L"----Set Green Foreground----");
|
Log::Comment(L"----Set Green Foreground----");
|
||||||
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
|
textAttributes.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
qExpectedInput.push_back("\x1b[32m");
|
qExpectedInput.push_back("\x1b[32m");
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
|
@ -870,7 +870,7 @@ void VtRendererTest::Xterm256TestAttributesAcrossReset()
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
Log::Comment(L"----Set Green Background----");
|
Log::Comment(L"----Set Green Background----");
|
||||||
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
|
textAttributes.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
qExpectedInput.push_back("\x1b[42m");
|
qExpectedInput.push_back("\x1b[42m");
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
|
@ -1104,7 +1104,7 @@ void VtRendererTest::XtermTestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the BG----"));
|
L"----Change only the BG----"));
|
||||||
textAttributes.SetIndexedBackground(FOREGROUND_RED);
|
textAttributes.SetIndexedBackground(TextColor::DARK_RED);
|
||||||
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -1113,7 +1113,7 @@ void VtRendererTest::XtermTestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the FG----"));
|
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
|
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -1150,7 +1150,7 @@ void VtRendererTest::XtermTestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the FG to a 256-color index----"));
|
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
|
qExpectedInput.push_back("\x1b[37m"); // Foreground DARK_WHITE
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -1159,7 +1159,7 @@ void VtRendererTest::XtermTestColors()
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"----Change only the BG to a 256-color index----"));
|
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
|
qExpectedInput.push_back("\x1b[41m"); // Background DARK_RED
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes,
|
||||||
&renderData,
|
&renderData,
|
||||||
|
@ -1351,7 +1351,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
Log::Comment(L"----Set Green Foreground----");
|
Log::Comment(L"----Set Green Foreground----");
|
||||||
textAttributes.SetIndexedForeground(FOREGROUND_GREEN);
|
textAttributes.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
qExpectedInput.push_back("\x1b[32m");
|
qExpectedInput.push_back("\x1b[32m");
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
|
@ -1362,7 +1362,7 @@ void VtRendererTest::XtermTestAttributesAcrossReset()
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
Log::Comment(L"----Set Green Background----");
|
Log::Comment(L"----Set Green Background----");
|
||||||
textAttributes.SetIndexedBackground(FOREGROUND_GREEN);
|
textAttributes.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
qExpectedInput.push_back("\x1b[42m");
|
qExpectedInput.push_back("\x1b[42m");
|
||||||
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
VERIFY_SUCCEEDED(engine->UpdateDrawingBrushes(textAttributes, &renderData, false, false));
|
||||||
|
|
||||||
|
|
|
@ -22,20 +22,6 @@ enum class ExtendedAttributes : BYTE
|
||||||
};
|
};
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes);
|
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
|
enum class CursorType : unsigned int
|
||||||
{
|
{
|
||||||
Legacy = 0x0, // uses the cursor's height value to range from underscore-like to full box
|
Legacy = 0x0, // uses the cursor's height value to range from underscore-like to full box
|
||||||
|
|
|
@ -208,7 +208,11 @@ void Clipboard::StoreSelectionToClipboard(bool const copyFormatting)
|
||||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
const auto& buffer = gci.GetActiveOutputBuffer().GetTextBuffer();
|
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;
|
bool includeCRLF, trimTrailingWhitespace;
|
||||||
if (WI_IsFlagSet(GetKeyState(VK_SHIFT), KEY_PRESSED))
|
if (WI_IsFlagSet(GetKeyState(VK_SHIFT), KEY_PRESSED))
|
||||||
|
|
|
@ -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++)
|
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.
|
// 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++)
|
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.
|
// Ensure that attributes only contain color specification.
|
||||||
|
|
|
@ -199,13 +199,14 @@ using namespace Microsoft::Console::Render;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// 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:
|
// 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
|
// - fIsForeground: true if we should emit the foreground sequence, false for background
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
|
// - 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
|
const bool fIsForeground) noexcept
|
||||||
{
|
{
|
||||||
// Always check using the foreground flags, because the bg flags constants
|
// 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.
|
// terminals display the bright color when displaying bolded text.
|
||||||
// By specifying the boldness and brightness separately, we'll make sure the
|
// By specifying the boldness and brightness separately, we'll make sure the
|
||||||
// terminal has an accurate representation of our buffer.
|
// terminal has an accurate representation of our buffer.
|
||||||
const int vtIndex = 30 +
|
const auto prefix = WI_IsFlagSet(index, FOREGROUND_INTENSITY) ? (fIsForeground ? 90 : 100) : (fIsForeground ? 30 : 40);
|
||||||
(fIsForeground ? 0 : 10) +
|
return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), prefix + (index & 7));
|
||||||
((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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Formats and writes a sequence to change the current text attributes to an
|
// - Formats and writes a sequence to change the current text attributes to an
|
||||||
// indexed color from the 256-color table.
|
// indexed color from the 256-color table.
|
||||||
// Arguments:
|
// 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
|
// - fIsForeground: true if we should emit the foreground sequence, false for background
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
|
// - 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
|
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:
|
// Method Description:
|
||||||
|
|
|
@ -287,9 +287,10 @@ using namespace Microsoft::Console::Types;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use the legacy color calculations to generate an approximation of the
|
// We use the legacy color calculations to generate an approximation of the
|
||||||
// colors in the 16-color table.
|
// colors in the Windows 16-color table, but we need to transpose those
|
||||||
auto fgIndex = fg.GetLegacyIndex(0);
|
// values to obtain an index in an ANSI-compatible order.
|
||||||
auto bgIndex = bg.GetLegacyIndex(0);
|
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.
|
// If the bold attribute is set, and the foreground can be brightened, then do so.
|
||||||
const bool brighten = textAttributes.IsBold() && fg.CanBeBrightened();
|
const bool brighten = textAttributes.IsBold() && fg.CanBeBrightened();
|
||||||
|
|
|
@ -185,9 +185,9 @@ namespace Microsoft::Console::Render
|
||||||
[[nodiscard]] HRESULT _ClearScreen() noexcept;
|
[[nodiscard]] HRESULT _ClearScreen() noexcept;
|
||||||
[[nodiscard]] HRESULT _ClearScrollback() noexcept;
|
[[nodiscard]] HRESULT _ClearScrollback() noexcept;
|
||||||
[[nodiscard]] HRESULT _ChangeTitle(const std::string& title) 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;
|
const bool fIsForeground) noexcept;
|
||||||
[[nodiscard]] HRESULT _SetGraphicsRendition256Color(const WORD index,
|
[[nodiscard]] HRESULT _SetGraphicsRendition256Color(const BYTE index,
|
||||||
const bool fIsForeground) noexcept;
|
const bool fIsForeground) noexcept;
|
||||||
[[nodiscard]] HRESULT _SetGraphicsRenditionRGBColor(const COLORREF color,
|
[[nodiscard]] HRESULT _SetGraphicsRenditionRGBColor(const COLORREF color,
|
||||||
const bool fIsForeground) noexcept;
|
const bool fIsForeground) noexcept;
|
||||||
|
|
|
@ -2541,13 +2541,13 @@ void AdaptDispatch::_ReportSGRSetting() const
|
||||||
const auto iterator = std::back_insert_iterator(response);
|
const auto iterator = std::back_insert_iterator(response);
|
||||||
if (color.IsIndex16())
|
if (color.IsIndex16())
|
||||||
{
|
{
|
||||||
const auto index = XtermToWindowsIndex(color.GetIndex());
|
const auto index = color.GetIndex();
|
||||||
const auto colorParameter = base + (index >= 8 ? 60 : 0) + (index % 8);
|
const auto colorParameter = base + (index >= 8 ? 60 : 0) + (index % 8);
|
||||||
fmt::format_to(iterator, FMT_STRING(L";{}"), colorParameter);
|
fmt::format_to(iterator, FMT_STRING(L";{}"), colorParameter);
|
||||||
}
|
}
|
||||||
else if (color.IsIndex256())
|
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);
|
fmt::format_to(iterator, FMT_STRING(L";{};5;{}"), base + 8, index);
|
||||||
}
|
}
|
||||||
else if (color.IsRgb())
|
else if (color.IsRgb())
|
||||||
|
|
|
@ -13,29 +13,6 @@
|
||||||
using namespace Microsoft::Console::VirtualTerminal;
|
using namespace Microsoft::Console::VirtualTerminal;
|
||||||
using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
|
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:
|
// Routine Description:
|
||||||
// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG)
|
// - 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)
|
// 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);
|
const size_t tableIndex = options.at(1).value_or(0);
|
||||||
if (tableIndex <= 255)
|
if (tableIndex <= 255)
|
||||||
{
|
{
|
||||||
const auto adjustedIndex = gsl::narrow_cast<BYTE>(::Xterm256ToWindowsIndex(tableIndex));
|
const auto adjustedIndex = gsl::narrow_cast<BYTE>(tableIndex);
|
||||||
if (isForeground)
|
if (isForeground)
|
||||||
{
|
{
|
||||||
attr.SetIndexedForeground256(adjustedIndex);
|
attr.SetIndexedForeground256(adjustedIndex);
|
||||||
|
@ -178,100 +155,100 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options)
|
||||||
attr.SetOverlined(false);
|
attr.SetOverlined(false);
|
||||||
break;
|
break;
|
||||||
case ForegroundBlack:
|
case ForegroundBlack:
|
||||||
attr.SetIndexedForeground(DARK_BLACK);
|
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case ForegroundBlue:
|
case ForegroundBlue:
|
||||||
attr.SetIndexedForeground(DARK_BLUE);
|
attr.SetIndexedForeground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case ForegroundGreen:
|
case ForegroundGreen:
|
||||||
attr.SetIndexedForeground(DARK_GREEN);
|
attr.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case ForegroundCyan:
|
case ForegroundCyan:
|
||||||
attr.SetIndexedForeground(DARK_CYAN);
|
attr.SetIndexedForeground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case ForegroundRed:
|
case ForegroundRed:
|
||||||
attr.SetIndexedForeground(DARK_RED);
|
attr.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case ForegroundMagenta:
|
case ForegroundMagenta:
|
||||||
attr.SetIndexedForeground(DARK_MAGENTA);
|
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case ForegroundYellow:
|
case ForegroundYellow:
|
||||||
attr.SetIndexedForeground(DARK_YELLOW);
|
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case ForegroundWhite:
|
case ForegroundWhite:
|
||||||
attr.SetIndexedForeground(DARK_WHITE);
|
attr.SetIndexedForeground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case BackgroundBlack:
|
case BackgroundBlack:
|
||||||
attr.SetIndexedBackground(DARK_BLACK);
|
attr.SetIndexedBackground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case BackgroundBlue:
|
case BackgroundBlue:
|
||||||
attr.SetIndexedBackground(DARK_BLUE);
|
attr.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case BackgroundGreen:
|
case BackgroundGreen:
|
||||||
attr.SetIndexedBackground(DARK_GREEN);
|
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case BackgroundCyan:
|
case BackgroundCyan:
|
||||||
attr.SetIndexedBackground(DARK_CYAN);
|
attr.SetIndexedBackground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case BackgroundRed:
|
case BackgroundRed:
|
||||||
attr.SetIndexedBackground(DARK_RED);
|
attr.SetIndexedBackground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case BackgroundMagenta:
|
case BackgroundMagenta:
|
||||||
attr.SetIndexedBackground(DARK_MAGENTA);
|
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BackgroundYellow:
|
case BackgroundYellow:
|
||||||
attr.SetIndexedBackground(DARK_YELLOW);
|
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BackgroundWhite:
|
case BackgroundWhite:
|
||||||
attr.SetIndexedBackground(DARK_WHITE);
|
attr.SetIndexedBackground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundBlack:
|
case BrightForegroundBlack:
|
||||||
attr.SetIndexedForeground(BRIGHT_BLACK);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundBlue:
|
case BrightForegroundBlue:
|
||||||
attr.SetIndexedForeground(BRIGHT_BLUE);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundGreen:
|
case BrightForegroundGreen:
|
||||||
attr.SetIndexedForeground(BRIGHT_GREEN);
|
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundCyan:
|
case BrightForegroundCyan:
|
||||||
attr.SetIndexedForeground(BRIGHT_CYAN);
|
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundRed:
|
case BrightForegroundRed:
|
||||||
attr.SetIndexedForeground(BRIGHT_RED);
|
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundMagenta:
|
case BrightForegroundMagenta:
|
||||||
attr.SetIndexedForeground(BRIGHT_MAGENTA);
|
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundYellow:
|
case BrightForegroundYellow:
|
||||||
attr.SetIndexedForeground(BRIGHT_YELLOW);
|
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BrightForegroundWhite:
|
case BrightForegroundWhite:
|
||||||
attr.SetIndexedForeground(BRIGHT_WHITE);
|
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundBlack:
|
case BrightBackgroundBlack:
|
||||||
attr.SetIndexedBackground(BRIGHT_BLACK);
|
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundBlue:
|
case BrightBackgroundBlue:
|
||||||
attr.SetIndexedBackground(BRIGHT_BLUE);
|
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundGreen:
|
case BrightBackgroundGreen:
|
||||||
attr.SetIndexedBackground(BRIGHT_GREEN);
|
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundCyan:
|
case BrightBackgroundCyan:
|
||||||
attr.SetIndexedBackground(BRIGHT_CYAN);
|
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundRed:
|
case BrightBackgroundRed:
|
||||||
attr.SetIndexedBackground(BRIGHT_RED);
|
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundMagenta:
|
case BrightBackgroundMagenta:
|
||||||
attr.SetIndexedBackground(BRIGHT_MAGENTA);
|
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundYellow:
|
case BrightBackgroundYellow:
|
||||||
attr.SetIndexedBackground(BRIGHT_YELLOW);
|
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case BrightBackgroundWhite:
|
case BrightBackgroundWhite:
|
||||||
attr.SetIndexedBackground(BRIGHT_WHITE);
|
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
case ForegroundExtended:
|
case ForegroundExtended:
|
||||||
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
|
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
|
||||||
|
|
|
@ -10,10 +10,16 @@ using namespace Microsoft::Console::VirtualTerminal;
|
||||||
|
|
||||||
TerminalOutput::TerminalOutput() noexcept
|
TerminalOutput::TerminalOutput() noexcept
|
||||||
{
|
{
|
||||||
|
// By default we set all of the G-sets to ASCII, so if someone accidentally
|
||||||
|
// triggers a locking shift, they won't end up with Latin1 in the GL table,
|
||||||
|
// making their system unreadable. If ISO-2022 encoding is selected, though,
|
||||||
|
// we'll reset the G2 and G3 tables to Latin1, so that 8-bit apps will get a
|
||||||
|
// more meaningful character mapping by default. This is triggered by a DOCS
|
||||||
|
// sequence, which will call the EnableGrTranslation method below.
|
||||||
_gsetTranslationTables.at(0) = Ascii;
|
_gsetTranslationTables.at(0) = Ascii;
|
||||||
_gsetTranslationTables.at(1) = Ascii;
|
_gsetTranslationTables.at(1) = Ascii;
|
||||||
_gsetTranslationTables.at(2) = Latin1;
|
_gsetTranslationTables.at(2) = Ascii;
|
||||||
_gsetTranslationTables.at(3) = Latin1;
|
_gsetTranslationTables.at(3) = Ascii;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TerminalOutput::Designate94Charset(size_t gsetNumber, const VTID charset)
|
bool TerminalOutput::Designate94Charset(size_t gsetNumber, const VTID charset)
|
||||||
|
@ -91,7 +97,13 @@ bool TerminalOutput::NeedToTranslate() const noexcept
|
||||||
void TerminalOutput::EnableGrTranslation(boolean enabled)
|
void TerminalOutput::EnableGrTranslation(boolean enabled)
|
||||||
{
|
{
|
||||||
_grTranslationEnabled = enabled;
|
_grTranslationEnabled = enabled;
|
||||||
// We need to reapply the right locking shift to (de)activate the translation table.
|
// The default table for G2 and G3 is Latin1 when GR translation is enabled,
|
||||||
|
// and ASCII when disabled. The reason for this is explained in the constructor.
|
||||||
|
const auto defaultTranslationTable = enabled ? std::wstring_view{ Latin1 } : std::wstring_view{ Ascii };
|
||||||
|
_gsetTranslationTables.at(2) = defaultTranslationTable;
|
||||||
|
_gsetTranslationTables.at(3) = defaultTranslationTable;
|
||||||
|
// We need to reapply the locking shifts in case the underlying G-sets have changed.
|
||||||
|
LockingShift(_glSetNumber);
|
||||||
LockingShiftRight(_grSetNumber);
|
LockingShiftRight(_grSetNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1307,49 +1307,49 @@ public:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Black'");
|
Log::Comment(L"Testing graphics 'Foreground Color Black'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(0);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundBlue:
|
case DispatchTypes::GraphicsOptions::ForegroundBlue:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundGreen:
|
case DispatchTypes::GraphicsOptions::ForegroundGreen:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Green'");
|
Log::Comment(L"Testing graphics 'Foreground Color Green'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundCyan:
|
case DispatchTypes::GraphicsOptions::ForegroundCyan:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Cyan'");
|
Log::Comment(L"Testing graphics 'Foreground Color Cyan'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundRed:
|
case DispatchTypes::GraphicsOptions::ForegroundRed:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Red'");
|
Log::Comment(L"Testing graphics 'Foreground Color Red'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundMagenta:
|
case DispatchTypes::GraphicsOptions::ForegroundMagenta:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Magenta'");
|
Log::Comment(L"Testing graphics 'Foreground Color Magenta'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundYellow:
|
case DispatchTypes::GraphicsOptions::ForegroundYellow:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Yellow'");
|
Log::Comment(L"Testing graphics 'Foreground Color Yellow'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundWhite:
|
case DispatchTypes::GraphicsOptions::ForegroundWhite:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color White'");
|
Log::Comment(L"Testing graphics 'Foreground Color White'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::ForegroundDefault:
|
case DispatchTypes::GraphicsOptions::ForegroundDefault:
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Default'");
|
Log::Comment(L"Testing graphics 'Foreground Color Default'");
|
||||||
|
@ -1362,49 +1362,49 @@ public:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Black'");
|
Log::Comment(L"Testing graphics 'Background Color Black'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(0);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLACK);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundBlue:
|
case DispatchTypes::GraphicsOptions::BackgroundBlue:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Blue'");
|
Log::Comment(L"Testing graphics 'Background Color Blue'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundGreen:
|
case DispatchTypes::GraphicsOptions::BackgroundGreen:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Green'");
|
Log::Comment(L"Testing graphics 'Background Color Green'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundCyan:
|
case DispatchTypes::GraphicsOptions::BackgroundCyan:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Cyan'");
|
Log::Comment(L"Testing graphics 'Background Color Cyan'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_CYAN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundRed:
|
case DispatchTypes::GraphicsOptions::BackgroundRed:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Red'");
|
Log::Comment(L"Testing graphics 'Background Color Red'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_RED >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_RED);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundMagenta:
|
case DispatchTypes::GraphicsOptions::BackgroundMagenta:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Magenta'");
|
Log::Comment(L"Testing graphics 'Background Color Magenta'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundYellow:
|
case DispatchTypes::GraphicsOptions::BackgroundYellow:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Yellow'");
|
Log::Comment(L"Testing graphics 'Background Color Yellow'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_YELLOW);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundWhite:
|
case DispatchTypes::GraphicsOptions::BackgroundWhite:
|
||||||
Log::Comment(L"Testing graphics 'Background Color White'");
|
Log::Comment(L"Testing graphics 'Background Color White'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_INTENSITY };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_INTENSITY };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_WHITE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BackgroundDefault:
|
case DispatchTypes::GraphicsOptions::BackgroundDefault:
|
||||||
Log::Comment(L"Testing graphics 'Background Color Default'");
|
Log::Comment(L"Testing graphics 'Background Color Default'");
|
||||||
|
@ -1417,97 +1417,97 @@ public:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Black'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Black'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundBlue:
|
case DispatchTypes::GraphicsOptions::BrightForegroundBlue:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Blue'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundGreen:
|
case DispatchTypes::GraphicsOptions::BrightForegroundGreen:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Green'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Green'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED | FOREGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundCyan:
|
case DispatchTypes::GraphicsOptions::BrightForegroundCyan:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Cyan'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_RED };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundRed:
|
case DispatchTypes::GraphicsOptions::BrightForegroundRed:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Red'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Red'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundMagenta:
|
case DispatchTypes::GraphicsOptions::BrightForegroundMagenta:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Magenta'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundYellow:
|
case DispatchTypes::GraphicsOptions::BrightForegroundYellow:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color Yellow'");
|
||||||
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ FOREGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightForegroundWhite:
|
case DispatchTypes::GraphicsOptions::BrightForegroundWhite:
|
||||||
Log::Comment(L"Testing graphics 'Bright Foreground Color White'");
|
Log::Comment(L"Testing graphics 'Bright Foreground Color White'");
|
||||||
_testGetSet->_attribute = TextAttribute{ 0 };
|
_testGetSet->_attribute = TextAttribute{ 0 };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundBlack:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundBlack:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Black'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Black'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_INTENSITY >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLACK);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundBlue:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundBlue:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Blue'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Blue'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_BLUE);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundGreen:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundGreen:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Green'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Green'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED | BACKGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_GREEN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundCyan:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundCyan:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Cyan'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Cyan'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_RED };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_CYAN);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundRed:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundRed:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Red'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Red'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE | BACKGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_RED);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundMagenta:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Magenta'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Magenta'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_GREEN };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundYellow:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundYellow:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color Yellow'");
|
Log::Comment(L"Testing graphics 'Bright Background Color Yellow'");
|
||||||
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE };
|
_testGetSet->_attribute = TextAttribute{ BACKGROUND_BLUE };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
|
||||||
break;
|
break;
|
||||||
case DispatchTypes::GraphicsOptions::BrightBackgroundWhite:
|
case DispatchTypes::GraphicsOptions::BrightBackgroundWhite:
|
||||||
Log::Comment(L"Testing graphics 'Bright Background Color White'");
|
Log::Comment(L"Testing graphics 'Bright Background Color White'");
|
||||||
_testGetSet->_attribute = TextAttribute{ 0 };
|
_testGetSet->_attribute = TextAttribute{ 0 };
|
||||||
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground((BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::BRIGHT_WHITE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_FAIL(L"Test not implemented yet!");
|
VERIFY_FAIL(L"Test not implemented yet!");
|
||||||
|
@ -1545,7 +1545,7 @@ public:
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundCyan;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundCyan;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(3);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_CYAN);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
|
@ -1561,7 +1561,7 @@ public:
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
|
@ -1572,14 +1572,14 @@ public:
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
// First pop:
|
// First pop:
|
||||||
cOptions = 0;
|
cOptions = 0;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
|
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
|
||||||
|
|
||||||
|
@ -1593,22 +1593,22 @@ public:
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BoldBright;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::BoldBright;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetBold(true);
|
_testGetSet->_expectedAttribute.SetBold(true);
|
||||||
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
_testGetSet->_expectedAttribute.SetDefaultBackground();
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundBlue;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundBlue;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
_testGetSet->_expectedAttribute.SetBold(true);
|
_testGetSet->_expectedAttribute.SetBold(true);
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
|
@ -1624,8 +1624,8 @@ public:
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundGreen;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundGreen;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::DoublyUnderlined;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::DoublyUnderlined;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_GREEN);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetBold(true);
|
_testGetSet->_expectedAttribute.SetBold(true);
|
||||||
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
@ -1633,24 +1633,24 @@ public:
|
||||||
cOptions = 1;
|
cOptions = 1;
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundRed;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetBold(true);
|
_testGetSet->_expectedAttribute.SetBold(true);
|
||||||
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::NotBoldOrFaint;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::NotBoldOrFaint;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_GREEN >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
_testGetSet->_expectedAttribute.SetDoublyUnderlined(true);
|
||||||
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
// And then restore...
|
// And then restore...
|
||||||
cOptions = 0;
|
cOptions = 0;
|
||||||
_testGetSet->_expectedAttribute = {};
|
_testGetSet->_expectedAttribute = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground(FOREGROUND_RED);
|
_testGetSet->_expectedAttribute.SetIndexedForeground(TextColor::DARK_RED);
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground(BACKGROUND_BLUE >> 4);
|
_testGetSet->_expectedAttribute.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||||
_testGetSet->_expectedAttribute.SetBold(true);
|
_testGetSet->_expectedAttribute.SetBold(true);
|
||||||
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
|
VERIFY_IS_TRUE(_pDispatch->PopGraphicsRendition());
|
||||||
}
|
}
|
||||||
|
@ -1672,7 +1672,7 @@ public:
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
Log::Comment(L"Enabling brightness");
|
Log::Comment(L"Enabling brightness");
|
||||||
|
@ -1683,7 +1683,7 @@ public:
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
|
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_TRUE(WI_IsFlagSet(_testGetSet->_attribute.GetLegacyAttributes(), FOREGROUND_GREEN));
|
VERIFY_IS_TRUE(WI_IsFlagSet(_testGetSet->_attribute.GetLegacyAttributes(), FOREGROUND_GREEN));
|
||||||
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
||||||
|
@ -1698,13 +1698,13 @@ public:
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
|
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Blue', brightness of 9x series doesn't persist");
|
Log::Comment(L"Testing graphics 'Foreground Color Blue', brightness of 9x series doesn't persist");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
||||||
|
|
||||||
|
@ -1717,7 +1717,7 @@ public:
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
Log::Comment(L"Testing graphics 'Foreground Color Blue'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_FALSE(_testGetSet->_attribute.IsBold());
|
||||||
|
|
||||||
|
@ -1729,19 +1729,19 @@ public:
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
|
Log::Comment(L"Testing graphics 'Foreground Color Bright Blue'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BrightForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Blue, with brightness', brightness of 9x series doesn't affect brightness");
|
Log::Comment(L"Testing graphics 'Foreground Color Blue, with brightness', brightness of 9x series doesn't affect brightness");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundBlue;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
|
Log::Comment(L"Testing graphics 'Foreground Color Green, with brightness'");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundGreen;
|
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(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
VERIFY_IS_TRUE(_testGetSet->_attribute.IsBold());
|
||||||
}
|
}
|
||||||
|
@ -1971,16 +1971,16 @@ public:
|
||||||
Log::Comment(L"Requesting SGR attributes (standard colors).");
|
Log::Comment(L"Requesting SGR attributes (standard colors).");
|
||||||
_testGetSet->PrepData();
|
_testGetSet->PrepData();
|
||||||
_testGetSet->_attribute = {};
|
_testGetSet->_attribute = {};
|
||||||
_testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(3));
|
_testGetSet->_attribute.SetIndexedForeground(TextColor::DARK_YELLOW);
|
||||||
_testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(6));
|
_testGetSet->_attribute.SetIndexedBackground(TextColor::DARK_CYAN);
|
||||||
requestSetting(L"m");
|
requestSetting(L"m");
|
||||||
_testGetSet->ValidateInputEvent(L"\033P1$r0;33;46m\033\\");
|
_testGetSet->ValidateInputEvent(L"\033P1$r0;33;46m\033\\");
|
||||||
|
|
||||||
Log::Comment(L"Requesting SGR attributes (AIX colors).");
|
Log::Comment(L"Requesting SGR attributes (AIX colors).");
|
||||||
_testGetSet->PrepData();
|
_testGetSet->PrepData();
|
||||||
_testGetSet->_attribute = {};
|
_testGetSet->_attribute = {};
|
||||||
_testGetSet->_attribute.SetIndexedForeground((BYTE)::XtermToWindowsIndex(14));
|
_testGetSet->_attribute.SetIndexedForeground(TextColor::BRIGHT_CYAN);
|
||||||
_testGetSet->_attribute.SetIndexedBackground((BYTE)::XtermToWindowsIndex(11));
|
_testGetSet->_attribute.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
|
||||||
requestSetting(L"m");
|
requestSetting(L"m");
|
||||||
_testGetSet->ValidateInputEvent(L"\033P1$r0;96;103m\033\\");
|
_testGetSet->ValidateInputEvent(L"\033P1$r0;96;103m\033\\");
|
||||||
|
|
||||||
|
@ -2297,14 +2297,14 @@ public:
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
||||||
rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green
|
rgOptions[2] = (DispatchTypes::GraphicsOptions)2; // Green
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(2));
|
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
|
||||||
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
Log::Comment(L"Test 2: Change Background");
|
Log::Comment(L"Test 2: Change Background");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
||||||
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
|
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground256((BYTE)::XtermToWindowsIndex(9));
|
_testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::BRIGHT_RED);
|
||||||
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
||||||
|
|
||||||
Log::Comment(L"Test 3: Change Foreground to RGB color");
|
Log::Comment(L"Test 3: Change Foreground to RGB color");
|
||||||
|
@ -2328,7 +2328,7 @@ public:
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
||||||
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
|
rgOptions[2] = (DispatchTypes::GraphicsOptions)9; // Bright Red
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground256((BYTE)::XtermToWindowsIndex(9));
|
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::BRIGHT_RED);
|
||||||
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
|
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");
|
Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
||||||
_testGetSet->_expectedAttribute.SetIndexedForeground256(0);
|
_testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_BLACK);
|
||||||
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 2 }));
|
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 2 }));
|
||||||
|
|
||||||
Log::Comment(L"Test 2: Change Indexed Background with default index parameter");
|
Log::Comment(L"Test 2: Change Indexed Background with default index parameter");
|
||||||
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
|
rgOptions[0] = DispatchTypes::GraphicsOptions::BackgroundExtended;
|
||||||
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index;
|
||||||
rgOptions[2] = {};
|
rgOptions[2] = {};
|
||||||
_testGetSet->_expectedAttribute.SetIndexedBackground256(0);
|
_testGetSet->_expectedAttribute.SetIndexedBackground256(TextColor::DARK_BLACK);
|
||||||
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 3 }));
|
VERIFY_IS_TRUE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, 3 }));
|
||||||
|
|
||||||
Log::Comment(L"Test 3: Change RGB Foreground with all RGB parameters missing");
|
Log::Comment(L"Test 3: Change RGB Foreground with all RGB parameters missing");
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
using namespace std::string_view_literals;
|
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{ 0x0C, 0x0C, 0x0C },
|
||||||
til::color{ 0xC5, 0x0F, 0x1F },
|
til::color{ 0xC5, 0x0F, 0x1F },
|
||||||
til::color{ 0x13, 0xA1, 0x0E },
|
til::color{ 0x13, 0xA1, 0x0E },
|
||||||
|
@ -25,25 +25,6 @@ static constexpr std::array<til::color, 16> campbellColorTable{
|
||||||
til::color{ 0xB4, 0x00, 0x9E },
|
til::color{ 0xB4, 0x00, 0x9E },
|
||||||
til::color{ 0x61, 0xD6, 0xD6 },
|
til::color{ 0x61, 0xD6, 0xD6 },
|
||||||
til::color{ 0xF2, 0xF2, 0xF2 },
|
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, 0x00 },
|
||||||
til::color{ 0x00, 0x00, 0x5F },
|
til::color{ 0x00, 0x00, 0x5F },
|
||||||
til::color{ 0x00, 0x00, 0x87 },
|
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 } }
|
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()
|
gsl::span<const til::color> Utils::CampbellColorTable()
|
||||||
{
|
{
|
||||||
return gsl::make_span(campbellColorTable);
|
return gsl::make_span(standard256ColorTable).first(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - Fill the first 16 entries of a given color table with the Campbell color
|
// - Fill up to 256 entries of a given color table with the default values
|
||||||
// scheme, in the Windows BGR order.
|
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - table: a color table with at least 16 entries
|
// - table: a color table to be filled
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>, throws if the table has less that 16 entries
|
// - <none>
|
||||||
void Utils::InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table)
|
void Utils::InitializeColorTable(const gsl::span<COLORREF> table)
|
||||||
{
|
{
|
||||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
const auto tableSize = std::min(table.size(), standard256ColorTable.size());
|
||||||
InitializeCampbellColorTable(table);
|
std::copy_n(standard256ColorTable.begin(), tableSize, table.begin());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
|
|
|
@ -12,11 +12,7 @@ Abstract:
|
||||||
|
|
||||||
namespace Microsoft::Console::Utils
|
namespace Microsoft::Console::Utils
|
||||||
{
|
{
|
||||||
void InitializeCampbellColorTable(const gsl::span<COLORREF> table);
|
void InitializeColorTable(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);
|
|
||||||
gsl::span<const til::color> CampbellColorTable();
|
gsl::span<const til::color> CampbellColorTable();
|
||||||
|
|
||||||
std::optional<til::color> ColorFromXOrgAppColorName(const std::wstring_view wstr) noexcept;
|
std::optional<til::color> ColorFromXOrgAppColorName(const std::wstring_view wstr) noexcept;
|
||||||
|
|
|
@ -20,7 +20,6 @@ class UtilsTests
|
||||||
TEST_CLASS(UtilsTests);
|
TEST_CLASS(UtilsTests);
|
||||||
|
|
||||||
TEST_METHOD(TestClampToShortMax);
|
TEST_METHOD(TestClampToShortMax);
|
||||||
TEST_METHOD(TestSwapColorPalette);
|
|
||||||
TEST_METHOD(TestGuidToString);
|
TEST_METHOD(TestGuidToString);
|
||||||
TEST_METHOD(TestSplitString);
|
TEST_METHOD(TestSplitString);
|
||||||
TEST_METHOD(TestFilterStringForPaste);
|
TEST_METHOD(TestFilterStringForPaste);
|
||||||
|
@ -55,35 +54,6 @@ void UtilsTests::TestClampToShortMax()
|
||||||
auto withinRangeActual = ClampToShortMax(withinRangeExpected, min);
|
auto withinRangeActual = ClampToShortMax(withinRangeExpected, min);
|
||||||
VERIFY_ARE_EQUAL(withinRangeExpected, withinRangeActual);
|
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()
|
void UtilsTests::TestGuidToString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "inc/utils.hpp"
|
#include "inc/utils.hpp"
|
||||||
#include "inc/colorTable.hpp"
|
#include "inc/colorTable.hpp"
|
||||||
|
|
||||||
#include <wil/token_helpers.h >
|
#include <wil/token_helpers.h>
|
||||||
|
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue