Compare commits

..

12 commits

Author SHA1 Message Date
Mike Griese 93937533bc it's BODGY time 2021-11-16 09:51:33 -06:00
Mike Griese 02344048de Revert "Experiment with removing the static MediaPlayer"
This reverts commit fb1ed58d37.
2021-11-16 09:40:23 -06:00
Mike Griese fb1ed58d37 Experiment with removing the static MediaPlayer
Somehow, this also causes an exception on teardown north of
  `Windows.Media.MediaControl.dll!AudioStateMonitorImpl::remove_SoundLevelChanged()`,
  which is in OS code somewhere. Not sure there's anything we can actually do
  about this. There are piles of bugs on that function in the OS repo.

  I think we're going to have to just end up avoiding this entirely.
2021-11-16 09:38:40 -06:00
Mike Griese 2eda14cc1b Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/honk 2021-11-16 09:18:59 -06:00
Mike Griese 684956d848 thanks for nothing VS 2021-11-01 14:57:53 -05:00
Mike Griese 9f4ed0ee18 allow env vars in paths too 2021-11-01 14:52:27 -05:00
Mike Griese 2c895b2c18 it's a singleton now 2021-11-01 12:46:00 -05:00
Mike Griese 0bb42efc0d Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/honk 2021-11-01 10:40:56 -05:00
Mike Griese cc9487e2b8 allow a single item as a list with length 1 2021-10-14 15:12:53 -05:00
Mike Griese 4c4fde9da3 oh yea, it was that easy 2021-10-14 12:57:58 -05:00
Mike Griese 8fbd32d3c3 many honks 2021-10-14 12:45:12 -05:00
Mike Griese be11388a04 it honks 2021-10-14 12:37:21 -05:00
114 changed files with 1148 additions and 1317 deletions

View file

@ -32,7 +32,6 @@ hyperlink
hyperlinking hyperlinking
hyperlinks hyperlinks
img img
inlined
It'd It'd
kje kje
liga liga

View file

@ -169,7 +169,6 @@ toupper
TTask TTask
TVal TVal
UChar UChar
UFIELD
ULARGE ULARGE
UPDATEINIFILE UPDATEINIFILE
userenv userenv

View file

@ -508,7 +508,6 @@ dealloc
Debian Debian
debolden debolden
debugtype debugtype
DECAC
DECALN DECALN
DECANM DECANM
DECAUPSS DECAUPSS

View file

@ -4,7 +4,7 @@ https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]* https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]* https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]* https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]* https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]* https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"? [Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier) (?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)

View file

@ -17,7 +17,7 @@
"Microsoft.Net.Component.4.5.TargetingPack", "Microsoft.Net.Component.4.5.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools", "Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.VisualStudio.Component.Debugger.JustInTime", "Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.Component.Windows10SDK.22000", "Microsoft.VisualStudio.Component.Windows10SDK.19041",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support", "Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde", "Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",

View file

@ -99,29 +99,15 @@ If you don't have any additional info/context to add but would like to indicate
## Contributing fixes / features ## Contributing fixes / features
If you're able & willing to help fix issues and/or implement features, we'd love your contribution! For those able & willing to help fix issues and/or implement features ...
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.
* ["Tasks"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Task%22+) are usually new pieces of functionality that aren't yet implemented for the Terminal/Console. These are usually smaller features, which we believe
- could be a single, atomic PR
- Don't require much design consideration, or we've already written the spec for the larger feature they belong to.
* ["Features"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Feature%22+) are larger pieces of new functionality. These are usually things we believe would require larger discussion of how they should be implemented, or they'll require some complicated new settings. They might just be features that are composed of many individual tasks. Often times, with features, we like to have a spec written before development work is started, to make sure we're all on the same page (see below).
Bugs and tasks are obviously the easiest to get started with, but don't feel afraid of features either! We've had some community members contribute some amazing "feature"-level work to the Terminal (albeit, with lots of discussion 😄).
Often, we like to assign issues that generally belong to somebody's area of expertise to the team member that owns that area. This doesn't mean the community can't jump in -- they should reach out and have a chat with the assignee to see if it'd okay to take. If an issue's been assigned more than a month ago, there's a good chance it's fair game to try yourself.
### To Spec or not to Spec ### To Spec or not to Spec
Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below. Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below.
Small issues that do not require a spec will be labelled `Issue-Bug` or `Issue-Task`. Small issues that do not require a spec will be labelled Issue-Bug or Issue-Task.
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled `Issue-Feature`. More often than not, we'll add such features to the ["Specification Tracker" project](https://github.com/microsoft/terminal/projects/1). However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled Issue-Feature.
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run. Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.

View file

@ -63,14 +63,8 @@
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
DependsOnTargets="_GenerateBranchAndBrandingCache"> DependsOnTargets="_GenerateBranchAndBrandingCache">
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" /> <MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
<!-- This commandline is escaped like:
powershell -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)'' -Branding $(_WTBrandingName)"
which was the only way I could find to get it to obey spaces in the SolutionDir
-->
<Exec <Exec
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;&amp;&apos;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&apos; -Path &apos;%(FeatureFlagFile.FullPath)&apos; -Branding $(_WTBrandingName)&quot;" Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
ConsoleToMsBuild="true" ConsoleToMsBuild="true"
StandardOutputImportance="low"> StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" /> <Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />

View file

@ -22,7 +22,7 @@ Param(
[Parameter(HelpMessage="Path to makeappx.exe")] [Parameter(HelpMessage="Path to makeappx.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})] [ValidateScript({Test-Path $_ -Type Leaf})]
[string] [string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\MakeAppx.exe" $MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\MakeAppx.exe"
) )
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) { If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {

View file

@ -8,7 +8,7 @@ Param(
[Parameter(HelpMessage="Path to Windows Kit")] [Parameter(HelpMessage="Path to Windows Kit")]
[ValidateScript({Test-Path $_ -Type Leaf})] [ValidateScript({Test-Path $_ -Type Leaf})]
[string] [string]
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0" $WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0"
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"

View file

@ -380,7 +380,7 @@ Here's the AppxManifest we're using:
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies> </Dependencies>
@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
```xml ```xml
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies> </Dependencies>

View file

@ -23,7 +23,7 @@
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid> <ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>EchoCon</RootNamespace> <RootNamespace>EchoCon</RootNamespace>
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion> <WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -163,4 +163,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View file

@ -27,7 +27,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -118,23 +118,6 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup> </PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" /> <Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" /> <Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

@ -128,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
// - Calculates rgb colors based off of current color table and active modification attributes. // - Calculates rgb colors based off of current color table and active modification attributes.
// Arguments: // Arguments:
// - colorTable: the current color table rgb values. // - colorTable: the current color table rgb values.
// - defaultFgIndex: the color table index of the default foreground color. // - defaultFgColor: the default foreground color rgb value.
// - defaultBgIndex: the color table index of the default background color. // - defaultBgColor: the default background color rgb value.
// - reverseScreenMode: true if the screen mode is reversed. // - reverseScreenMode: true if the screen mode is reversed.
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false) // - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true) // - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
// Return Value: // Return Value:
// - the foreground and background colors that should be displayed. // - the foreground and background colors that should be displayed.
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const size_t defaultFgIndex, const COLORREF defaultFgColor,
const size_t defaultBgIndex, const COLORREF defaultBgColor,
const bool reverseScreenMode, const bool reverseScreenMode,
const bool blinkingIsFaint, const bool blinkingIsFaint,
const bool boldIsBright) const noexcept const bool boldIsBright) const noexcept
{ {
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold()); auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgIndex); auto bg = _background.GetColor(colorTable, defaultBgColor);
if (IsFaint() || (IsBlinking() && blinkingIsFaint)) if (IsFaint() || (IsBlinking() && blinkingIsFaint))
{ {
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two. fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.

View file

@ -64,9 +64,9 @@ public:
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept; static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
WORD GetLegacyAttributes() const noexcept; WORD GetLegacyAttributes() const noexcept;
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const size_t defaultFgIndex, const COLORREF defaultFgColor,
const size_t defaultBgIndex, const COLORREF defaultBgColor,
const bool reverseScreenMode = false, const bool reverseScreenMode = false,
const bool blinkingIsFaint = false, const bool blinkingIsFaint = false,
const bool boldIsBright = true) const noexcept; const bool boldIsBright = true) const noexcept;

View file

@ -139,16 +139,14 @@ void TextColor::SetDefault() noexcept
// Arguments: // Arguments:
// - colorTable: The table of colors we should use to look up the value of // - colorTable: The table of colors we should use to look up the value of
// an indexed attribute from. // an indexed attribute from.
// - defaultIndex: The color table index to use if we're a default attribute. // - defaultColor: The color value to use if we're a default attribute.
// - brighten: if true, we'll brighten a dark color table index. // - brighten: if true, we'll brighten a dark color table index.
// Return Value: // Return Value:
// - a COLORREF containing the real value of this TextColor. // - a COLORREF containing the real value of this TextColor.
COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
{ {
if (IsDefault()) if (IsDefault())
{ {
const auto defaultColor = til::at(colorTable, defaultIndex);
if (brighten) if (brighten)
{ {
// See MSFT:20266024 for context on this fix. // See MSFT:20266024 for context on this fix.

View file

@ -65,11 +65,6 @@ public:
static constexpr BYTE BRIGHT_CYAN = 14; static constexpr BYTE BRIGHT_CYAN = 14;
static constexpr BYTE BRIGHT_WHITE = 15; static constexpr BYTE BRIGHT_WHITE = 15;
static constexpr size_t DEFAULT_FOREGROUND = 256;
static constexpr size_t DEFAULT_BACKGROUND = 257;
static constexpr size_t CURSOR_COLOR = 258;
static constexpr size_t TABLE_SIZE = 259;
constexpr TextColor() noexcept : constexpr TextColor() noexcept :
_meta{ ColorType::IsDefault }, _meta{ ColorType::IsDefault },
_red{ 0 }, _red{ 0 },
@ -108,7 +103,7 @@ public:
void SetIndex(const BYTE index, const bool isIndex256) noexcept; void SetIndex(const BYTE index, const bool isIndex256) noexcept;
void SetDefault() noexcept; void SetDefault() noexcept;
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept; COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept; BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
constexpr BYTE GetIndex() const noexcept constexpr BYTE GetIndex() const noexcept

View file

@ -27,7 +27,9 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_fDeferCursorRedraw(false), _fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false), _fHaveDeferredCursorRedraw(false),
_ulSize(ulSize), _ulSize(ulSize),
_cursorType(CursorType::Legacy) _cursorType(CursorType::Legacy),
_fUseColor(false),
_color(s_InvertCursorColor)
{ {
} }
@ -141,9 +143,10 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
_RedrawCursor(); _RedrawCursor();
} }
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
{ {
_ulSize = ulSize; _ulSize = ulSize;
_color = color;
_cursorType = type; _cursorType = type;
_RedrawCursor(); _RedrawCursor();
@ -282,6 +285,7 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
// Size will be handled separately in the resize operation. // Size will be handled separately in the resize operation.
//_ulSize = OtherCursor._ulSize; //_ulSize = OtherCursor._ulSize;
_cursorType = OtherCursor._cursorType; _cursorType = OtherCursor._cursorType;
_color = OtherCursor._color;
} }
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
@ -331,6 +335,21 @@ const CursorType Cursor::GetType() const noexcept
return _cursorType; return _cursorType;
} }
const bool Cursor::IsUsingColor() const noexcept
{
return GetColor() != INVALID_COLOR;
}
const COLORREF Cursor::GetColor() const noexcept
{
return _color;
}
void Cursor::SetColor(const unsigned int color) noexcept
{
_color = gsl::narrow_cast<COLORREF>(color);
}
void Cursor::SetType(const CursorType type) noexcept void Cursor::SetType(const CursorType type) noexcept
{ {
_cursorType = type; _cursorType = type;

View file

@ -24,6 +24,7 @@ class TextBuffer;
class Cursor final class Cursor final
{ {
public: public:
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
// the following values are used to create the textmode cursor. // the following values are used to create the textmode cursor.
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
@ -50,6 +51,8 @@ public:
COORD GetPosition() const noexcept; COORD GetPosition() const noexcept;
const CursorType GetType() const noexcept; const CursorType GetType() const noexcept;
const bool IsUsingColor() const noexcept;
const COLORREF GetColor() const noexcept;
void StartDeferDrawing() noexcept; void StartDeferDrawing() noexcept;
bool IsDeferDrawing() noexcept; bool IsDeferDrawing() noexcept;
@ -64,7 +67,7 @@ public:
void SetIsPopupShown(const bool fIsPopupShown) noexcept; void SetIsPopupShown(const bool fIsPopupShown) noexcept;
void SetDelay(const bool fDelay) noexcept; void SetDelay(const bool fDelay) noexcept;
void SetSize(const ULONG ulSize) noexcept; void SetSize(const ULONG ulSize) noexcept;
void SetStyle(const ULONG ulSize, const CursorType type) noexcept; void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
void SetPosition(const COORD cPosition) noexcept; void SetPosition(const COORD cPosition) noexcept;
void SetXPosition(const int NewX) noexcept; void SetXPosition(const int NewX) noexcept;
@ -81,6 +84,7 @@ public:
COORD GetDelayedAtPosition() const noexcept; COORD GetDelayedAtPosition() const noexcept;
bool IsDelayedEOLWrap() const noexcept; bool IsDelayedEOLWrap() const noexcept;
void SetColor(const unsigned int color) noexcept;
void SetType(const CursorType type) noexcept; void SetType(const CursorType type) noexcept;
private: private:
@ -113,4 +117,6 @@ private:
void _RedrawCursorAlways() noexcept; void _RedrawCursorAlways() noexcept;
CursorType _cursorType; CursorType _cursorType;
bool _fUseColor;
COLORREF _color;
}; };

View file

@ -24,11 +24,9 @@ class TextAttributeTests
TEST_METHOD(TestRoundtripDefaultColors); TEST_METHOD(TestRoundtripDefaultColors);
TEST_METHOD(TestBoldAsBright); TEST_METHOD(TestBoldAsBright);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable; std::array<COLORREF, 256> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3); COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6); COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
}; };
bool TextAttributeTests::ClassSetup() bool TextAttributeTests::ClassSetup()
@ -49,8 +47,6 @@ bool TextAttributeTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta _colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow _colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White _colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true; return true;
} }
@ -136,17 +132,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// values when reverse video is not set // values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo()); VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be // with reverse video set, calculated foreground/background values should be
// switched while getters stay the same // switched while getters stay the same
attr.SetReverseVideo(true); attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// reset the reverse video // reset the reverse video
attr.SetReverseVideo(false); attr.SetReverseVideo(false);
@ -155,17 +151,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// while the background and getters stay the same // while the background and getters stay the same
attr.SetFaint(true); attr.SetFaint(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be // with reverse video set, calculated foreground/background values should be
// switched, and the background fainter, while getters stay the same // switched, and the background fainter, while getters stay the same
attr.SetReverseVideo(true); attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// reset the reverse video and faint attributes // reset the reverse video and faint attributes
attr.SetReverseVideo(false); attr.SetReverseVideo(false);
@ -175,17 +171,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// background, while getters stay the same // background, while getters stay the same
attr.SetInvisible(true); attr.SetInvisible(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, the calculated background value should match // with reverse video set, the calculated background value should match
// the foreground, while getters stay the same // the foreground, while getters stay the same
attr.SetReverseVideo(true); attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
} }
void TextAttributeTests::TestReverseDefaultColors() void TextAttributeTests::TestReverseDefaultColors()
@ -198,34 +194,34 @@ void TextAttributeTests::TestReverseDefaultColors()
// values when reverse video is not set // values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo()); VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be // with reverse video set, calculated foreground/background values should be
// switched while getters stay the same // switched while getters stay the same
attr.SetReverseVideo(true); attr.SetReverseVideo(true);
VERIFY_IS_TRUE(attr.IsReverseVideo()); VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
attr.SetForeground(red); attr.SetForeground(red);
VERIFY_IS_TRUE(attr.IsReverseVideo()); VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
attr.Invert(); attr.Invert();
VERIFY_IS_FALSE(attr.IsReverseVideo()); VERIFY_IS_FALSE(attr.IsReverseVideo());
attr.SetDefaultForeground(); attr.SetDefaultForeground();
attr.SetBackground(green); attr.SetBackground(green);
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex)); VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
} }
void TextAttributeTests::TestRoundtripDefaultColors() void TextAttributeTests::TestRoundtripDefaultColors()
@ -281,43 +277,43 @@ void TextAttributeTests::TestBoldAsBright()
// values when not bold // values when not bold
VERIFY_IS_FALSE(attr.IsBold()); VERIFY_IS_FALSE(attr.IsBold());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex)); VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex)); VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, 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, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
// with bold set, calculated foreground/background values shouldn't change for the default colors. // with bold set, calculated foreground/background values shouldn't change for the default colors.
attr.SetBold(true); attr.SetBold(true);
VERIFY_IS_TRUE(attr.IsBold()); VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, 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, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedForeground(TextColor::DARK_BLACK); 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");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true)); VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
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, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedBackground(TextColor::DARK_GREEN); 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'");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, 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(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetBold(false); attr.SetBold(false);
VERIFY_IS_FALSE(attr.IsBold()); VERIFY_IS_FALSE(attr.IsBold());
Log::Comment(L"when not bold, 'bold is bright' changes nothing"); Log::Comment(L"when not bold, 'bold is bright' changes nothing");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true)); VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
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(TextColor::BRIGHT_BLACK); 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, _defaultFgIndex, _defaultBgIndex, 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, _defaultFgIndex, _defaultBgIndex, false, false, false)); VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
} }

View file

@ -23,11 +23,9 @@ class TextColorTests
TEST_METHOD(TestRgbColor); TEST_METHOD(TestRgbColor);
TEST_METHOD(TestChangeColor); TEST_METHOD(TestChangeColor);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable; std::array<COLORREF, 256> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3); COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6); COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
}; };
bool TextColorTests::ClassSetup() bool TextColorTests::ClassSetup()
@ -48,8 +46,6 @@ bool TextColorTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta _colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow _colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White _colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true; return true;
} }
@ -61,16 +57,16 @@ void TextColorTests::TestDefaultColor()
VERIFY_IS_FALSE(defaultColor.IsLegacy()); VERIFY_IS_FALSE(defaultColor.IsLegacy());
VERIFY_IS_FALSE(defaultColor.IsRgb()); VERIFY_IS_FALSE(defaultColor.IsRgb());
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false); auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color); VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true); color = defaultColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color); VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false); color = defaultColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color); VERIFY_ARE_EQUAL(_defaultBg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true); color = defaultColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color); VERIFY_ARE_EQUAL(_defaultBg, color);
} }
@ -82,16 +78,16 @@ void TextColorTests::TestDarkIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy()); VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb()); VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false); auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color); VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true); color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false); color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color); VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true); color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
} }
@ -103,16 +99,16 @@ void TextColorTests::TestBrightIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy()); VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb()); VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false); auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true); color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false); color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true); color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
} }
@ -125,16 +121,16 @@ void TextColorTests::TestRgbColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy()); VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb()); VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false); auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
} }
@ -147,55 +143,55 @@ void TextColorTests::TestChangeColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy()); VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb()); VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false); auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color); VERIFY_ARE_EQUAL(myColor, color);
rgbColor.SetDefault(); rgbColor.SetDefault();
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color); VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color); VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color); VERIFY_ARE_EQUAL(_defaultBg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color); VERIFY_ARE_EQUAL(_defaultBg, color);
rgbColor.SetIndex(7, false); rgbColor.SetIndex(7, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color); VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color); VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
rgbColor.SetIndex(15, false); rgbColor.SetIndex(15, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false); color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true); color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color); VERIFY_ARE_EQUAL(_colorTable[15], color);
} }

View file

@ -61,26 +61,13 @@
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" /> <Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" /> <Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup> <ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj"> <ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project> <ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
</ProjectReference> <ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj"> <ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project> <ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
</ProjectReference> <ProjectReference Include="..\wt\wt.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\wt\wt.vcxproj">
<Project>{506fd703-baa7-4f6e-9361-64f550ec8fca}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\exe\Host.EXE.vcxproj">
<Project>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\proxy\Host.Proxy.vcxproj">
<Project>{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}</Project>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems"> <Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">

View file

@ -26,7 +26,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -27,7 +27,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -27,7 +27,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -28,7 +28,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies> </Dependencies>

View file

@ -9,7 +9,7 @@
<uap:SupportedUsers>multiple</uap:SupportedUsers> <uap:SupportedUsers>multiple</uap:SupportedUsers>
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>
<Resource Language="x-generate" /> <Resource Language="x-generate" />

View file

@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
_terminal->SetBackgroundCallback([](auto) {}); _terminal->SetBackgroundCallback([](auto) {});
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer); _terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12)); _terminal->SetDefaultBackground(RGB(12, 12, 12));
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204)); _terminal->SetDefaultForeground(RGB(204, 204, 204));
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); }); _terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
localPointerToThread->EnablePainting(); localPointerToThread->EnablePainting();
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
{ {
auto lock = publicTerminal->_terminal->LockForWriting(); auto lock = publicTerminal->_terminal->LockForWriting();
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground); publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground); publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha); publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
// Set the font colors // Set the font colors

View file

@ -33,6 +33,7 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr }; winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr }; winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
winrt::Windows::Media::Playback::MediaPlayer Pane::s_bellPlayer = { nullptr };
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) : Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
_control{ control }, _control{ control },
@ -69,6 +70,36 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo
_FocusFirstChild(); _FocusFirstChild();
e.Handled(true); e.Handled(true);
}); });
if (!s_bellPlayer)
{
try
{
s_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer();
if (s_bellPlayer)
{
// BODGY
//
// Manually leak a ref to the MediaPlayer we just instantiated.
// We're doing this just like the way we do in AppHost with the
// App itself.
//
// We have to do this because there's some bug in the OS with
// the way a MediaPlayer gets torn down. At time fo writing (Nov
// 2021), if you search for `remove_SoundLevelChanged` in the OS
// repo, you'll find a pile of bugs.
//
// We tried moving the MediaPlayer singleton up to the
// TerminalPage, but alas, that teardown had the same problem.
// So _whatever_. We'll leak it here. It needs to last the
// lifetim of the app anyways, and it'll get cleaned up when the
// Termnial is closed, so whatever.
winrt::Windows::Media::Playback::MediaPlayer p{ s_bellPlayer };
::winrt::detach_abi(p);
}
}
CATCH_LOG();
}
} }
Pane::Pane(std::shared_ptr<Pane> first, Pane::Pane(std::shared_ptr<Pane> first,
@ -1108,6 +1139,23 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
} }
} }
winrt::fire_and_forget Pane::_playBellSound(winrt::Windows::Foundation::Uri uri)
{
auto weakThis{ shared_from_this() };
co_await winrt::resume_foreground(_root.Dispatcher());
if (auto pane{ weakThis.get() })
{
if (s_bellPlayer)
{
auto source{ winrt::Windows::Media::Core::MediaSource::CreateFromUri(uri) };
auto item{ winrt::Windows::Media::Playback::MediaPlaybackItem(source) };
s_bellPlayer.Source(item);
s_bellPlayer.Play();
}
}
}
// Method Description: // Method Description:
// - Plays a warning note when triggered by the BEL control character, // - Plays a warning note when triggered by the BEL control character,
// using the sound configured for the "Critical Stop" system event.` // using the sound configured for the "Critical Stop" system event.`
@ -1131,8 +1179,18 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible)) if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
{ {
// Audible is set, play the sound // Audible is set, play the sound
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND); auto sounds{ _profile.BellSound() };
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY); if (sounds && sounds.Size() > 0)
{
winrt::hstring soundPath{ wil::ExpandEnvironmentStringsW<std::wstring>(sounds.GetAt(rand() % sounds.Size()).c_str()) };
winrt::Windows::Foundation::Uri uri{ soundPath };
_playBellSound(uri);
}
else
{
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
}
} }
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window)) if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))

View file

@ -229,6 +229,8 @@ private:
bool _zoomed{ false }; bool _zoomed{ false };
static winrt::Windows::Media::Playback::MediaPlayer s_bellPlayer;
bool _IsLeaf() const noexcept; bool _IsLeaf() const noexcept;
bool _HasFocusedChild() const noexcept; bool _HasFocusedChild() const noexcept;
void _SetupChildCloseHandlers(); void _SetupChildCloseHandlers();
@ -282,6 +284,8 @@ private:
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const; std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
winrt::fire_and_forget _playBellSound(winrt::Windows::Foundation::Uri uri);
// Function Description: // Function Description:
// - Returns true if the given direction can be used with the given split // - Returns true if the given direction can be used with the given split
// type. // type.

View file

@ -318,29 +318,7 @@
</ProjectReference> </ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and <!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below manually include the winmds as References below -->
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj">
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See <!-- This is a hack to get the ARM64 CI build working. See

View file

@ -3,38 +3,38 @@
#include "pch.h" #include "pch.h"
#include "TerminalPage.h" #include "TerminalPage.h"
#include "TerminalPage.g.cpp" #include "Utils.h"
#include "RenameWindowRequestedArgs.g.cpp" #include "../../types/inc/utils.hpp"
#include <filesystem> #include <filesystem>
#include <inc/WindowingBehavior.h>
#include <LibraryResources.h> #include <LibraryResources.h>
#include <TerminalCore/ControlKeyStates.hpp>
#include <til/latch.h>
#include "../../types/inc/utils.hpp" #include "TerminalPage.g.cpp"
#include <winrt/Windows.Storage.h>
#include "TabRowControl.h"
#include "ColorHelper.h" #include "ColorHelper.h"
#include "DebugTapConnection.h" #include "DebugTapConnection.h"
#include "SettingsTab.h" #include "SettingsTab.h"
#include "TabRowControl.h" #include "RenameWindowRequestedArgs.g.cpp"
#include "../inc/WindowingBehavior.h"
#include <til/latch.h>
using namespace winrt; using namespace winrt;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::TerminalApp; using namespace ::TerminalApp;
using namespace ::Microsoft::Console; using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
using namespace std::chrono_literals; using namespace std::chrono_literals;
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action }); #define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
@ -1038,153 +1038,29 @@ namespace winrt::TerminalApp::implementation
} }
// Method Description: // Method Description:
// - Called when the users pressed keyBindings while CommandPalette is open. // Called when the users pressed keyBindings while CommandPalette is open.
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
// Arguments: // Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke. // - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value: // Return Value:
// - <none> // - <none>
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e) void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{ {
const auto keyStatus = e.KeyStatus(); const auto key = e.OriginalKey();
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey()); const auto scanCode = e.KeyStatus().ScanCode;
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode); const auto coreWindow = CoreWindow::GetForCurrentThread();
const auto modifiers = _GetPressedModifierKeys(); const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
// GH#11076: winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
// For some weird reason we sometimes receive a WM_KEYDOWN if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
// message without vkey or scanCode if a user drags a tab.
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
// either have a valid vkey/scanCode. This is important, because this prevents
// accidential insertion of invalid KeyChords into classes like ActionMap.
if (!vkey && !scanCode)
{ {
return; if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
// details
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
{
return;
}
// GH#2235: Terminal::Settings hasn't been modified to differentiate
// between AltGr and Ctrl+Alt yet.
// -> Don't check for key bindings if this is an AltGr key combination.
if (modifiers.IsAltGrPressed())
{
return;
}
const auto actionMap = _settings.ActionMap();
if (!actionMap)
{
return;
}
const auto cmd = actionMap.GetActionByKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
modifiers.IsWinPressed(),
vkey,
scanCode,
});
if (!cmd)
{
return;
}
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
{
return;
}
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
p.Visibility(Visibility::Collapsed);
}
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
_ClearKeyboardState(vkey, scanCode);
e.Handled(true);
}
// Method Description:
// - Get the modifier keys that are currently pressed. This can be used to
// find out which modifiers (ctrl, alt, shift) are pressed in events that
// don't necessarily include that state.
// - This is a copy of TermControl::_GetPressedModifierKeys.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
// != CoreVirtualKeyStates::None
// OR
// == CoreVirtualKeyStates::Down
// Sometimes with the key down, the state is Down | Locked.
// Sometimes with the key up, the state is Locked.
// IsFlagSet(Down) is the only correct solution.
struct KeyModifier
{
VirtualKey vkey;
ControlKeyStates flags;
};
constexpr std::array<KeyModifier, 7> modifiers{ {
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
} };
ControlKeyStates flags;
for (const auto& mod : modifiers)
{
const auto state = window.GetKeyState(mod.vkey);
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
if (isDown)
{ {
flags |= mod.flags; CommandPalette().Visibility(Visibility::Collapsed);
} }
} _actionDispatch->DoAction(cmd.ActionAndArgs());
e.Handled(true);
return flags;
}
// Method Description:
// - Discards currently pressed dead keys.
// - This is a copy of TermControl::_ClearKeyboardState.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
{
return;
}
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
std::array<wchar_t, 16> buffer;
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
{
} }
} }

View file

@ -14,17 +14,12 @@
static constexpr uint32_t DefaultRowsToScroll{ 3 }; static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" }; static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
// fwdecl unittest classes
namespace TerminalAppLocalTests namespace TerminalAppLocalTests
{ {
class TabTests; class TabTests;
class SettingsTests; class SettingsTests;
} };
namespace Microsoft::Terminal::Core
{
class ControlKeyStates;
}
namespace winrt::TerminalApp::implementation namespace winrt::TerminalApp::implementation
{ {
@ -230,8 +225,6 @@ namespace winrt::TerminalApp::implementation
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept; void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
void _RegisterActionCallbacks(); void _RegisterActionCallbacks();

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license. // Licensed under the MIT license.
// //
// pch.h // pch.h
@ -45,6 +45,9 @@
#include <winrt/Windows.UI.Xaml.Markup.h> #include <winrt/Windows.UI.Xaml.Markup.h>
#include <winrt/Windows.UI.Xaml.Media.h> #include <winrt/Windows.UI.Xaml.Media.h>
#include <winrt/Windows.UI.Xaml.Media.Animation.h> #include <winrt/Windows.UI.Xaml.Media.Animation.h>
#include <winrt/Windows.Media.h>
#include <winrt/Windows.Media.Core.h>
#include <winrt/Windows.Media.Playback.h>
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h> #include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h> #include <winrt/Microsoft.UI.Xaml.Controls.h>

View file

@ -68,22 +68,5 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" /> <Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
</Project> </Project>

View file

@ -97,39 +97,4 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" /> <Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>
<!--
BODGY:
We depend on `cpprest142*.dll`, which comes from our vcpkg dependency. As a
part of the vcpkg dependency restore, msbuild will call the `deployBinary()`
function in
`packages\vcpkg-cpprestsdk.2.10.14\scripts\BuildSystems\msbuild\AppLocal.ps1`.
That function does the actual job of copying the file. It copies it outside of
MsBuild. MsBuild then, in the `_CopyFilesMarkedCopyLocal` target, determines
that it needs to copy `cpprest142*.dll`, because that dll is a member of
`@(ReferencesCopiedInThisBuild)`. However, the file's already been copied, so
MsBuild never copies it. But that also prevents MsBuild from setting
`WroteAtLeastOneFile`, which then means that MsBuild will never create the
.CopyComplete file for this project.
Because that file is missing, MsBuild will never think the project is up to
date, and the FastUpToDate check in VS will always force MsBuild to run a pass
on this project.
To mitigate this, we're adding this other target here, which runs after
_CopyFilesMarkedCopyLocal, and always creates the CopyUpToDateMarker. This
makes the FastUpToDate check succeed.
-->
<Target
Name="_Post_CopyFilesMarkedCopyLocal"
AfterTargets="_CopyFilesMarkedCopyLocal"
Condition="'@(ReferenceCopyLocalPaths)' != ''">
<Touch Files="@(CopyUpToDateMarker)"
AlwaysCreate="true" />
</Target>
</Project>

View file

@ -1089,7 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::color ControlCore::BackgroundColor() const til::color ControlCore::BackgroundColor() const
{ {
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); return _terminal->GetDefaultBackground();
} }
// Method Description: // Method Description:

View file

@ -773,15 +773,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_HidePointerCursorHandlers(*this, nullptr); _HidePointerCursorHandlers(*this, nullptr);
const auto ch = e.Character(); const auto ch = e.Character();
const auto keyStatus = e.KeyStatus(); const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
auto modifiers = _GetPressedModifierKeys(); auto modifiers = _GetPressedModifierKeys();
if (e.KeyStatus().IsExtendedKey)
if (keyStatus.IsExtendedKey)
{ {
modifiers |= ControlKeyStates::EnhancedKey; modifiers |= ControlKeyStates::EnhancedKey;
} }
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers); const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
e.Handled(handled); e.Handled(handled);
} }
@ -876,11 +873,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode); const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
auto modifiers = _GetPressedModifierKeys(); auto modifiers = _GetPressedModifierKeys();
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// GH#11076: // GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN // For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab. // message without vkey or scanCode if a user drags a tab.
@ -914,6 +906,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return; return;
} }
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// Alt-Numpad# input will send us a character once the user releases // Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character // Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more // will be sent through the TSFInputControl. See GH#1401 for more
@ -991,7 +988,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Arguments: // Arguments:
// - vkey: The vkey of the key pressed. // - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed. // - scanCode: The scan code of the key pressed.
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
{ {
std::array<BYTE, 256> keyState; std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data())) if (!GetKeyboardState(keyState.data()))
@ -2063,7 +2060,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// don't necessarily include that state. // don't necessarily include that state.
// Return Value: // Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states. // - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept ControlKeyStates TermControl::_GetPressedModifierKeys() const
{ {
const CoreWindow window = CoreWindow::GetForCurrentThread(); const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE // DONT USE

View file

@ -245,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown); void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept; ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const; bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept; void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition); const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);

View file

@ -40,10 +40,13 @@ namespace Microsoft::Terminal::Core
virtual bool WarningBell() noexcept = 0; virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0; virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0; virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0; virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
virtual bool SetCursorColor(const DWORD color) noexcept = 0;
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0; virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;

View file

@ -41,6 +41,8 @@ Terminal::Terminal() :
_mutableViewport{ Viewport::Empty() }, _mutableViewport{ Viewport::Empty() },
_title{}, _title{},
_colorTable{}, _colorTable{},
_defaultFg{ RGB(255, 255, 255) },
_defaultBg{ ARGB(0, 0, 0, 0) },
_screenReversed{ false }, _screenReversed{ false },
_pfnWriteInput{ nullptr }, _pfnWriteInput{ nullptr },
_scrollOffset{ 0 }, _scrollOffset{ 0 },
@ -59,14 +61,6 @@ Terminal::Terminal() :
_stateMachine = std::make_unique<StateMachine>(std::move(engine)); _stateMachine = std::make_unique<StateMachine>(std::move(engine));
// Until we have a true pass-through mode (GH#1173), the decision as to
// whether C1 controls are interpreted or not is made at the conhost level.
// If they are being filtered out, then we will simply never receive them.
// But if they are being accepted by conhost, there's a chance they may get
// passed through in some situations, so it's important that our state
// machine is always prepared to accept them.
_stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true);
auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) { auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) {
if (!_pfnWriteInput) if (!_pfnWriteInput)
{ {
@ -79,10 +73,6 @@ Terminal::Terminal() :
_terminalInput = std::make_unique<TerminalInput>(passAlongInput); _terminalInput = std::make_unique<TerminalInput>(passAlongInput);
_InitializeColorTable(); _InitializeColorTable();
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = RGB(255, 255, 255);
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = ARGB(0, 0, 0, 0);
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
} }
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget) void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
@ -182,13 +172,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
{ {
// Set the default background as transparent to prevent the // Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect // DX layer from overwriting the background image or acrylic effect
const til::color newBackgroundColor{ appearance.DefaultBackground() }; til::color newBackgroundColor{ appearance.DefaultBackground() };
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0); _defaultBg = newBackgroundColor.with_alpha(0);
const til::color newForegroundColor{ appearance.DefaultForeground() }; _defaultFg = appearance.DefaultForeground();
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = newForegroundColor;
const til::color newCursorColor{ appearance.CursorColor() };
_colorTable.at(TextColor::CURSOR_COLOR) = newCursorColor;
_intenseIsBright = appearance.IntenseIsBright(); _intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors(); _adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
@ -227,7 +213,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
if (_buffer) if (_buffer)
{ {
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape); _buffer->GetCursor().SetStyle(appearance.CursorHeight(),
til::color{ appearance.CursorColor() },
cursorShape);
} }
_defaultCursorShape = cursorShape; _defaultCursorShape = cursorShape;

View file

@ -106,9 +106,11 @@ public:
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override; bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool WarningBell() noexcept override; bool WarningBell() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override; bool SetWindowTitle(std::wstring_view title) noexcept override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override; bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override; bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
bool SetCursorColor(const COLORREF color) noexcept override;
bool SetDefaultForeground(const COLORREF color) noexcept override;
bool SetDefaultBackground(const COLORREF color) noexcept override;
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override; bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
@ -210,6 +212,7 @@ public:
void ClearPatternTree() noexcept; void ClearPatternTree() noexcept;
const std::optional<til::color> GetTabColor() const noexcept; const std::optional<til::color> GetTabColor() const noexcept;
til::color GetDefaultBackground() const noexcept;
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept; Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
@ -278,7 +281,9 @@ private:
std::optional<til::color> _startingTabColor; std::optional<til::color> _startingTabColor;
// This is still stored as a COLORREF because it interacts with some code in ConTypes // This is still stored as a COLORREF because it interacts with some code in ConTypes
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable; std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
til::color _defaultFg;
til::color _defaultBg;
CursorType _defaultCursorShape; CursorType _defaultCursorShape;
bool _screenReversed; bool _screenReversed;
mutable Microsoft::Console::Render::BlinkingState _blinkingState; mutable Microsoft::Console::Render::BlinkingState _blinkingState;

View file

@ -69,6 +69,14 @@ COORD Terminal::GetCursorPosition() noexcept
return newPos; return newPos;
} }
bool Terminal::SetCursorColor(const COLORREF color) noexcept
try
{
_buffer->GetCursor().SetColor(color);
return true;
}
CATCH_RETURN_FALSE()
// Method Description: // Method Description:
// - Moves the cursor down one line, and possibly also to the leftmost column. // - Moves the cursor down one line, and possibly also to the leftmost column.
// Arguments: // Arguments:
@ -362,22 +370,6 @@ try
} }
CATCH_RETURN_FALSE() CATCH_RETURN_FALSE()
// Method Description:
// - Retrieves the value in the colortable at the specified index.
// Arguments:
// - tableIndex: the index of the color table to retrieve.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
try
{
return _colorTable.at(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
}
// Method Description: // Method Description:
// - Updates the value in the colortable at index tableIndex to the new color // - Updates the value in the colortable at index tableIndex to the new color
// color. color is a COLORREF, format 0x00BBGGRR. // color. color is a COLORREF, format 0x00BBGGRR.
@ -391,11 +383,6 @@ try
{ {
_colorTable.at(tableIndex) = color; _colorTable.at(tableIndex) = color;
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
{
_pfnBackgroundColorChanged(color);
}
// Repaint everything - the colors might have changed // Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll(); _buffer->GetRenderTarget().TriggerRedrawAll();
return true; return true;
@ -455,6 +442,46 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
return true; return true;
} }
// Method Description:
// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default foreground color
// Return Value:
// - true
bool Terminal::SetDefaultForeground(const COLORREF color) noexcept
try
{
_defaultFg = color;
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Updates the default background color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default background color
// Return Value:
// - true
bool Terminal::SetDefaultBackground(const COLORREF color) noexcept
try
{
_defaultBg = color;
_pfnBackgroundColorChanged(color);
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
til::color Terminal::GetDefaultBackground() const noexcept
{
return _defaultBg;
}
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
try try
{ {

View file

@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
try try
{ {
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color); return _terminalApi.SetCursorColor(color);
} }
CATCH_LOG_RETURN_FALSE() CATCH_LOG_RETURN_FALSE()
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
try try
{ {
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color); return _terminalApi.SetDefaultForeground(color);
} }
CATCH_LOG_RETURN_FALSE() CATCH_LOG_RETURN_FALSE()
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
try try
{ {
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color); return _terminalApi.SetDefaultBackground(color);
} }
CATCH_LOG_RETURN_FALSE() CATCH_LOG_RETURN_FALSE()

View file

@ -73,19 +73,19 @@ std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute&
if (attr.IsReverseVideo() ^ _screenReversed) if (attr.IsReverseVideo() ^ _screenReversed)
{ {
colors.first = _adjustedForegroundColors[fgIndex][bgIndex]; colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
colors.second = fgTextColor.GetColor(_colorTable, TextColor::DEFAULT_FOREGROUND); colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
} }
else else
{ {
colors.first = _adjustedForegroundColors[bgIndex][fgIndex]; colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND); colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
} }
} }
else else
{ {
colors = attr.CalculateRgbColors(_colorTable, colors = attr.CalculateRgbColors(_colorTable,
TextColor::DEFAULT_FOREGROUND, _defaultFg,
TextColor::DEFAULT_BACKGROUND, _defaultBg,
_screenReversed, _screenReversed,
_blinkingState.IsBlinkingFaint(), _blinkingState.IsBlinkingFaint(),
_intenseIsBright); _intenseIsBright);
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
COLORREF Terminal::GetCursorColor() const noexcept COLORREF Terminal::GetCursorColor() const noexcept
{ {
return _colorTable.at(TextColor::CURSOR_COLOR); return _buffer->GetCursor().GetColor();
} }
bool Terminal::IsCursorDoubleWidth() const bool Terminal::IsCursorDoubleWidth() const
@ -312,8 +312,8 @@ void Terminal::_MakeAdjustedColorArray()
// to include the default background and default foreground colors // to include the default background and default foreground colors
std::array<COLORREF, 18> colorTableWithDefaults; std::array<COLORREF, 18> colorTableWithDefaults;
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults)); std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
colorTableWithDefaults[DefaultBgIndex] = _colorTable.at(TextColor::DEFAULT_BACKGROUND); colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND); colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex) for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
{ {
const auto fg = til::at(colorTableWithDefaults, fgIndex); const auto fg = til::at(colorTableWithDefaults, fgIndex);

View file

@ -3,7 +3,6 @@
#include "pch.h" #include "pch.h"
#include "Profiles.h" #include "Profiles.h"
#include "PreviewConnection.h" #include "PreviewConnection.h"
#include "Profiles.g.cpp" #include "Profiles.g.cpp"
#include "EnumEntry.h" #include "EnumEntry.h"
@ -11,54 +10,6 @@
#include <LibraryResources.h> #include <LibraryResources.h>
#include "..\WinRTUtils\inc\Utils.h" #include "..\WinRTUtils\inc\Utils.h"
// This function is a copy of DxFontInfo::_NearbyCollection() with
// * the call to DxFontInfo::s_GetNearbyFonts() inlined
// * checkForUpdates for GetSystemFontCollection() set to true
static wil::com_ptr<IDWriteFontCollection1> NearbyCollection(IDWriteFactory* dwriteFactory)
{
// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
wil::com_ptr<IDWriteFactory6> factory6;
// wil's query() facilities don't work inside WinRT land at the moment.
// They produce a compilation error due to IUnknown and winrt::Windows::Foundation::IUnknown being ambiguous.
if (!SUCCEEDED(dwriteFactory->QueryInterface(__uuidof(IDWriteFactory6), factory6.put_void())))
{
return nullptr;
}
wil::com_ptr<IDWriteFontCollection1> systemFontCollection;
THROW_IF_FAILED(factory6->GetSystemFontCollection(false, systemFontCollection.addressof(), true));
wil::com_ptr<IDWriteFontSet> systemFontSet;
THROW_IF_FAILED(systemFontCollection->GetFontSet(systemFontSet.addressof()));
wil::com_ptr<IDWriteFontSetBuilder2> fontSetBuilder2;
THROW_IF_FAILED(factory6->CreateFontSetBuilder(fontSetBuilder2.addressof()));
THROW_IF_FAILED(fontSetBuilder2->AddFontSet(systemFontSet.get()));
{
const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
const auto folder{ module.parent_path() };
for (const auto& p : std::filesystem::directory_iterator(folder))
{
if (til::ends_with(p.path().native(), L".ttf"))
{
fontSetBuilder2->AddFontFile(p.path().c_str());
}
}
}
wil::com_ptr<IDWriteFontSet> fontSet;
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(fontSet.addressof()));
wil::com_ptr<IDWriteFontCollection1> fontCollection;
THROW_IF_FAILED(factory6->CreateFontCollectionFromFontSet(fontSet.get(), &fontCollection));
return fontCollection;
}
using namespace winrt::Windows::UI::Text; using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls; using namespace winrt::Windows::UI::Xaml::Controls;
@ -156,7 +107,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
reinterpret_cast<::IUnknown**>(factory.put()))); reinterpret_cast<::IUnknown**>(factory.put())));
// get the font collection; subscribe to updates // get the font collection; subscribe to updates
const auto fontCollection = NearbyCollection(factory.get()); com_ptr<IDWriteFontCollection> fontCollection;
THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.put(), TRUE));
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i) for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
{ {

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license. // Licensed under the MIT license.
// //
// pch.h // pch.h
@ -51,7 +51,8 @@
#include <shlobj.h> #include <shlobj.h>
#include <shobjidl_core.h> #include <shobjidl_core.h>
#include <dwrite_3.h> #include <dwrite.h>
#include <dwrite_1.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers // Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h" #include "til.h"

View file

@ -307,9 +307,16 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
val.reserve(json.size()); val.reserve(json.size());
ConversionTrait<T> trait; ConversionTrait<T> trait;
for (const auto& element : json) if (json.isArray())
{ {
val.push_back(trait.FromJson(element)); for (const auto& element : json)
{
val.push_back(trait.FromJson(element));
}
}
else
{
val.push_back(trait.FromJson(json));
} }
return val; return val;
@ -318,7 +325,9 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
bool CanConvert(const Json::Value& json) const bool CanConvert(const Json::Value& json) const
{ {
ConversionTrait<T> trait; ConversionTrait<T> trait;
return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) mutable -> bool { return trait.CanConvert(json); }); // If there's only one element provided, then see if we can convert
// that single element into a length-1 array
return (json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) mutable -> bool { return trait.CanConvert(json); })) || trait.CanConvert(json);
} }
Json::Value ToJson(const std::vector<T>& val) Json::Value ToJson(const std::vector<T>& val)

View file

@ -74,7 +74,8 @@ Author(s):
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \ X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \
X(hstring, TabTitle, "tabTitle") \ X(hstring, TabTitle, "tabTitle") \
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \ X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
X(bool, UseAtlasEngine, "experimental.useAtlasEngine", false) X(bool, UseAtlasEngine, "experimental.useAtlasEngine", false) \
X(Windows::Foundation::Collections::IVector<winrt::hstring>, BellSound, "bellSound", nullptr)
#define MTSM_FONT_SETTINGS(X) \ #define MTSM_FONT_SETTINGS(X) \
X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \ X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \

View file

@ -197,29 +197,9 @@
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project> <Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and <!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below manually include the winmds as References below -->
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as <!-- Manually add references to each of our dependent winmds. Mark them as
@ -286,5 +266,4 @@
</Target> </Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" /> <Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" /> <Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
</Project> </Project>

View file

@ -30,6 +30,7 @@ static constexpr std::string_view FontInfoKey{ "font" };
static constexpr std::string_view PaddingKey{ "padding" }; static constexpr std::string_view PaddingKey{ "padding" };
static constexpr std::string_view TabColorKey{ "tabColor" }; static constexpr std::string_view TabColorKey{ "tabColor" };
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" }; static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
static constexpr std::string_view BellSoundKey{ "bellSound" };
Profile::Profile(guid guid) noexcept : Profile::Profile(guid guid) noexcept :
_Guid(guid) _Guid(guid)
@ -104,6 +105,7 @@ winrt::com_ptr<Profile> Profile::CopySettings() const
profile->_Hidden = _Hidden; profile->_Hidden = _Hidden;
profile->_TabColor = _TabColor; profile->_TabColor = _TabColor;
profile->_Padding = _Padding; profile->_Padding = _Padding;
profile->_Origin = _Origin; profile->_Origin = _Origin;
profile->_FontInfo = *fontInfo; profile->_FontInfo = *fontInfo;
profile->_DefaultAppearance = *defaultAppearance; profile->_DefaultAppearance = *defaultAppearance;
@ -178,6 +180,7 @@ void Profile::LayerJson(const Json::Value& json)
#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ #define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name); JsonUtils::GetValueForKey(json, jsonKey, _##name);
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON) MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON)
#undef PROFILE_SETTINGS_LAYER_JSON #undef PROFILE_SETTINGS_LAYER_JSON
@ -318,6 +321,7 @@ Json::Value Profile::ToJson() const
#define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ #define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
JsonUtils::SetValueForKey(json, jsonKey, _##name); JsonUtils::SetValueForKey(json, jsonKey, _##name);
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_TO_JSON) MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_TO_JSON)
#undef PROFILE_SETTINGS_TO_JSON #undef PROFILE_SETTINGS_TO_JSON

View file

@ -80,5 +80,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing); INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);
INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle); INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle);
INHERITABLE_PROFILE_SETTING(Boolean, UseAtlasEngine); INHERITABLE_PROFILE_SETTING(Boolean, UseAtlasEngine);
INHERITABLE_PROFILE_SETTING(Windows.Foundation.Collections.IVector<String>, BellSound);
} }
} }

View file

@ -65,7 +65,7 @@
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj"> <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with <!-- Private:false and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. --> xbf's into the packaging project twice. -->

View file

@ -96,10 +96,9 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
auto& g = ServiceLocator::LocateGlobals(); auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation(); auto& gci = g.getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR); gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR); gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight); m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer(); auto& currentBuffer = gci.GetActiveOutputBuffer();

View file

@ -59,6 +59,7 @@ void TerminalApiTest::SetColorTableEntry()
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100)); VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100)); VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(256, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100)); VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
} }
@ -270,7 +271,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink()
auto& stateMachine = *(term._stateMachine); auto& stateMachine = *(term._stateMachine);
// Process the opening osc 8 sequence // Process the opening osc 8 sequence
stateMachine.ProcessString(L"\x1b]8;;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
@ -280,7 +281,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink()
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
// Process the closing osc 8 sequences // Process the closing osc 8 sequences
stateMachine.ProcessString(L"\x1b]8;;\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;\x9c");
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
} }
@ -296,7 +297,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId()
auto& stateMachine = *(term._stateMachine); auto& stateMachine = *(term._stateMachine);
// Process the opening osc 8 sequence // Process the opening osc 8 sequence
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
@ -308,7 +309,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId()
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
// Process the closing osc 8 sequences // Process the closing osc 8 sequences
stateMachine.ProcessString(L"\x1b]8;;\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;\x9c");
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
} }
@ -324,7 +325,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
auto& stateMachine = *(term._stateMachine); auto& stateMachine = *(term._stateMachine);
// Process the opening osc 8 sequence // Process the opening osc 8 sequence
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
@ -332,7 +333,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
const auto oldAttributes{ tbi.GetCurrentAttributes() }; const auto oldAttributes{ tbi.GetCurrentAttributes() };
// Send any other text // Send any other text
stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
@ -355,58 +356,58 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress()
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
// Set some values for taskbar state and progress through state machine // Set some values for taskbar state and progress through state machine
stateMachine.ProcessString(L"\x1b]9;4;1;50\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;1;50\x9c");
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50));
// Reset to 0 // Reset to 0
stateMachine.ProcessString(L"\x1b]9;4;0;0\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;0;0\x9c");
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
// Set an out of bounds value for state // Set an out of bounds value for state
stateMachine.ProcessString(L"\x1b]9;4;5;50\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;5;50\x9c");
// Nothing should have changed (dispatch should have returned false) // Nothing should have changed (dispatch should have returned false)
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
// Set an out of bounds value for progress // Set an out of bounds value for progress
stateMachine.ProcessString(L"\x1b]9;4;1;999\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;1;999\x9c");
// Progress should have been clamped to 100 // Progress should have been clamped to 100
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100));
// Don't specify any params // Don't specify any params
stateMachine.ProcessString(L"\x1b]9;4\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4\x9c");
// State and progress should both be reset to 0 // State and progress should both be reset to 0
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
// Specify additional params // Specify additional params
stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x9c");
// Additional params should be ignored, state and progress still set normally // Additional params should be ignored, state and progress still set normally
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
// Edge cases + trailing semicolon testing // Edge cases + trailing semicolon testing
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;2;\x9c");
// String should be processed correctly despite the trailing semicolon, // String should be processed correctly despite the trailing semicolon,
// taskbar progress should remain unchanged from previous value // taskbar progress should remain unchanged from previous value
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
stateMachine.ProcessString(L"\x1b]9;4;3;75\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;3;75\x9c");
// Given progress value should be ignored because this is the indeterminate state, // Given progress value should be ignored because this is the indeterminate state,
// so the progress value should remain unchanged // so the progress value should remain unchanged
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(3)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(3));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
stateMachine.ProcessString(L"\x1b]9;4;0;50\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;0;50\x9c");
// Taskbar progress should be 0 (the given value should be ignored) // Taskbar progress should be 0 (the given value should be ignored)
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\"); stateMachine.ProcessString(L"\x1b]9;4;2;\x9c");
// String should be processed correctly despite the trailing semicolon, // String should be processed correctly despite the trailing semicolon,
// taskbar progress should be set to a 'minimum', non-zero value // taskbar progress should be set to a 'minimum', non-zero value
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2)); VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
@ -426,45 +427,45 @@ void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory()
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
// Invalid sequences should not change CWD // Invalid sequences should not change CWD
stateMachine.ProcessString(L"\x1b]9;9\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9\x9c");
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
stateMachine.ProcessString(L"\x1b]9;9\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9\"\x9c");
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x9c");
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
// Valid sequences should change CWD // Valid sequences should change CWD
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
// Test OSC 9;9 sequences without quotation marks // Test OSC 9;9 sequences without quotation marks
stateMachine.ProcessString(L"\x1b]9;9;C:\\\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;C:\\\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文"); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
// These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these. // These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these.
stateMachine.ProcessString(L"\x1b]9;9;\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\""); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
stateMachine.ProcessString(L"\x1b]9;9;\"\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\""); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\""); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x1b\\"); stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x9c");
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\""); VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
} }

View file

@ -348,7 +348,7 @@ void AppHost::Initialize()
_window->SetContent(_logic.GetRoot()); _window->SetContent(_logic.GetRoot());
_window->OnAppInitialized(); _window->OnAppInitialized();
// THIS IS A HACK // BODGY
// //
// We've got a weird crash that happens terribly inconsistently, but pretty // We've got a weird crash that happens terribly inconsistently, but pretty
// readily on migrie's laptop, only in Debug mode. Apparently, there's some // readily on migrie's laptop, only in Debug mode. Apparently, there's some

View file

@ -115,23 +115,6 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup> </PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" /> <Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" /> <Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

@ -18,7 +18,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -18,7 +18,7 @@
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>

View file

@ -29,7 +29,7 @@
<Description>TAEF Packaged Cwa FullTrust Application Host Process</Description> <Description>TAEF Packaged Cwa FullTrust Application Host Process</Description>
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies> </Dependencies>

View file

@ -75,7 +75,7 @@
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.22000.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)' == ''">10.0.18362.0</WindowsTargetPlatformMinVersion> <WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)' == ''">10.0.18362.0</WindowsTargetPlatformMinVersion>
</PropertyGroup> </PropertyGroup>

View file

@ -219,6 +219,36 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
return pInputBuffer; return pInputBuffer;
} }
// Method Description:
// - Return the default foreground color of the console. If the settings are
// configured to have a default foreground color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default foreground color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
{
const auto fg = GetDefaultForegroundColor();
return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
}
// Method Description:
// - Return the default background color of the console. If the settings are
// configured to have a default background color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default background color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
{
const auto bg = GetDefaultBackgroundColor();
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.
@ -227,12 +257,26 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
// 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(),
GetDefaultForegroundIndex(), defaultFg,
GetDefaultBackgroundIndex(), defaultBg,
IsScreenReversed(), IsScreenReversed(),
_blinkingState.IsBlinkingFaint()); _blinkingState.IsBlinkingFaint());
} }

View file

@ -143,7 +143,7 @@
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>copy &quot;$(SolutionDir)\dep\WinAppDriver\*&quot; &quot;$(OutDir)\&quot;</PostBuildEvent> <PostBuildEvent>copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" /> <Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@ -152,4 +152,4 @@
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" /> <Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" />
</Target> </Target>
</Project> </Project>

View file

@ -1499,6 +1499,12 @@ void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType); screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
} }
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor)
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetColor(cursorColor);
}
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo, void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri, const std::wstring_view uri,
const std::wstring_view params) const std::wstring_view params)
@ -1957,6 +1963,115 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
screenInfo.GetActiveBuffer().MoveToBottom(); screenInfo.GetActiveBuffer().MoveToBottom();
} }
// Method Description:
// - Retrieve the color table value at the specified index.
// Arguments:
// - index: the index in the table to retrieve.
// - value: receives the RGB value for the color at that index in the table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
value = gci.GetColorTableEntry(index);
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the color table value in index to the color specified in value.
// Can be used to set the 256-color table as well as the 16-color table.
// Arguments:
// - index: the index in the table to change.
// - value: the new RGB value to use for that index in the color table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
// Notes:
// Does not take a buffer parameter. The color table for a console and for
// terminals as well is global, not per-screen-buffer.
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetColorTableEntry(index, value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default foreground color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultForegroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default background color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultBackgroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Routine Description: // Routine Description:
// - A private API call for filling a region of the screen buffer. // - A private API call for filling a region of the screen buffer.
// Arguments: // Arguments:

View file

@ -36,6 +36,8 @@ void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo, void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
const CursorType cursorType); const CursorType cursorType);
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor);
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo, void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri, const std::wstring_view uri,
@ -61,6 +63,13 @@ void DoSrvPrivateInsertLines(const size_t count);
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo); void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo, [[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
const COORD startPosition, const COORD startPosition,
const size_t fillLength, const size_t fillLength,

View file

@ -15,7 +15,6 @@
using namespace Microsoft::Console; using namespace Microsoft::Console;
using Microsoft::Console::Interactivity::ServiceLocator; using Microsoft::Console::Interactivity::ServiceLocator;
using Microsoft::Console::VirtualTerminal::StateMachine;
using Microsoft::Console::VirtualTerminal::TerminalInput; using Microsoft::Console::VirtualTerminal::TerminalInput;
WriteBuffer::WriteBuffer(_In_ Microsoft::Console::IIoProvider& io) : WriteBuffer::WriteBuffer(_In_ Microsoft::Console::IIoProvider& io) :
@ -264,35 +263,22 @@ bool ConhostInternalGetSet::SetInputMode(const TerminalInput::Mode mode, const b
} }
// Routine Description: // Routine Description:
// - Sets the various StateMachine parser modes. // - Sets the terminal emulation mode to either ANSI-compatible or VT52.
// SetParserMode is an internal-only "API" call that the vt commands can execute, // PrivateSetAnsiMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface. // but it is not represented as a function call on out public API surface.
// Arguments: // Arguments:
// - mode - the parser mode to change. // - ansiMode - set to true to enable the ANSI mode, false for VT52 mode.
// - enabled - set to true to enable the mode, false to disable it.
// Return Value: // Return Value:
// - true if successful. false otherwise. // - true if successful. false otherwise.
bool ConhostInternalGetSet::SetParserMode(const StateMachine::Mode mode, const bool enabled) bool ConhostInternalGetSet::PrivateSetAnsiMode(const bool ansiMode)
{ {
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine(); auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
stateMachine.SetParserMode(mode, enabled); stateMachine.SetAnsiMode(ansiMode);
auto& terminalInput = _io.GetActiveInputBuffer()->GetTerminalInput();
terminalInput.SetInputMode(TerminalInput::Mode::Ansi, ansiMode);
return true; return true;
} }
// Routine Description:
// - Retrieves the various StateMachine parser modes.
// GetParserMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - mode - the parser mode to query.
// Return Value:
// - true if the mode is enabled. false if disabled.
bool ConhostInternalGetSet::GetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode) const
{
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
return stateMachine.GetParserMode(mode);
}
// Routine Description: // Routine Description:
// - Connects the PrivateSetScreenMode call directly into our Driver Message servicing call inside Conhost.exe // - Connects the PrivateSetScreenMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateSetScreenMode is an internal-only "API" call that the vt commands can execute, // PrivateSetScreenMode is an internal-only "API" call that the vt commands can execute,
@ -552,6 +538,21 @@ bool ConhostInternalGetSet::PrivateSuppressResizeRepaint()
return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint()); return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint());
} }
// Routine Description:
// - Connects the SetCursorStyle call directly into our Driver Message servicing call inside Conhost.exe
// SetCursorStyle is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// Arguments:
// - cursorColor: The color to change the cursor to. INVALID_COLOR will revert
// it to the legacy inverting behavior.
// Return Value:
// - true if successful (see DoSrvSetCursorStyle). false otherwise.
bool ConhostInternalGetSet::SetCursorColor(const COLORREF cursorColor)
{
DoSrvSetCursorColor(_io.GetActiveOutputBuffer(), cursorColor);
return true;
}
// Routine Description: // Routine Description:
// - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe // - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe
// - NOTE: This ONE method behaves differently! The rest of the methods on this // - NOTE: This ONE method behaves differently! The rest of the methods on this
@ -593,61 +594,54 @@ bool ConhostInternalGetSet::MoveToBottom() const
} }
// Method Description: // Method Description:
// - Retrieves the value in the colortable at the specified index. // - Connects the PrivateGetColorTableEntry call directly into our Driver Message servicing
// call inside Conhost.exe
// Arguments: // Arguments:
// - tableIndex: the index of the color table to retrieve. // - index: the index in the table to retrieve.
// - value: receives the RGB value for the color at that index in the table.
// Return Value: // Return Value:
// - the COLORREF value for the color at that index in the table. // - true if successful (see DoSrvPrivateGetColorTableEntry). false otherwise.
COLORREF ConhostInternalGetSet::GetColorTableEntry(const size_t tableIndex) const noexcept bool ConhostInternalGetSet::PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept
try
{ {
auto& g = ServiceLocator::LocateGlobals(); return SUCCEEDED(DoSrvPrivateGetColorTableEntry(index, value));
auto& gci = g.getConsoleInformation();
return gci.GetColorTableEntry(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
} }
// Method Description: // Method Description:
// - Updates the value in the colortable at index tableIndex to the new color // - Connects the PrivateSetColorTableEntry call directly into our Driver Message servicing
// color. color is a COLORREF, format 0x00BBGGRR. // call inside Conhost.exe
// Arguments: // Arguments:
// - tableIndex: the index of the color table to update. // - index: the index in the table to change.
// - color: the new COLORREF to use as that color table value. // - value: the new RGB value to use for that index in the color table.
// Return Value: // Return Value:
// - true if successful. false otherwise. // - true if successful (see DoSrvPrivateSetColorTableEntry). false otherwise.
bool ConhostInternalGetSet::SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept bool ConhostInternalGetSet::PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept
try
{ {
auto& g = ServiceLocator::LocateGlobals(); return SUCCEEDED(DoSrvPrivateSetColorTableEntry(index, value));
auto& gci = g.getConsoleInformation(); }
gci.SetColorTableEntry(tableIndex, color); // Method Description:
// - Connects the PrivateSetDefaultForeground call directly into our Driver Message servicing
// If we're setting the default foreground or background colors // call inside Conhost.exe
// we need to make sure the index is correctly set as well. // Arguments:
if (tableIndex == TextColor::DEFAULT_FOREGROUND) // - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
{ // Return Value:
gci.SetDefaultForegroundIndex(TextColor::DEFAULT_FOREGROUND); // - true if successful (see DoSrvPrivateSetDefaultForegroundColor). false otherwise.
} bool ConhostInternalGetSet::PrivateSetDefaultForeground(const COLORREF value) const noexcept
if (tableIndex == TextColor::DEFAULT_BACKGROUND) {
{ return SUCCEEDED(DoSrvPrivateSetDefaultForegroundColor(value));
gci.SetDefaultBackgroundIndex(TextColor::DEFAULT_BACKGROUND); }
}
// Method Description:
// Update the screen colors if we're not a pty // - Connects the PrivateSetDefaultBackground call directly into our Driver Message servicing
// No need to force a redraw in pty mode. // call inside Conhost.exe
if (g.pRender && !gci.IsInVtIoMode()) // Arguments:
{ // - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
g.pRender->TriggerRedrawAll(); // Return Value:
} // - true if successful (see DoSrvPrivateSetDefaultBackgroundColor). false otherwise.
bool ConhostInternalGetSet::PrivateSetDefaultBackground(const COLORREF value) const noexcept
return true; {
return SUCCEEDED(DoSrvPrivateSetDefaultBackgroundColor(value));
} }
CATCH_RETURN_FALSE()
// Routine Description: // Routine Description:
// - Connects the PrivateFillRegion call directly into our Driver Message servicing // - Connects the PrivateFillRegion call directly into our Driver Message servicing

View file

@ -73,9 +73,8 @@ public:
const SMALL_RECT& window) override; const SMALL_RECT& window) override;
bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override; bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
bool SetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode, const bool enabled) override;
bool GetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode) const override;
bool PrivateSetAnsiMode(const bool ansiMode) override;
bool PrivateSetScreenMode(const bool reverseMode) override; bool PrivateSetScreenMode(const bool reverseMode) override;
bool PrivateSetAutoWrapMode(const bool wrapAtEOL) override; bool PrivateSetAutoWrapMode(const bool wrapAtEOL) override;
@ -101,6 +100,7 @@ public:
bool GetUserDefaultCursorStyle(CursorType& style) override; bool GetUserDefaultCursorStyle(CursorType& style) override;
bool SetCursorStyle(CursorType const style) override; bool SetCursorStyle(CursorType const style) override;
bool SetCursorColor(COLORREF const color) override;
bool PrivateRefreshWindow() override; bool PrivateRefreshWindow() override;
@ -118,8 +118,12 @@ public:
bool MoveToBottom() const override; bool MoveToBottom() const override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override; bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override; bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept override;
bool PrivateSetDefaultForeground(const COLORREF value) const noexcept override;
bool PrivateSetDefaultBackground(const COLORREF value) const noexcept override;
bool PrivateFillRegion(const COORD startPosition, bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength, const size_t fillLength,

View file

@ -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();
} }
@ -224,7 +226,8 @@ ULONG RenderData::GetCursorPixelWidth() const noexcept
COLORREF RenderData::GetCursorColor() const noexcept COLORREF RenderData::GetCursorColor() const noexcept
{ {
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetColorTableEntry(TextColor::CURSOR_COLOR); const auto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.GetColor();
} }
// Routine Description: // Routine Description:
@ -361,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

View file

@ -72,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);
}; };

View file

@ -123,6 +123,7 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION()
pScreen->_renderTarget); pScreen->_renderTarget);
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
pScreen->_textBuffer->GetCursor().SetColor(gci.GetCursorColor());
pScreen->_textBuffer->GetCursor().SetType(gci.GetCursorType()); pScreen->_textBuffer->GetCursor().SetType(gci.GetCursorType());
const NTSTATUS status = pScreen->_InitializeOutputStateMachine(); const NTSTATUS status = pScreen->_InitializeOutputStateMachine();
@ -1629,6 +1630,29 @@ void SCREEN_INFORMATION::SetCursorInformation(const ULONG Size,
} }
} }
// Routine Description:
// - This routine sets the cursor color. Also updates the cursor information of
// this buffer's main buffer, if this buffer is an alt buffer.
// Arguments:
// - Color - The new color to set the cursor to
// - setMain - If true, propagate change to main buffer as well.
// Return Value:
// - None
void SCREEN_INFORMATION::SetCursorColor(const unsigned int Color, const bool setMain) noexcept
{
Cursor& cursor = _textBuffer->GetCursor();
cursor.SetColor(Color);
// If we're an alt buffer, DON'T propagate this setting up to the main buffer.
// We don't want to pollute that buffer with this state,
// UNLESS we're getting called from the propsheet, then we DO want to update this.
if (_psiMainBuffer && setMain)
{
_psiMainBuffer->SetCursorColor(Color);
}
}
// Routine Description: // Routine Description:
// - This routine sets the cursor shape both in the data // - This routine sets the cursor shape both in the data
// structures and on the screen. Also updates the cursor information of // structures and on the screen. Also updates the cursor information of
@ -1884,7 +1908,7 @@ const SCREEN_INFORMATION& SCREEN_INFORMATION::GetMainBuffer() const
auto& myCursor = GetTextBuffer().GetCursor(); auto& myCursor = GetTextBuffer().GetCursor();
auto* const createdBuffer = *ppsiNewScreenBuffer; auto* const createdBuffer = *ppsiNewScreenBuffer;
auto& altCursor = createdBuffer->GetTextBuffer().GetCursor(); auto& altCursor = createdBuffer->GetTextBuffer().GetCursor();
altCursor.SetStyle(myCursor.GetSize(), myCursor.GetType()); altCursor.SetStyle(myCursor.GetSize(), myCursor.GetColor(), myCursor.GetType());
altCursor.SetIsVisible(myCursor.IsVisible()); altCursor.SetIsVisible(myCursor.IsVisible());
altCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed()); altCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
// The new position should match the viewport-relative position of the main buffer. // The new position should match the viewport-relative position of the main buffer.
@ -1982,7 +2006,7 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
// Copy the alt buffer's cursor style and visibility back to the main buffer. // Copy the alt buffer's cursor style and visibility back to the main buffer.
const auto& altCursor = psiAlt->GetTextBuffer().GetCursor(); const auto& altCursor = psiAlt->GetTextBuffer().GetCursor();
auto& mainCursor = psiMain->GetTextBuffer().GetCursor(); auto& mainCursor = psiMain->GetTextBuffer().GetCursor();
mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetType()); mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetColor(), altCursor.GetType());
mainCursor.SetIsVisible(altCursor.IsVisible()); mainCursor.SetIsVisible(altCursor.IsVisible());
mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed()); mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed());

View file

@ -189,6 +189,8 @@ public:
void SetCursorInformation(const ULONG Size, void SetCursorInformation(const ULONG Size,
const bool Visible) noexcept; const bool Visible) noexcept;
void SetCursorColor(const unsigned int Color, const bool setMain = false) noexcept;
void SetCursorType(const CursorType Type, const bool setMain = false) noexcept; void SetCursorType(const CursorType Type, const bool setMain = false) noexcept;
void SetCursorDBMode(const bool DoubleCursor); void SetCursorDBMode(const bool DoubleCursor);

View file

@ -16,6 +16,7 @@ Selection::Selection() :
_fSelectionVisible(false), _fSelectionVisible(false),
_ulSavedCursorSize(0), _ulSavedCursorSize(0),
_fSavedCursorVisible(false), _fSavedCursorVisible(false),
_savedCursorColor(INVALID_COLOR),
_savedCursorType(CursorType::Legacy), _savedCursorType(CursorType::Legacy),
_dwSelectionFlags(0), _dwSelectionFlags(0),
_fLineSelection(true), _fLineSelection(true),

View file

@ -174,6 +174,7 @@ private:
COORD _coordSavedCursorPosition; COORD _coordSavedCursorPosition;
ULONG _ulSavedCursorSize; ULONG _ulSavedCursorSize;
bool _fSavedCursorVisible; bool _fSavedCursorVisible;
COLORREF _savedCursorColor;
CursorType _savedCursorType; CursorType _savedCursorType;
#ifdef UNIT_TESTING #ifdef UNIT_TESTING

View file

@ -168,6 +168,7 @@ void Selection::_SaveCursorData(const Cursor& cursor) noexcept
_coordSavedCursorPosition = cursor.GetPosition(); _coordSavedCursorPosition = cursor.GetPosition();
_ulSavedCursorSize = cursor.GetSize(); _ulSavedCursorSize = cursor.GetSize();
_fSavedCursorVisible = cursor.IsVisible(); _fSavedCursorVisible = cursor.IsVisible();
_savedCursorColor = cursor.GetColor();
_savedCursorType = cursor.GetType(); _savedCursorType = cursor.GetType();
} }
@ -181,6 +182,7 @@ void Selection::_RestoreDataToCursor(Cursor& cursor) noexcept
{ {
cursor.SetSize(_ulSavedCursorSize); cursor.SetSize(_ulSavedCursorSize);
cursor.SetIsVisible(_fSavedCursorVisible); cursor.SetIsVisible(_fSavedCursorVisible);
cursor.SetColor(_savedCursorColor);
cursor.SetType(_savedCursorType); cursor.SetType(_savedCursorType);
cursor.SetIsOn(true); cursor.SetIsOn(true);
cursor.SetPosition(_coordSavedCursorPosition); cursor.SetPosition(_coordSavedCursorPosition);

View file

@ -124,7 +124,10 @@ public:
COOKED_READ_DATA& CookedReadData() noexcept; COOKED_READ_DATA& CookedReadData() noexcept;
void SetCookedReadData(COOKED_READ_DATA* readData) noexcept; void SetCookedReadData(COOKED_READ_DATA* readData) noexcept;
COLORREF GetDefaultForeground() const noexcept;
COLORREF GetDefaultBackground() const noexcept;
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const noexcept; std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const 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);

View file

@ -56,8 +56,8 @@ Settings::Settings() :
_fScreenReversed(false), _fScreenReversed(false),
// window size pixels initialized below // window size pixels initialized below
_fInterceptCopyPaste(0), _fInterceptCopyPaste(0),
_defaultForegroundIndex(TextColor::DARK_WHITE), _DefaultForeground(INVALID_COLOR),
_defaultBackgroundIndex(TextColor::DARK_BLACK), _DefaultBackground(INVALID_COLOR),
_fUseDx(UseDx::Disabled), _fUseDx(UseDx::Disabled),
_fCopyColor(false) _fCopyColor(false)
{ {
@ -78,14 +78,11 @@ Settings::Settings() :
ZeroMemory((void*)&_FaceName, sizeof(_FaceName)); ZeroMemory((void*)&_FaceName, sizeof(_FaceName));
wcscpy_s(_FaceName, DEFAULT_TT_FONT_FACENAME); wcscpy_s(_FaceName, DEFAULT_TT_FONT_FACENAME);
_CursorColor = Cursor::s_InvertCursorColor;
_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::InitializeColorTable(tableView); ::Microsoft::Console::Utils::InitializeColorTable(tableView);
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = INVALID_COLOR;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = INVALID_COLOR;
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
} }
// Routine Description: // Routine Description:
@ -232,11 +229,11 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
_fCtrlKeyShortcutsDisabled = pStateInfo->fCtrlKeyShortcutsDisabled; _fCtrlKeyShortcutsDisabled = pStateInfo->fCtrlKeyShortcutsDisabled;
_bLineSelection = pStateInfo->fLineSelection; _bLineSelection = pStateInfo->fLineSelection;
_bWindowAlpha = pStateInfo->bWindowTransparency; _bWindowAlpha = pStateInfo->bWindowTransparency;
_CursorColor = pStateInfo->CursorColor;
_CursorType = static_cast<CursorType>(pStateInfo->CursorType); _CursorType = static_cast<CursorType>(pStateInfo->CursorType);
_fInterceptCopyPaste = pStateInfo->InterceptCopyPaste; _fInterceptCopyPaste = pStateInfo->InterceptCopyPaste;
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = pStateInfo->DefaultForeground; _DefaultForeground = pStateInfo->DefaultForeground;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = pStateInfo->DefaultBackground; _DefaultBackground = pStateInfo->DefaultBackground;
_colorTable.at(TextColor::CURSOR_COLOR) = pStateInfo->CursorColor;
_TerminalScrolling = pStateInfo->TerminalScrolling; _TerminalScrolling = pStateInfo->TerminalScrolling;
} }
@ -277,11 +274,11 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
csi.fCtrlKeyShortcutsDisabled = _fCtrlKeyShortcutsDisabled; csi.fCtrlKeyShortcutsDisabled = _fCtrlKeyShortcutsDisabled;
csi.fLineSelection = _bLineSelection; csi.fLineSelection = _bLineSelection;
csi.bWindowTransparency = _bWindowAlpha; csi.bWindowTransparency = _bWindowAlpha;
csi.CursorColor = _CursorColor;
csi.CursorType = static_cast<unsigned int>(_CursorType); csi.CursorType = static_cast<unsigned int>(_CursorType);
csi.InterceptCopyPaste = _fInterceptCopyPaste; csi.InterceptCopyPaste = _fInterceptCopyPaste;
csi.DefaultForeground = _colorTable.at(TextColor::DEFAULT_FOREGROUND); csi.DefaultForeground = _DefaultForeground;
csi.DefaultBackground = _colorTable.at(TextColor::DEFAULT_BACKGROUND); csi.DefaultBackground = _DefaultBackground;
csi.CursorColor = _colorTable.at(TextColor::CURSOR_COLOR);
csi.TerminalScrolling = _TerminalScrolling; csi.TerminalScrolling = _TerminalScrolling;
return csi; return csi;
} }
@ -333,22 +330,16 @@ void Settings::Validate()
WI_ClearAllFlags(_wFillAttribute, ~(FG_ATTRS | BG_ATTRS)); WI_ClearAllFlags(_wFillAttribute, ~(FG_ATTRS | BG_ATTRS));
WI_ClearAllFlags(_wPopupFillAttribute, ~(FG_ATTRS | BG_ATTRS)); WI_ClearAllFlags(_wPopupFillAttribute, ~(FG_ATTRS | BG_ATTRS));
const auto defaultForeground = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
const auto defaultBackground = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
const auto cursorColor = _colorTable.at(TextColor::CURSOR_COLOR);
// If the extended color options are set to invalid values (all the same color), reset them. // If the extended color options are set to invalid values (all the same color), reset them.
if (cursorColor != INVALID_COLOR && cursorColor == defaultBackground) if (_CursorColor != Cursor::s_InvertCursorColor && _CursorColor == _DefaultBackground)
{ {
// INVALID_COLOR is used to represent "Invert Colors" _CursorColor = Cursor::s_InvertCursorColor;
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
} }
if (defaultForeground != INVALID_COLOR && defaultForeground == defaultBackground) if (_DefaultForeground != INVALID_COLOR && _DefaultForeground == _DefaultBackground)
{ {
// INVALID_COLOR is used as an "unset" sentinel in future attribute functions. // INVALID_COLOR is used as an "unset" sentinel in future attribute functions.
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = INVALID_COLOR; _DefaultForeground = _DefaultBackground = INVALID_COLOR;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = INVALID_COLOR;
// If the damaged settings _further_ propagated to the default fill attribute, fix it. // If the damaged settings _further_ propagated to the default fill attribute, fix it.
if (_wFillAttribute == 0) if (_wFillAttribute == 0)
{ {
@ -360,8 +351,6 @@ void Settings::Validate()
// At this point the default fill attributes are fully initialized // At this point the default fill attributes are fully initialized
// so we can pass on the final colors to the TextAttribute class. // so we can pass on the final colors to the TextAttribute class.
TextAttribute::SetLegacyDefaultAttributes(_wFillAttribute); TextAttribute::SetLegacyDefaultAttributes(_wFillAttribute);
// And calculate the position of the default colors in the color table.
CalculateDefaultColorIndices();
FAIL_FAST_IF(!(_dwWindowSize.X > 0)); FAIL_FAST_IF(!(_dwWindowSize.X > 0));
FAIL_FAST_IF(!(_dwWindowSize.Y > 0)); FAIL_FAST_IF(!(_dwWindowSize.Y > 0));
@ -771,11 +760,21 @@ COLORREF Settings::GetLegacyColorTableEntry(const size_t index) const
return _colorTable.at(TextColor::TransposeLegacyIndex(index)); return _colorTable.at(TextColor::TransposeLegacyIndex(index));
} }
COLORREF Settings::GetCursorColor() const noexcept
{
return _CursorColor;
}
CursorType Settings::GetCursorType() const noexcept CursorType Settings::GetCursorType() const noexcept
{ {
return _CursorType; return _CursorType;
} }
void Settings::SetCursorColor(const COLORREF CursorColor) noexcept
{
_CursorColor = CursorColor;
}
void Settings::SetCursorType(const CursorType cursorType) noexcept void Settings::SetCursorType(const CursorType cursorType) noexcept
{ {
_CursorType = cursorType; _CursorType = cursorType;
@ -791,35 +790,24 @@ void Settings::SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept
_fInterceptCopyPaste = interceptCopyPaste; _fInterceptCopyPaste = interceptCopyPaste;
} }
void Settings::CalculateDefaultColorIndices() noexcept COLORREF Settings::GetDefaultForegroundColor() const noexcept
{ {
const auto foregroundColor = _colorTable.at(TextColor::DEFAULT_FOREGROUND); return _DefaultForeground;
const auto foregroundIndex = TextColor::TransposeLegacyIndex(_wFillAttribute & FG_ATTRS);
_defaultForegroundIndex = foregroundColor != INVALID_COLOR ? TextColor::DEFAULT_FOREGROUND : foregroundIndex;
const auto backgroundColor = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
const auto backgroundIndex = TextColor::TransposeLegacyIndex((_wFillAttribute & BG_ATTRS) >> 4);
_defaultBackgroundIndex = backgroundColor != INVALID_COLOR ? TextColor::DEFAULT_BACKGROUND : backgroundIndex;
} }
size_t Settings::GetDefaultForegroundIndex() const noexcept void Settings::SetDefaultForegroundColor(const COLORREF defaultForeground) noexcept
{ {
return _defaultForegroundIndex; _DefaultForeground = defaultForeground;
} }
void Settings::SetDefaultForegroundIndex(const size_t index) noexcept COLORREF Settings::GetDefaultBackgroundColor() const noexcept
{ {
_defaultForegroundIndex = index; return _DefaultBackground;
} }
size_t Settings::GetDefaultBackgroundIndex() const noexcept void Settings::SetDefaultBackgroundColor(const COLORREF defaultBackground) noexcept
{ {
return _defaultBackgroundIndex; _DefaultBackground = defaultBackground;
}
void Settings::SetDefaultBackgroundIndex(const size_t index) noexcept
{
_defaultBackgroundIndex = index;
} }
bool Settings::IsTerminalScrolling() const noexcept bool Settings::IsTerminalScrolling() const noexcept

View file

@ -167,7 +167,7 @@ public:
void SetHistoryNoDup(const bool fHistoryNoDup); void SetHistoryNoDup(const bool fHistoryNoDup);
// The first 16 items of the color table are the same as the 16-color palette. // The first 16 items of the color table are the same as the 16-color palette.
inline const std::array<COLORREF, TextColor::TABLE_SIZE>& GetColorTable() const noexcept inline const std::array<COLORREF, XTERM_COLOR_TABLE_SIZE>& GetColorTable() const noexcept
{ {
return _colorTable; return _colorTable;
} }
@ -177,17 +177,20 @@ public:
void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue); void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue);
COLORREF GetLegacyColorTableEntry(const size_t index) const; COLORREF GetLegacyColorTableEntry(const size_t index) const;
COLORREF GetCursorColor() const noexcept;
CursorType GetCursorType() const noexcept; CursorType GetCursorType() const noexcept;
void SetCursorColor(const COLORREF CursorColor) noexcept;
void SetCursorType(const CursorType cursorType) noexcept; void SetCursorType(const CursorType cursorType) noexcept;
bool GetInterceptCopyPaste() const noexcept; bool GetInterceptCopyPaste() const noexcept;
void SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept; void SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept;
void CalculateDefaultColorIndices() noexcept; COLORREF GetDefaultForegroundColor() const noexcept;
size_t GetDefaultForegroundIndex() const noexcept; void SetDefaultForegroundColor(const COLORREF defaultForeground) noexcept;
void SetDefaultForegroundIndex(const size_t index) noexcept;
size_t GetDefaultBackgroundIndex() const noexcept; COLORREF GetDefaultBackgroundColor() const noexcept;
void SetDefaultBackgroundIndex(const size_t index) noexcept; void SetDefaultBackgroundColor(const COLORREF defaultBackground) noexcept;
bool IsTerminalScrolling() const noexcept; bool IsTerminalScrolling() const noexcept;
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept; void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;
@ -239,19 +242,20 @@ private:
UseDx _fUseDx; UseDx _fUseDx;
bool _fCopyColor; bool _fCopyColor;
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable; std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
// this is used for the special STARTF_USESIZE mode. // this is used for the special STARTF_USESIZE mode.
bool _fUseWindowSizePixels; bool _fUseWindowSizePixels;
COORD _dwWindowSizePixels; COORD _dwWindowSizePixels;
// Technically a COLORREF, but using INVALID_COLOR as "Invert Colors"
unsigned int _CursorColor;
CursorType _CursorType; CursorType _CursorType;
bool _fInterceptCopyPaste; bool _fInterceptCopyPaste;
size_t _defaultForegroundIndex; COLORREF _DefaultForeground;
size_t _defaultBackgroundIndex; COLORREF _DefaultBackground;
bool _TerminalScrolling; bool _TerminalScrolling;
friend class RegistrySerialization; friend class RegistrySerialization;
}; };

View file

@ -67,10 +67,9 @@ class ConptyOutputTests
// Set up some sane defaults // Set up some sane defaults
auto& g = ServiceLocator::LocateGlobals(); auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation(); auto& gci = g.getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR); gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR); gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight); m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer(); auto& currentBuffer = gci.GetActiveOutputBuffer();

View file

@ -59,10 +59,9 @@ class ScreenBufferTests
{ {
// Set up some sane defaults // Set up some sane defaults
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR); gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR); gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(); m_state->PrepareNewTextBufferInfo();
auto& currentBuffer = gci.GetActiveOutputBuffer(); auto& currentBuffer = gci.GetActiveOutputBuffer();
@ -360,11 +359,12 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
auto mainCursorPos = COORD{ 3, 5 }; auto mainCursorPos = COORD{ 3, 5 };
auto mainCursorVisible = false; auto mainCursorVisible = false;
auto mainCursorSize = 33u; auto mainCursorSize = 33u;
auto mainCursorColor = RGB(1, 2, 3);
auto mainCursorType = CursorType::DoubleUnderscore; auto mainCursorType = CursorType::DoubleUnderscore;
auto mainCursorBlinking = false; auto mainCursorBlinking = false;
mainCursor.SetPosition(mainCursorPos); mainCursor.SetPosition(mainCursorPos);
mainCursor.SetIsVisible(mainCursorVisible); mainCursor.SetIsVisible(mainCursorVisible);
mainCursor.SetStyle(mainCursorSize, mainCursorType); mainCursor.SetStyle(mainCursorSize, mainCursorColor, mainCursorType);
mainCursor.SetBlinkingAllowed(mainCursorBlinking); mainCursor.SetBlinkingAllowed(mainCursorBlinking);
Log::Comment(L"Switch to the alternate buffer."); Log::Comment(L"Switch to the alternate buffer.");
@ -379,6 +379,7 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
VERIFY_ARE_EQUAL(mainCursorVisible, altCursor.IsVisible()); VERIFY_ARE_EQUAL(mainCursorVisible, altCursor.IsVisible());
Log::Comment(L"Confirm the cursor style is inherited from the main buffer."); Log::Comment(L"Confirm the cursor style is inherited from the main buffer.");
VERIFY_ARE_EQUAL(mainCursorSize, altCursor.GetSize()); VERIFY_ARE_EQUAL(mainCursorSize, altCursor.GetSize());
VERIFY_ARE_EQUAL(mainCursorColor, altCursor.GetColor());
VERIFY_ARE_EQUAL(mainCursorType, altCursor.GetType()); VERIFY_ARE_EQUAL(mainCursorType, altCursor.GetType());
VERIFY_ARE_EQUAL(mainCursorBlinking, altCursor.IsBlinkingAllowed()); VERIFY_ARE_EQUAL(mainCursorBlinking, altCursor.IsBlinkingAllowed());
@ -386,11 +387,12 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
auto altCursorPos = COORD{ 5, 3 }; auto altCursorPos = COORD{ 5, 3 };
auto altCursorVisible = true; auto altCursorVisible = true;
auto altCursorSize = 66u; auto altCursorSize = 66u;
auto altCursorColor = RGB(3, 2, 1);
auto altCursorType = CursorType::EmptyBox; auto altCursorType = CursorType::EmptyBox;
auto altCursorBlinking = true; auto altCursorBlinking = true;
altCursor.SetPosition(altCursorPos); altCursor.SetPosition(altCursorPos);
altCursor.SetIsVisible(altCursorVisible); altCursor.SetIsVisible(altCursorVisible);
altCursor.SetStyle(altCursorSize, altCursorType); altCursor.SetStyle(altCursorSize, altCursorColor, altCursorType);
altCursor.SetBlinkingAllowed(altCursorBlinking); altCursor.SetBlinkingAllowed(altCursorBlinking);
Log::Comment(L"Switch back to the main buffer."); Log::Comment(L"Switch back to the main buffer.");
@ -404,6 +406,7 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
VERIFY_ARE_EQUAL(altCursorVisible, mainCursor.IsVisible()); VERIFY_ARE_EQUAL(altCursorVisible, mainCursor.IsVisible());
Log::Comment(L"Confirm the cursor style is inherited from the alt buffer."); Log::Comment(L"Confirm the cursor style is inherited from the alt buffer.");
VERIFY_ARE_EQUAL(altCursorSize, mainCursor.GetSize()); VERIFY_ARE_EQUAL(altCursorSize, mainCursor.GetSize());
VERIFY_ARE_EQUAL(altCursorColor, mainCursor.GetColor());
VERIFY_ARE_EQUAL(altCursorType, mainCursor.GetType()); VERIFY_ARE_EQUAL(altCursorType, mainCursor.GetType());
VERIFY_ARE_EQUAL(altCursorBlinking, mainCursor.IsBlinkingAllowed()); VERIFY_ARE_EQUAL(altCursorBlinking, mainCursor.IsBlinkingAllowed());
} }
@ -1385,9 +1388,8 @@ void ScreenBufferTests::VtScrollMarginsNewlineColor()
const COLORREF yellow = RGB(255, 255, 0); const COLORREF yellow = RGB(255, 255, 0);
const COLORREF magenta = RGB(255, 0, 255); const COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow); gci.SetDefaultForegroundColor(yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
const TextAttribute defaultAttrs = {}; const TextAttribute defaultAttrs = {};
si.SetAttributes(defaultAttrs); si.SetAttributes(defaultAttrs);
@ -1739,6 +1741,7 @@ void ScreenBufferTests::ResizeCursorUnchanged()
// Get initial cursor values // Get initial cursor values
const CursorType initialType = initialCursor.GetType(); const CursorType initialType = initialCursor.GetType();
const auto initialSize = initialCursor.GetSize(); const auto initialSize = initialCursor.GetSize();
const COLORREF initialColor = initialCursor.GetColor();
// set our wrap mode accordingly - ResizeScreenBuffer will be smart enough // set our wrap mode accordingly - ResizeScreenBuffer will be smart enough
// to call the appropriate implementation // to call the appropriate implementation
@ -1753,8 +1756,10 @@ void ScreenBufferTests::ResizeCursorUnchanged()
const auto& finalCursor = si.GetTextBuffer().GetCursor(); const auto& finalCursor = si.GetTextBuffer().GetCursor();
const CursorType finalType = finalCursor.GetType(); const CursorType finalType = finalCursor.GetType();
const auto finalSize = finalCursor.GetSize(); const auto finalSize = finalCursor.GetSize();
const COLORREF finalColor = finalCursor.GetColor();
VERIFY_ARE_EQUAL(initialType, finalType); VERIFY_ARE_EQUAL(initialType, finalType);
VERIFY_ARE_EQUAL(initialColor, finalColor);
VERIFY_ARE_EQUAL(initialSize, finalSize); VERIFY_ARE_EQUAL(initialSize, finalSize);
} }
@ -2117,6 +2122,7 @@ void ScreenBufferTests::TestAltBufferCursorState()
// Validate that the cursor state was copied appropriately into the // Validate that the cursor state was copied appropriately into the
// alternate buffer // alternate buffer
VERIFY_ARE_EQUAL(mainCursor.GetSize(), altCursor.GetSize()); VERIFY_ARE_EQUAL(mainCursor.GetSize(), altCursor.GetSize());
VERIFY_ARE_EQUAL(mainCursor.GetColor(), altCursor.GetColor());
VERIFY_ARE_EQUAL(mainCursor.GetType(), altCursor.GetType()); VERIFY_ARE_EQUAL(mainCursor.GetType(), altCursor.GetType());
} }
} }
@ -2253,9 +2259,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE); COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow); gci.SetDefaultForegroundColor(yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 6 X's:")); Log::Comment(NoThrowString().Format(L"Write 6 X's:"));
@ -2356,9 +2361,8 @@ void ScreenBufferTests::SetDefaultsTogether()
COLORREF yellow = RGB(255, 255, 0); COLORREF yellow = RGB(255, 255, 0);
COLORREF color250 = gci.GetColorTableEntry(250); COLORREF color250 = gci.GetColorTableEntry(250);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow); gci.SetDefaultForegroundColor(yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 6 X's:")); Log::Comment(NoThrowString().Format(L"Write 6 X's:"));
@ -2428,9 +2432,8 @@ void ScreenBufferTests::ReverseResetWithDefaultBackground()
COLORREF magenta = RGB(255, 0, 255); COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR); gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 3 X's:")); Log::Comment(NoThrowString().Format(L"Write 3 X's:"));
@ -2498,8 +2501,7 @@ void ScreenBufferTests::BackspaceDefaultAttrs()
COLORREF magenta = RGB(255, 0, 255); COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one.")); Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one."));
@ -2562,8 +2564,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsWriteCharsLegacy()
COLORREF magenta = RGB(255, 0, 255); COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one.")); Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one."));
@ -2631,8 +2632,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsInPrompt()
COLORREF magenta = RGB(255, 0, 255); COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta); gci.SetDefaultBackgroundColor(magenta);
gci.CalculateDefaultColorIndices();
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
TextAttribute expectedDefaults{}; TextAttribute expectedDefaults{};
@ -2889,15 +2889,15 @@ void ScreenBufferTests::SetDefaultForegroundColor()
StateMachine& stateMachine = mainBuffer.GetStateMachine(); StateMachine& stateMachine = mainBuffer.GetStateMachine();
COLORREF originalColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); COLORREF originalColor = gci.GetDefaultForegroundColor();
COLORREF newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); COLORREF newColor = gci.GetDefaultForegroundColor();
COLORREF testColor = RGB(0x33, 0x66, 0x99); COLORREF testColor = RGB(0x33, 0x66, 0x99);
VERIFY_ARE_NOT_EQUAL(originalColor, testColor); VERIFY_ARE_NOT_EQUAL(originalColor, testColor);
Log::Comment(L"Valid Hexadecimal Notation"); Log::Comment(L"Valid Hexadecimal Notation");
stateMachine.ProcessString(L"\x1b]10;rgb:33/66/99\x1b\\"); stateMachine.ProcessString(L"\x1b]10;rgb:33/66/99\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); newColor = gci.GetDefaultForegroundColor();
VERIFY_ARE_EQUAL(testColor, newColor); VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Valid Hexadecimal Notation"); Log::Comment(L"Valid Hexadecimal Notation");
@ -2905,7 +2905,7 @@ void ScreenBufferTests::SetDefaultForegroundColor()
testColor = RGB(0xff, 0xff, 0xff); testColor = RGB(0xff, 0xff, 0xff);
stateMachine.ProcessString(L"\x1b]10;rgb:ff/ff/ff\x1b\\"); stateMachine.ProcessString(L"\x1b]10;rgb:ff/ff/ff\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); newColor = gci.GetDefaultForegroundColor();
VERIFY_ARE_EQUAL(testColor, newColor); VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Invalid syntax"); Log::Comment(L"Invalid syntax");
@ -2913,7 +2913,7 @@ void ScreenBufferTests::SetDefaultForegroundColor()
testColor = RGB(153, 102, 51); testColor = RGB(153, 102, 51);
stateMachine.ProcessString(L"\x1b]10;99/66/33\x1b\\"); stateMachine.ProcessString(L"\x1b]10;99/66/33\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); newColor = gci.GetDefaultForegroundColor();
VERIFY_ARE_NOT_EQUAL(testColor, newColor); VERIFY_ARE_NOT_EQUAL(testColor, newColor);
// it will, in fact leave the color the way it was // it will, in fact leave the color the way it was
VERIFY_ARE_EQUAL(originalColor, newColor); VERIFY_ARE_EQUAL(originalColor, newColor);
@ -2934,15 +2934,15 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
StateMachine& stateMachine = mainBuffer.GetStateMachine(); StateMachine& stateMachine = mainBuffer.GetStateMachine();
COLORREF originalColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); COLORREF originalColor = gci.GetDefaultBackgroundColor();
COLORREF newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); COLORREF newColor = gci.GetDefaultBackgroundColor();
COLORREF testColor = RGB(0x33, 0x66, 0x99); COLORREF testColor = RGB(0x33, 0x66, 0x99);
VERIFY_ARE_NOT_EQUAL(originalColor, testColor); VERIFY_ARE_NOT_EQUAL(originalColor, testColor);
Log::Comment(L"Valid Hexadecimal Notation"); Log::Comment(L"Valid Hexadecimal Notation");
stateMachine.ProcessString(L"\x1b]11;rgb:33/66/99\x1b\\"); stateMachine.ProcessString(L"\x1b]11;rgb:33/66/99\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); newColor = gci.GetDefaultBackgroundColor();
VERIFY_ARE_EQUAL(testColor, newColor); VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Valid Hexadecimal Notation"); Log::Comment(L"Valid Hexadecimal Notation");
@ -2950,7 +2950,7 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
testColor = RGB(0xff, 0xff, 0xff); testColor = RGB(0xff, 0xff, 0xff);
stateMachine.ProcessString(L"\x1b]11;rgb:ff/ff/ff\x1b\\"); stateMachine.ProcessString(L"\x1b]11;rgb:ff/ff/ff\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); newColor = gci.GetDefaultBackgroundColor();
VERIFY_ARE_EQUAL(testColor, newColor); VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Invalid Syntax"); Log::Comment(L"Invalid Syntax");
@ -2958,7 +2958,7 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
testColor = RGB(153, 102, 51); testColor = RGB(153, 102, 51);
stateMachine.ProcessString(L"\x1b]11;99/66/33\x1b\\"); stateMachine.ProcessString(L"\x1b]11;99/66/33\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); newColor = gci.GetDefaultBackgroundColor();
VERIFY_ARE_NOT_EQUAL(testColor, newColor); VERIFY_ARE_NOT_EQUAL(testColor, newColor);
// it will, in fact leave the color the way it was // it will, in fact leave the color the way it was
VERIFY_ARE_EQUAL(originalColor, newColor); VERIFY_ARE_EQUAL(originalColor, newColor);
@ -5978,7 +5978,7 @@ void ScreenBufferTests::TestAddHyperlink()
auto& stateMachine = si.GetStateMachine(); auto& stateMachine = si.GetStateMachine();
// Process the opening osc 8 sequence with no custom id // Process the opening osc 8 sequence with no custom id
stateMachine.ProcessString(L"\x1b]8;;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
@ -5988,7 +5988,7 @@ void ScreenBufferTests::TestAddHyperlink()
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
// Process the closing osc 8 sequences // Process the closing osc 8 sequences
stateMachine.ProcessString(L"\x1b]8;;\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;\x9c");
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
} }
@ -6001,7 +6001,7 @@ void ScreenBufferTests::TestAddHyperlinkCustomId()
auto& stateMachine = si.GetStateMachine(); auto& stateMachine = si.GetStateMachine();
// Process the opening osc 8 sequence with a custom id // Process the opening osc 8 sequence with a custom id
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
@ -6013,7 +6013,7 @@ void ScreenBufferTests::TestAddHyperlinkCustomId()
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
// Process the closing osc 8 sequences // Process the closing osc 8 sequences
stateMachine.ProcessString(L"\x1b]8;;\x1b\\"); stateMachine.ProcessString(L"\x1b]8;;\x9c");
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
} }
@ -6026,7 +6026,7 @@ void ScreenBufferTests::TestAddHyperlinkCustomIdDifferentUri()
auto& stateMachine = si.GetStateMachine(); auto& stateMachine = si.GetStateMachine();
// Process the opening osc 8 sequence with a custom id // Process the opening osc 8 sequence with a custom id
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
@ -6034,7 +6034,7 @@ void ScreenBufferTests::TestAddHyperlinkCustomIdDifferentUri()
const auto oldAttributes{ tbi.GetCurrentAttributes() }; const auto oldAttributes{ tbi.GetCurrentAttributes() };
// Send any other text // Send any other text
stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x1b\\"); stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x9c");
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink()); VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url"); VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url");
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId()); VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());

View file

@ -37,3 +37,4 @@ enum class CursorType : unsigned int
constexpr COLORREF INVALID_COLOR = 0xffffffff; constexpr COLORREF INVALID_COLOR = 0xffffffff;
constexpr WORD COLOR_TABLE_SIZE = 16; constexpr WORD COLOR_TABLE_SIZE = 16;
constexpr WORD XTERM_COLOR_TABLE_SIZE = 256;

View file

@ -37,3 +37,23 @@ constexpr bool operator!=(const SMALL_RECT& a, const SMALL_RECT& b) noexcept
{ {
return !(a == b); return !(a == b);
} }
constexpr bool operator==(const std::wstring& wstr, const std::wstring_view& wstrView)
{
return (wstrView == std::wstring_view{ wstr.c_str(), wstr.size() });
}
constexpr bool operator==(const std::wstring_view& wstrView, const std::wstring& wstr)
{
return (wstr == wstrView);
}
constexpr bool operator!=(const std::wstring& wstr, const std::wstring_view& wstrView)
{
return !(wstr == wstrView);
}
constexpr bool operator!=(const std::wstring_view& wstrView, const std::wstring& wstr)
{
return !(wstr == wstrView);
}

View file

@ -3,136 +3,130 @@
#pragma once #pragma once
#ifdef __cpp_concepts #include <bitset>
#define TIL_ENUMSET_VARARG template<std::same_as<T>... Args>
#else
#define TIL_ENUMSET_VARARG template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<T, Args>...>>>
#endif
namespace til // Terminal Implementation Library. Also: "Today I Learned" namespace til // Terminal Implementation Library. Also: "Today I Learned"
{ {
// til::enumset stores a fixed size array of boolean elements, the positions // By design, this class hides several methods in the std::bitset class
// in the array being identified by values from a given enumerated type. // so they can be called with an enum parameter instead of a size_t, so
// Position N corresponds to bit 1<<N in the UnderlyingType integer. // we need to disable the "hides a non-virtual function" warning.
// #pragma warning(push)
// If you only need 32 positions for your T, UnderlyingType can be set uint32_t. #pragma warning(disable : 26434)
// It defaults to uintptr_t allowing you to set as many positions as a pointer has bits.
// This class doesn't statically assert that your given position fits into UnderlyingType. // til::enumset is a subclass of std::bitset, storing a fixed size array of
template<typename T, typename UnderlyingType = uintptr_t> // boolean elements, the positions in the array being identified by values
class enumset // from a given enumerated type. By default it holds the same number of
// bits as a size_t value.
template<typename Type, size_t Bits = std::numeric_limits<size_t>::digits>
class enumset : public std::bitset<Bits>
{ {
static_assert(std::is_unsigned_v<UnderlyingType>); using _base = std::bitset<Bits>;
public: public:
using reference = typename _base::reference;
enumset() = default;
// Method Description: // Method Description:
// - Constructs a new bitset with the given list of positions set to true. // - Constructs a new bitset with the given list of positions set to true.
TIL_ENUMSET_VARARG template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
constexpr enumset(Args... positions) noexcept : constexpr enumset(const Args... positions) noexcept :
_data{ to_underlying(positions...) } _base((... | (1ULL << static_cast<size_t>(positions))))
{ {
} }
// Method Description: // Method Description:
// - Returns the underlying bit positions as a copy. // - Returns the value of the bit at the given position.
constexpr UnderlyingType bits() const noexcept constexpr bool operator[](const Type pos) const
{ {
return _data; return _base::operator[](static_cast<size_t>(pos));
}
// Method Description:
// - Returns a reference to the bit at the given position.
reference operator[](const Type pos)
{
return _base::operator[](static_cast<size_t>(pos));
} }
// Method Description: // Method Description:
// - Returns the value of the bit at the given position. // - Returns the value of the bit at the given position.
// Throws std::out_of_range if it is not a valid position // Throws std::out_of_range if it is not a valid position
// in the bitset. // in the bitset.
constexpr bool test(const T pos) const noexcept bool test(const Type pos) const
{ {
const auto mask = to_underlying(pos); return _base::test(static_cast<size_t>(pos));
return (_data & mask) != 0;
} }
// Method Description: // Method Description:
// - Returns true if any of the bits are set to true. // - Returns true if any of the bits are set to true.
constexpr bool any() const noexcept bool any() const noexcept
{ {
return _data != 0; return _base::any();
} }
// Method Description: // Method Description:
// - Returns true if any of the bits in the given positions are true. // - Returns true if any of the bits in the given positions are true.
TIL_ENUMSET_VARARG template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
constexpr bool any(Args... positions) const noexcept bool any(const Args... positions) const noexcept
{ {
const auto mask = to_underlying(positions...); return (enumset{ positions... } & *this) != 0;
return (_data & mask) != 0;
} }
// Method Description: // Method Description:
// - Returns true if all of the bits are set to true. // - Returns true if all of the bits are set to true.
constexpr bool all() const noexcept bool all() const noexcept
{ {
return _data == ~UnderlyingType{ 0 }; return _base::all();
} }
// Method Description: // Method Description:
// - Returns true if all of the bits in the given positions are true. // - Returns true if all of the bits in the given positions are true.
TIL_ENUMSET_VARARG template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
constexpr bool all(Args... positions) const noexcept bool all(const Args... positions) const noexcept
{ {
const auto mask = to_underlying(positions...); return (enumset{ positions... } & *this) == enumset{ positions... };
return (_data & mask) == mask;
}
// Method Description:
// - Sets all of the bits in the given positions to true.
TIL_ENUMSET_VARARG
constexpr enumset& set(Args... positions) noexcept
{
_data |= to_underlying(positions...);
return *this;
} }
// Method Description: // Method Description:
// - Sets the bit in the given position to the specified value. // - Sets the bit in the given position to the specified value.
constexpr enumset& set(const T pos, const bool val) noexcept enumset& set(const Type pos, const bool val = true)
{ {
const auto mask = to_underlying(pos); _base::set(static_cast<size_t>(pos), val);
// false == 0 --> UnderlyingType(-0) == 0b0000...
// true == 1 --> UnderlyingType(-1) == 0b1111...
#pragma warning(suppress : 4804) // '-': unsafe use of type 'bool' in operation
_data = (_data & ~mask) | (-val & mask);
return *this; return *this;
} }
// Method Description: // Method Description:
// - Resets all of the bits in the given positions to false. // - Resets the bit in the given position to false.
TIL_ENUMSET_VARARG enumset& reset(const Type pos)
constexpr enumset& reset(Args... positions) noexcept
{ {
_data &= ~to_underlying(positions...); _base::reset(static_cast<size_t>(pos));
return *this; return *this;
} }
// Method Description: // Method Description:
// - Flips the bit at the given position. // - Flips the bit at the given position.
TIL_ENUMSET_VARARG enumset& flip(const Type pos)
constexpr enumset& flip(Args... positions) noexcept
{ {
_data ^= to_underlying(positions...); _base::flip(static_cast<size_t>(pos));
return *this; return *this;
} }
private: // Method Description:
// - Sets all of the bits in the given positions to true.
template<typename... Args> template<typename... Args>
static constexpr UnderlyingType to_underlying(Args... positions) noexcept enumset& set_all(const Args... positions)
{ {
return ((UnderlyingType{ 1 } << static_cast<UnderlyingType>(positions)) | ...); return (..., set(positions));
} }
template<> // Method Description:
static constexpr UnderlyingType to_underlying() noexcept // - Resets all of the bits in the given positions to false.
template<typename... Args>
enumset& reset_all(const Args... positions)
{ {
return 0; return (..., reset(positions));
} }
UnderlyingType _data{};
}; };
#pragma warning(pop)
} }

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license. // Licensed under the MIT license.
#pragma once #pragma once
@ -34,7 +34,10 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
template<typename T, typename Traits> template<typename T, typename Traits>
constexpr bool starts_with(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& prefix) noexcept constexpr bool starts_with(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& prefix) noexcept
{ {
return str.size() >= prefix.size() && __builtin_memcmp(str.data(), prefix.data(), prefix.size() * sizeof(T)) == 0; #ifdef __cpp_lib_starts_ends_with
#error This code can be replaced in C++20, which natively supports .starts_with().
#endif
return str.size() >= prefix.size() && Traits::compare(str.data(), prefix.data(), prefix.size()) == 0;
} }
constexpr bool starts_with(const std::string_view& str, const std::string_view& prefix) noexcept constexpr bool starts_with(const std::string_view& str, const std::string_view& prefix) noexcept
@ -49,10 +52,15 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
// std::string_view::ends_with support for C++17. // std::string_view::ends_with support for C++17.
template<typename T, typename Traits> template<typename T, typename Traits>
constexpr bool ends_with(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& suffix) noexcept constexpr bool ends_with(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& prefix) noexcept
{ {
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1). #ifdef __cpp_lib_ends_ends_with
return str.size() >= suffix.size() && __builtin_memcmp(str.data() + (str.size() - suffix.size()), suffix.data(), suffix.size() * sizeof(T)) == 0; #error This code can be replaced in C++20, which natively supports .ends_with().
#endif
#pragma warning(push)
#pragma warning(disable : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
return str.size() >= prefix.size() && Traits::compare(str.data() + (str.size() - prefix.size()), prefix.data(), prefix.size()) == 0;
#pragma warning(pop)
} }
constexpr bool ends_with(const std::string_view& str, const std::string_view& prefix) noexcept constexpr bool ends_with(const std::string_view& str, const std::string_view& prefix) noexcept
@ -160,20 +168,6 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return c; return c;
} }
// Just like std::wstring_view::operator==().
//
// At the time of writing wmemcmp() is not an intrinsic for MSVC,
// but the STL uses it to implement wide string comparisons.
// This produces 3x the assembly _per_ comparison and increases
// runtime by 2-3x for strings of medium length (16 characters)
// and 5x or more for long strings (128 characters or more).
// See: https://github.com/microsoft/STL/issues/2289
template<typename T, typename Traits>
bool equals(const std::basic_string_view<T, Traits>& str1, const std::basic_string_view<T, Traits>& str2) noexcept
{
return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
}
// Just like _memicmp, but without annoying locales. // Just like _memicmp, but without annoying locales.
template<typename T, typename Traits> template<typename T, typename Traits>
bool equals_insensitive_ascii(const std::basic_string_view<T, Traits>& str1, const std::basic_string_view<T, Traits>& str2) noexcept bool equals_insensitive_ascii(const std::basic_string_view<T, Traits>& str1, const std::basic_string_view<T, Traits>& str2) noexcept
@ -211,39 +205,6 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return equals_insensitive_ascii<>(str1, str2); return equals_insensitive_ascii<>(str1, str2);
} }
template<typename T, typename Traits>
constexpr bool starts_with_insensitive_ascii(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& prefix) noexcept
{
return str.size() >= prefix.size() && equals_insensitive_ascii<>({ str.data(), prefix.size() }, prefix);
}
constexpr bool starts_with_insensitive_ascii(const std::string_view& str, const std::string_view& prefix) noexcept
{
return starts_with_insensitive_ascii<>(str, prefix);
}
constexpr bool starts_with_insensitive_ascii(const std::wstring_view& str, const std::wstring_view& prefix) noexcept
{
return starts_with_insensitive_ascii<>(str, prefix);
}
template<typename T, typename Traits>
constexpr bool ends_with_insensitive_ascii(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& suffix) noexcept
{
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
return str.size() >= suffix.size() && equals_insensitive_ascii<>({ str.data() - suffix.size(), suffix.size() }, suffix);
}
constexpr bool ends_with_insensitive_ascii(const std::string_view& str, const std::string_view& prefix) noexcept
{
return ends_with_insensitive_ascii<>(str, prefix);
}
constexpr bool ends_with_insensitive_ascii(const std::wstring_view& str, const std::wstring_view& prefix) noexcept
{
return ends_with<>(str, prefix);
}
// Give the arguments ("foo bar baz", " "), this method will // Give the arguments ("foo bar baz", " "), this method will
// * modify the first argument to "bar baz" // * modify the first argument to "bar baz"
// * return "foo" // * return "foo"

View file

@ -208,8 +208,10 @@ 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 defaultForeground = gci.GetDefaultForeground();
const auto defaultBackground = gci.GetDefaultBackground();
const auto GetAttributeColors = [=, &gci](const auto& attr) { const auto GetAttributeColors = [=, &gci](const auto& attr) {
return gci.LookupAttributeColors(attr); return gci.LookupAttributeColors(attr, defaultForeground, defaultBackground);
}; };
bool includeCRLF, trimTrailingWhitespace; bool includeCRLF, trimTrailingWhitespace;
@ -274,10 +276,9 @@ void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows,
if (fAlsoCopyFormatting) if (fAlsoCopyFormatting)
{ {
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); const auto& fontData = ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetCurrentFont();
const auto& fontData = gci.GetActiveOutputBuffer().GetCurrentFont();
int const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi; int const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi;
const COLORREF bgColor = gci.GetColorTableEntry(gci.GetDefaultBackgroundIndex()); const COLORREF bgColor = ServiceLocator::LocateGlobals().getConsoleInformation().GetDefaultBackground();
std::string HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor); std::string HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
CopyToSystemClipboard(HTMLToPlaceOnClip, L"HTML Format"); CopyToSystemClipboard(HTMLToPlaceOnClip, L"HTML Format");

View file

@ -315,7 +315,7 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
const Cursor& cursor = ScreenInfo.GetTextBuffer().GetCursor(); const Cursor& cursor = ScreenInfo.GetTextBuffer().GetCursor();
pStateInfo->CursorSize = cursor.GetSize(); pStateInfo->CursorSize = cursor.GetSize();
pStateInfo->CursorColor = gci.GetColorTableEntry(TextColor::CURSOR_COLOR); pStateInfo->CursorColor = cursor.GetColor();
pStateInfo->CursorType = static_cast<unsigned int>(cursor.GetType()); pStateInfo->CursorType = static_cast<unsigned int>(cursor.GetType());
// Retrieve small icon for use in displaying the dialog // Retrieve small icon for use in displaying the dialog
@ -376,8 +376,8 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
pStateInfo->InterceptCopyPaste = gci.GetInterceptCopyPaste(); pStateInfo->InterceptCopyPaste = gci.GetInterceptCopyPaste();
// Get the properties from the settings // Get the properties from the settings
pStateInfo->DefaultForeground = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND); pStateInfo->DefaultForeground = gci.GetDefaultForegroundColor();
pStateInfo->DefaultBackground = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND); pStateInfo->DefaultBackground = gci.GetDefaultBackgroundColor();
pStateInfo->TerminalScrolling = gci.IsTerminalScrolling(); pStateInfo->TerminalScrolling = gci.IsTerminalScrolling();
// end console v2 properties // end console v2 properties
@ -461,12 +461,13 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
// Set the cursor properties in the Settings // Set the cursor properties in the Settings
const auto cursorType = static_cast<CursorType>(pStateInfo->CursorType); const auto cursorType = static_cast<CursorType>(pStateInfo->CursorType);
gci.SetCursorColor(pStateInfo->CursorColor);
gci.SetCursorType(cursorType); gci.SetCursorType(cursorType);
gci.SetColorTableEntry(TextColor::CURSOR_COLOR, pStateInfo->CursorColor);
// Then also apply them to the buffer's cursor // Then also apply them to the buffer's cursor
ScreenInfo.SetCursorInformation(pStateInfo->CursorSize, ScreenInfo.SetCursorInformation(pStateInfo->CursorSize,
ScreenInfo.GetTextBuffer().GetCursor().IsVisible()); ScreenInfo.GetTextBuffer().GetCursor().IsVisible());
ScreenInfo.SetCursorColor(pStateInfo->CursorColor, true);
ScreenInfo.SetCursorType(cursorType, true); ScreenInfo.SetCursorType(cursorType, true);
gci.SetTerminalScrolling(pStateInfo->TerminalScrolling); gci.SetTerminalScrolling(pStateInfo->TerminalScrolling);
@ -578,13 +579,11 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
gci.SetFillAttribute(pStateInfo->ScreenAttributes); gci.SetFillAttribute(pStateInfo->ScreenAttributes);
gci.SetPopupFillAttribute(pStateInfo->PopupAttributes); gci.SetPopupFillAttribute(pStateInfo->PopupAttributes);
// Store our updated Default Color values // Store our updated Default Color values
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, pStateInfo->DefaultForeground); gci.SetDefaultForegroundColor(pStateInfo->DefaultForeground);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, pStateInfo->DefaultBackground); gci.SetDefaultBackgroundColor(pStateInfo->DefaultBackground);
// Make sure the updated fill attributes are passed on to the TextAttribute class. // Make sure the updated fill attributes are passed on to the TextAttribute class.
TextAttribute::SetLegacyDefaultAttributes(pStateInfo->ScreenAttributes); TextAttribute::SetLegacyDefaultAttributes(pStateInfo->ScreenAttributes);
// And recalculate the position of the default colors in the color table.
gci.CalculateDefaultColorIndices();
// Set the screen info's default text attributes to defaults - // Set the screen info's default text attributes to defaults -
ScreenInfo.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() }); ScreenInfo.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });

View file

@ -574,10 +574,6 @@ using namespace Microsoft::Console::Types;
{ {
Menu::s_ShowPropertiesDialog(hWnd, TRUE); Menu::s_ShowPropertiesDialog(hWnd, TRUE);
} }
else if (wParam == SC_RESTORE && _fIsInFullscreen)
{
SetIsFullscreen(false);
}
else else
{ {
goto CallDefWin; goto CallDefWin;

View file

@ -78,10 +78,8 @@
<AdditionalIncludeDirectories>$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile> </ResourceCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<!-- If you don't include a '.' at the end of the $(IntermediateOutputPath),
mc.exe will get confused by the trailing slash. -->
<Target Name="MessageCompile" Inputs="@(MessageCompile)" Outputs="$(IntermediateOutputPath)\%(MessageCompile.Filename).h" BeforeTargets="ClCompile"> <Target Name="MessageCompile" Inputs="@(MessageCompile)" Outputs="$(IntermediateOutputPath)\%(MessageCompile.Filename).h" BeforeTargets="ClCompile">
<Exec Command="mc.exe /h &quot;$(IntermediateOutputPath).&quot; /r &quot;$(IntermediateOutputPath).&quot; @(MessageCompile)" /> <Exec Command="mc.exe /h $(IntermediateOutputPath) /r $(IntermediateOutputPath) @(MessageCompile)" />
</Target> </Target>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. --> <!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="..\common.build.post.props" /> <Import Project="..\common.build.post.props" />

View file

@ -7,7 +7,7 @@
#pragma hdrstop #pragma hdrstop
#define SET_FIELD_AND_SIZE(x) UFIELD_OFFSET(Settings, x), RTL_FIELD_SIZE(Settings, x) #define SET_FIELD_AND_SIZE(x) FIELD_OFFSET(Settings, x), RTL_FIELD_SIZE(Settings, x)
#define NT_TESTNULL(var) (((var) == nullptr) ? STATUS_NO_MEMORY : STATUS_SUCCESS) #define NT_TESTNULL(var) (((var) == nullptr) ? STATUS_NO_MEMORY : STATUS_SUCCESS)
@ -57,14 +57,14 @@ const RegistrySerialization::_RegPropertyMap RegistrySerialization::s_PropertyMa
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TRIMZEROHEADINGS, SET_FIELD_AND_SIZE(_fTrimLeadingZeros) }, { _RegPropertyType::Boolean, CONSOLE_REGISTRY_TRIMZEROHEADINGS, SET_FIELD_AND_SIZE(_fTrimLeadingZeros) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_ENABLE_COLOR_SELECTION, SET_FIELD_AND_SIZE(_fEnableColorSelection) }, { _RegPropertyType::Boolean, CONSOLE_REGISTRY_ENABLE_COLOR_SELECTION, SET_FIELD_AND_SIZE(_fEnableColorSelection) },
{ _RegPropertyType::Coordinate, CONSOLE_REGISTRY_WINDOWPOS, SET_FIELD_AND_SIZE(_dwWindowOrigin) }, { _RegPropertyType::Coordinate, CONSOLE_REGISTRY_WINDOWPOS, SET_FIELD_AND_SIZE(_dwWindowOrigin) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORCOLOR, SET_FIELD_AND_SIZE(_CursorColor) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORTYPE, SET_FIELD_AND_SIZE(_CursorType) }, { _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORTYPE, SET_FIELD_AND_SIZE(_CursorType) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_INTERCEPTCOPYPASTE, SET_FIELD_AND_SIZE(_fInterceptCopyPaste) }, { _RegPropertyType::Boolean, CONSOLE_REGISTRY_INTERCEPTCOPYPASTE, SET_FIELD_AND_SIZE(_fInterceptCopyPaste) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_DefaultForeground) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_DefaultBackground) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) }, { _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) }, { _RegPropertyType::Dword, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) }, { _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) }
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_colorTable[TextColor::DEFAULT_FOREGROUND]) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_colorTable[TextColor::DEFAULT_BACKGROUND]) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORCOLOR, SET_FIELD_AND_SIZE(_colorTable[TextColor::CURSOR_COLOR]) }
}; };
const size_t RegistrySerialization::s_PropertyMappingsSize = ARRAYSIZE(s_PropertyMappings); const size_t RegistrySerialization::s_PropertyMappingsSize = ARRAYSIZE(s_PropertyMappings);

View file

@ -96,11 +96,6 @@ bool DxFontInfo::GetFallback() const noexcept
return _didFallback; return _didFallback;
} }
IDWriteFontCollection* DxFontInfo::GetNearbyCollection() const noexcept
{
return _nearbyCollection.Get();
}
void DxFontInfo::SetFromEngine(const std::wstring_view familyName, void DxFontInfo::SetFromEngine(const std::wstring_view familyName,
const DWRITE_FONT_WEIGHT weight, const DWRITE_FONT_WEIGHT weight,
const DWRITE_FONT_STYLE style, const DWRITE_FONT_STYLE style,
@ -228,11 +223,13 @@ void DxFontInfo::SetFromEngine(const std::wstring_view familyName,
// If the system collection missed, try the files sitting next to our binary. // If the system collection missed, try the files sitting next to our binary.
if (withNearbyLookup && !familyExists) if (withNearbyLookup && !familyExists)
{ {
auto&& nearbyCollection = _NearbyCollection(dwriteFactory);
// May be null on OS below Windows 10. If null, just skip the attempt. // May be null on OS below Windows 10. If null, just skip the attempt.
if (const auto nearbyCollection = _NearbyCollection(dwriteFactory)) if (nearbyCollection)
{ {
THROW_IF_FAILED(nearbyCollection->FindFamilyName(_familyName.data(), &familyIndex, &familyExists)); nearbyCollection.As(&fontCollection);
fontCollection = nearbyCollection; THROW_IF_FAILED(fontCollection->FindFamilyName(_familyName.data(), &familyIndex, &familyExists));
} }
} }
@ -335,48 +332,42 @@ void DxFontInfo::SetFromEngine(const std::wstring_view familyName,
// - dwriteFactory - The DWrite factory to use // - dwriteFactory - The DWrite factory to use
// Return Value: // Return Value:
// - DirectWrite font collection. May be null if one cannot be created. // - DirectWrite font collection. May be null if one cannot be created.
[[nodiscard]] IDWriteFontCollection* DxFontInfo::_NearbyCollection(gsl::not_null<IDWriteFactory1*> dwriteFactory) [[nodiscard]] const Microsoft::WRL::ComPtr<IDWriteFontCollection1>& DxFontInfo::_NearbyCollection(gsl::not_null<IDWriteFactory1*> dwriteFactory) const
{ {
if (_nearbyCollection)
{
return _nearbyCollection.Get();
}
// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
::Microsoft::WRL::ComPtr<IDWriteFactory6> factory6;
if (FAILED(dwriteFactory->QueryInterface<IDWriteFactory6>(&factory6)))
{
return nullptr;
}
::Microsoft::WRL::ComPtr<IDWriteFontCollection1> systemFontCollection;
THROW_IF_FAILED(factory6->GetSystemFontCollection(false, &systemFontCollection, 0));
::Microsoft::WRL::ComPtr<IDWriteFontSet> systemFontSet;
THROW_IF_FAILED(systemFontCollection->GetFontSet(&systemFontSet));
::Microsoft::WRL::ComPtr<IDWriteFontSetBuilder2> fontSetBuilder2;
THROW_IF_FAILED(factory6->CreateFontSetBuilder(&fontSetBuilder2));
THROW_IF_FAILED(fontSetBuilder2->AddFontSet(systemFontSet.Get()));
// Magic static so we only attempt to grovel the hard disk once no matter how many instances // Magic static so we only attempt to grovel the hard disk once no matter how many instances
// of the font collection itself we require. // of the font collection itself we require.
static const auto knownPaths = s_GetNearbyFonts(); static const auto knownPaths = s_GetNearbyFonts();
for (auto& p : knownPaths)
// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
// Don't try to look up if below that OS version.
static const bool s_isWindows10OrGreater = IsWindows10OrGreater();
if (s_isWindows10OrGreater && !_nearbyCollection)
{ {
fontSetBuilder2->AddFontFile(p.c_str()); // Factory3 has a convenience to get us a font set builder.
::Microsoft::WRL::ComPtr<IDWriteFactory3> factory3;
THROW_IF_FAILED(dwriteFactory->QueryInterface<IDWriteFactory3>(&factory3));
::Microsoft::WRL::ComPtr<IDWriteFontSetBuilder> fontSetBuilder;
THROW_IF_FAILED(factory3->CreateFontSetBuilder(&fontSetBuilder));
// Builder2 has a convenience to just feed in paths to font files.
::Microsoft::WRL::ComPtr<IDWriteFontSetBuilder2> fontSetBuilder2;
THROW_IF_FAILED(fontSetBuilder.As(&fontSetBuilder2));
for (auto& p : knownPaths)
{
fontSetBuilder2->AddFontFile(p.c_str());
}
::Microsoft::WRL::ComPtr<IDWriteFontSet> fontSet;
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(&fontSet));
THROW_IF_FAILED(factory3->CreateFontCollectionFromFontSet(fontSet.Get(), &_nearbyCollection));
} }
::Microsoft::WRL::ComPtr<IDWriteFontSet> fontSet; return _nearbyCollection;
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(&fontSet));
::Microsoft::WRL::ComPtr<IDWriteFontCollection1> fontCollection;
THROW_IF_FAILED(factory6->CreateFontCollectionFromFontSet(fontSet.Get(), &fontCollection));
_nearbyCollection = fontCollection;
return _nearbyCollection.Get();
} }
// Routine Description: // Routine Description:
@ -395,11 +386,18 @@ void DxFontInfo::SetFromEngine(const std::wstring_view familyName,
const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) }; const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
const auto folder{ module.parent_path() }; const auto folder{ module.parent_path() };
for (const auto& p : std::filesystem::directory_iterator(folder)) for (auto& p : std::filesystem::directory_iterator(folder))
{ {
if (til::ends_with(p.path().native(), L".ttf")) if (p.is_regular_file())
{ {
paths.push_back(p.path()); auto extension = p.path().extension().wstring();
std::transform(extension.begin(), extension.end(), extension.begin(), std::towlower);
static constexpr std::wstring_view ttfExtension{ L".ttf" };
if (ttfExtension == extension)
{
paths.push_back(p);
}
} }
} }

View file

@ -41,8 +41,6 @@ namespace Microsoft::Console::Render
bool GetFallback() const noexcept; bool GetFallback() const noexcept;
IDWriteFontCollection* GetNearbyCollection() const noexcept;
void SetFromEngine(const std::wstring_view familyName, void SetFromEngine(const std::wstring_view familyName,
const DWRITE_FONT_WEIGHT weight, const DWRITE_FONT_WEIGHT weight,
const DWRITE_FONT_STYLE style, const DWRITE_FONT_STYLE style,
@ -59,11 +57,11 @@ namespace Microsoft::Console::Render
[[nodiscard]] std::wstring _GetFontFamilyName(gsl::not_null<IDWriteFontFamily*> const fontFamily, [[nodiscard]] std::wstring _GetFontFamilyName(gsl::not_null<IDWriteFontFamily*> const fontFamily,
std::wstring& localeName); std::wstring& localeName);
[[nodiscard]] IDWriteFontCollection* _NearbyCollection(gsl::not_null<IDWriteFactory1*> dwriteFactory); [[nodiscard]] const Microsoft::WRL::ComPtr<IDWriteFontCollection1>& _NearbyCollection(gsl::not_null<IDWriteFactory1*> dwriteFactory) const;
[[nodiscard]] static std::vector<std::filesystem::path> s_GetNearbyFonts(); [[nodiscard]] static std::vector<std::filesystem::path> s_GetNearbyFonts();
::Microsoft::WRL::ComPtr<IDWriteFontCollection> _nearbyCollection; mutable ::Microsoft::WRL::ComPtr<IDWriteFontCollection1> _nearbyCollection;
// The font name we should be looking for // The font name we should be looking for
std::wstring _familyName; std::wstring _familyName;

View file

@ -894,11 +894,11 @@ void DxFontRenderData::_BuildFontRenderData(const FontInfoDesired& desired, Font
_glyphCell = actual.GetSize(); _glyphCell = actual.GetSize();
} }
Microsoft::WRL::ComPtr<IDWriteTextFormat> DxFontRenderData::_BuildTextFormat(const DxFontInfo& fontInfo, const std::wstring_view localeName) Microsoft::WRL::ComPtr<IDWriteTextFormat> DxFontRenderData::_BuildTextFormat(const DxFontInfo fontInfo, const std::wstring_view localeName)
{ {
Microsoft::WRL::ComPtr<IDWriteTextFormat> format; Microsoft::WRL::ComPtr<IDWriteTextFormat> format;
THROW_IF_FAILED(_dwriteFactory->CreateTextFormat(fontInfo.GetFamilyName().data(), THROW_IF_FAILED(_dwriteFactory->CreateTextFormat(fontInfo.GetFamilyName().data(),
fontInfo.GetNearbyCollection(), nullptr,
fontInfo.GetWeight(), fontInfo.GetWeight(),
fontInfo.GetStyle(), fontInfo.GetStyle(),
fontInfo.GetStretch(), fontInfo.GetStretch(),

View file

@ -122,7 +122,7 @@ namespace Microsoft::Console::Render
float _FontStretchToWidthAxisValue(DWRITE_FONT_STRETCH fontStretch) noexcept; float _FontStretchToWidthAxisValue(DWRITE_FONT_STRETCH fontStretch) noexcept;
float _FontStyleToSlantFixedAxisValue(DWRITE_FONT_STYLE fontStyle) noexcept; float _FontStyleToSlantFixedAxisValue(DWRITE_FONT_STYLE fontStyle) noexcept;
void _BuildFontRenderData(const FontInfoDesired& desired, FontInfo& actual, const int dpi); void _BuildFontRenderData(const FontInfoDesired& desired, FontInfo& actual, const int dpi);
Microsoft::WRL::ComPtr<IDWriteTextFormat> _BuildTextFormat(const DxFontInfo& fontInfo, const std::wstring_view localeName); Microsoft::WRL::ComPtr<IDWriteTextFormat> _BuildTextFormat(const DxFontInfo fontInfo, const std::wstring_view localeName);
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap; std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap;
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap; std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap;

View file

@ -18,21 +18,21 @@
<ClCompile Include="..\BoxDrawingEffect.cpp" /> <ClCompile Include="..\BoxDrawingEffect.cpp" />
<ClCompile Include="..\CustomTextLayout.cpp" /> <ClCompile Include="..\CustomTextLayout.cpp" />
<ClCompile Include="..\CustomTextRenderer.cpp" /> <ClCompile Include="..\CustomTextRenderer.cpp" />
<ClCompile Include="..\DxFontInfo.cpp" />
<ClCompile Include="..\DxFontRenderData.cpp" />
<ClCompile Include="..\DxRenderer.cpp" />
<ClCompile Include="..\precomp.cpp"> <ClCompile Include="..\precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="..\DxFontInfo.cpp" />
<ClCompile Include="..\DxFontRenderData.cpp" />
<ClCompile Include="..\DxRenderer.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\BoxDrawingEffect.h" /> <ClInclude Include="..\BoxDrawingEffect.h" />
<ClInclude Include="..\CustomTextLayout.h" /> <ClInclude Include="..\CustomTextLayout.h" />
<ClInclude Include="..\CustomTextRenderer.h" /> <ClInclude Include="..\CustomTextRenderer.h" />
<ClInclude Include="..\precomp.h" />
<ClInclude Include="..\DxRenderer.hpp" />
<ClInclude Include="..\DxFontInfo.h" /> <ClInclude Include="..\DxFontInfo.h" />
<ClInclude Include="..\DxFontRenderData.h" /> <ClInclude Include="..\DxFontRenderData.h" />
<ClInclude Include="..\DxRenderer.hpp" />
<ClInclude Include="..\precomp.h" />
<ClInclude Include="..\ScreenPixelShader.h" /> <ClInclude Include="..\ScreenPixelShader.h" />
<ClInclude Include="..\ScreenVertexShader.h" /> <ClInclude Include="..\ScreenVertexShader.h" />
</ItemGroup> </ItemGroup>

View file

@ -4,26 +4,24 @@
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" /> <Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\BoxDrawingEffect.cpp" />
<ClCompile Include="..\CustomTextLayout.cpp" /> <ClCompile Include="..\CustomTextLayout.cpp" />
<ClCompile Include="..\CustomTextRenderer.cpp" /> <ClCompile Include="..\CustomTextRenderer.cpp" />
<ClCompile Include="..\DxFontInfo.cpp" /> <ClCompile Include="..\precomp.cpp" />
<ClCompile Include="..\DxFontRenderData.cpp" /> <ClCompile Include="..\DxFontRenderData.cpp" />
<ClCompile Include="..\DxRenderer.cpp" /> <ClCompile Include="..\DxRenderer.cpp" />
<ClCompile Include="..\precomp.cpp" /> <ClCompile Include="..\BoxDrawingEffect.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\BoxDrawingEffect.h" />
<ClInclude Include="..\CustomTextLayout.h" /> <ClInclude Include="..\CustomTextLayout.h" />
<ClInclude Include="..\CustomTextRenderer.h" /> <ClInclude Include="..\CustomTextRenderer.h" />
<ClInclude Include="..\DxFontInfo.h" />
<ClInclude Include="..\DxFontRenderData.h" />
<ClInclude Include="..\DxRenderer.hpp" />
<ClInclude Include="..\precomp.h" /> <ClInclude Include="..\precomp.h" />
<ClInclude Include="..\DxFontRenderData.h"/>
<ClInclude Include="..\DxRenderer.hpp" />
<ClInclude Include="..\ScreenPixelShader.h" /> <ClInclude Include="..\ScreenPixelShader.h" />
<ClInclude Include="..\ScreenVertexShader.h" /> <ClInclude Include="..\ScreenVertexShader.h" />
<ClInclude Include="..\BoxDrawingEffect.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Midl Include="..\IBoxDrawingEffect.idl" /> <Midl Include="..\IBoxDrawingEffect.idl" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -113,7 +113,6 @@ public:
virtual bool LockingShift(const size_t gsetNumber) = 0; // LS0, LS1, LS2, LS3 virtual bool LockingShift(const size_t gsetNumber) = 0; // LS0, LS1, LS2, LS3
virtual bool LockingShiftRight(const size_t gsetNumber) = 0; // LS1R, LS2R, LS3R virtual bool LockingShiftRight(const size_t gsetNumber) = 0; // LS1R, LS2R, LS3R
virtual bool SingleShift(const size_t gsetNumber) = 0; // SS2, SS3 virtual bool SingleShift(const size_t gsetNumber) = 0; // SS2, SS3
virtual bool AcceptC1Controls(const bool enabled) = 0; // DECAC1
virtual bool SoftReset() = 0; // DECSTR virtual bool SoftReset() = 0; // DECSTR
virtual bool HardReset() = 0; // RIS virtual bool HardReset() = 0; // RIS

View file

@ -344,7 +344,6 @@ bool AdaptDispatch::CursorSaveState()
savedCursorState.IsOriginModeRelative = _isOriginModeRelative; savedCursorState.IsOriginModeRelative = _isOriginModeRelative;
savedCursorState.Attributes = attributes; savedCursorState.Attributes = attributes;
savedCursorState.TermOutput = _termOutput; savedCursorState.TermOutput = _termOutput;
savedCursorState.C1ControlsAccepted = _pConApi->GetParserMode(StateMachine::Mode::AcceptC1);
_pConApi->GetConsoleOutputCP(savedCursorState.CodePage); _pConApi->GetConsoleOutputCP(savedCursorState.CodePage);
} }
@ -387,9 +386,6 @@ bool AdaptDispatch::CursorRestoreState()
// Restore designated character set. // Restore designated character set.
_termOutput = savedCursorState.TermOutput; _termOutput = savedCursorState.TermOutput;
// Restore the parsing state of C1 control codes.
AcceptC1Controls(savedCursorState.C1ControlsAccepted);
// Restore the code page if it was previously saved. // Restore the code page if it was previously saved.
if (savedCursorState.CodePage != 0) if (savedCursorState.CodePage != 0)
{ {
@ -1247,12 +1243,7 @@ bool AdaptDispatch::SetAnsiMode(const bool ansiMode)
// need to be reset to defaults, even if the mode doesn't actually change. // need to be reset to defaults, even if the mode doesn't actually change.
_termOutput = {}; _termOutput = {};
_pConApi->SetParserMode(StateMachine::Mode::Ansi, ansiMode); return _pConApi->PrivateSetAnsiMode(ansiMode);
_pConApi->SetInputMode(TerminalInput::Mode::Ansi, ansiMode);
// We don't check the SetInputMode return value, because we'll never want
// to forward a DECANM mode change over conpty.
return true;
} }
// Routine Description: // Routine Description:
@ -1696,10 +1687,9 @@ void AdaptDispatch::_InitTabStopsForWidth(const size_t width)
//Routine Description: //Routine Description:
// DOCS - Selects the coding system through which character sets are activated. // DOCS - Selects the coding system through which character sets are activated.
// When ISO2022 is selected, the code page is set to ISO-8859-1, C1 control // When ISO2022 is selected, the code page is set to ISO-8859-1, and both
// codes are accepted, and both GL and GR areas of the code table can be // GL and GR areas of the code table can be remapped. When UTF8 is selected,
// remapped. When UTF8 is selected, the code page is set to UTF-8, the C1 // the code page is set to UTF-8, and only the GL area can be remapped.
// control codes are disabled, and only the GL area can be remapped.
//Arguments: //Arguments:
// - codingSystem - The coding system that will be selected. // - codingSystem - The coding system that will be selected.
// Return value: // Return value:
@ -1722,7 +1712,6 @@ bool AdaptDispatch::DesignateCodingSystem(const VTID codingSystem)
success = _pConApi->SetConsoleOutputCP(28591); success = _pConApi->SetConsoleOutputCP(28591);
if (success) if (success)
{ {
AcceptC1Controls(true);
_termOutput.EnableGrTranslation(true); _termOutput.EnableGrTranslation(true);
} }
break; break;
@ -1730,7 +1719,6 @@ bool AdaptDispatch::DesignateCodingSystem(const VTID codingSystem)
success = _pConApi->SetConsoleOutputCP(CP_UTF8); success = _pConApi->SetConsoleOutputCP(CP_UTF8);
if (success) if (success)
{ {
AcceptC1Controls(false);
_termOutput.EnableGrTranslation(false); _termOutput.EnableGrTranslation(false);
} }
break; break;
@ -1804,17 +1792,6 @@ bool AdaptDispatch::SingleShift(const size_t gsetNumber)
return _termOutput.SingleShift(gsetNumber); return _termOutput.SingleShift(gsetNumber);
} }
//Routine Description:
// DECAC1 - Enable or disable the reception of C1 control codes in the parser.
//Arguments:
// - enabled - true to allow C1 controls to be used, false to disallow.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::AcceptC1Controls(const bool enabled)
{
return _pConApi->SetParserMode(StateMachine::Mode::AcceptC1, enabled);
}
//Routine Description: //Routine Description:
// Soft Reset - Perform a soft reset. See http://www.vt100.net/docs/vt510-rm/DECSTR.html // Soft Reset - Perform a soft reset. See http://www.vt100.net/docs/vt510-rm/DECSTR.html
// The following table lists everything that should be done, 'X's indicate the ones that // The following table lists everything that should be done, 'X's indicate the ones that
@ -1863,8 +1840,6 @@ bool AdaptDispatch::SoftReset()
// Restore initial code page if previously changed by a DOCS sequence. // Restore initial code page if previously changed by a DOCS sequence.
success = _pConApi->SetConsoleOutputCP(_initialCodePage.value()) && success; success = _pConApi->SetConsoleOutputCP(_initialCodePage.value()) && success;
} }
// Disable parsing of C1 control codes.
success = AcceptC1Controls(false) && success;
success = SetGraphicsRendition({}) && success; // Normal rendition. success = SetGraphicsRendition({}) && success; // Normal rendition.
@ -2250,7 +2225,7 @@ bool AdaptDispatch::SetCursorColor(const COLORREF cursorColor)
return false; return false;
} }
return _pConApi->SetColorTableEntry(TextColor::CURSOR_COLOR, cursorColor); return _pConApi->SetCursorColor(cursorColor);
} }
// Routine Description: // Routine Description:
@ -2273,7 +2248,7 @@ bool AdaptDispatch::SetClipboard(const std::wstring_view /*content*/) noexcept
// True if handled successfully. False otherwise. // True if handled successfully. False otherwise.
bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor)
{ {
const bool success = _pConApi->SetColorTableEntry(tableIndex, dwColor); const bool success = _pConApi->PrivateSetColorTableEntry(tableIndex, dwColor);
// If we're a conpty, always return false, so that we send the updated color // If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use // value to the terminal. Still handle the sequence so apps that use
@ -2293,10 +2268,10 @@ bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwCo
// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR. // - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value: // Return Value:
// True if handled successfully. False otherwise. // True if handled successfully. False otherwise.
bool AdaptDispatch::SetDefaultForeground(const DWORD dwColor) bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultForeground(const DWORD dwColor)
{ {
bool success = true; bool success = true;
success = _pConApi->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, dwColor); success = _pConApi->PrivateSetDefaultForeground(dwColor);
// If we're a conpty, always return false, so that we send the updated color // If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use // value to the terminal. Still handle the sequence so apps that use
@ -2316,10 +2291,10 @@ bool AdaptDispatch::SetDefaultForeground(const DWORD dwColor)
// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR. // - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value: // Return Value:
// True if handled successfully. False otherwise. // True if handled successfully. False otherwise.
bool AdaptDispatch::SetDefaultBackground(const DWORD dwColor) bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultBackground(const DWORD dwColor)
{ {
bool success = true; bool success = true;
success = _pConApi->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, dwColor); success = _pConApi->PrivateSetDefaultBackground(dwColor);
// If we're a conpty, always return false, so that we send the updated color // If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use // value to the terminal. Still handle the sequence so apps that use

View file

@ -101,7 +101,6 @@ namespace Microsoft::Console::VirtualTerminal
bool LockingShift(const size_t gsetNumber) override; // LS0, LS1, LS2, LS3 bool LockingShift(const size_t gsetNumber) override; // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t gsetNumber) override; // LS1R, LS2R, LS3R bool LockingShiftRight(const size_t gsetNumber) override; // LS1R, LS2R, LS3R
bool SingleShift(const size_t gsetNumber) override; // SS2, SS3 bool SingleShift(const size_t gsetNumber) override; // SS2, SS3
bool AcceptC1Controls(const bool enabled) override; // DECAC1
bool SoftReset() override; // DECSTR bool SoftReset() override; // DECSTR
bool HardReset() override; // RIS bool HardReset() override; // RIS
bool ScreenAlignmentPattern() override; // DECALN bool ScreenAlignmentPattern() override; // DECALN
@ -156,7 +155,6 @@ namespace Microsoft::Console::VirtualTerminal
bool IsOriginModeRelative = false; bool IsOriginModeRelative = false;
TextAttribute Attributes = {}; TextAttribute Attributes = {};
TerminalOutput TermOutput = {}; TerminalOutput TermOutput = {};
bool C1ControlsAccepted = false;
unsigned int CodePage = 0; unsigned int CodePage = 0;
}; };
struct Offset struct Offset

View file

@ -16,7 +16,6 @@ Author(s):
#pragma once #pragma once
#include "../input/terminalInput.hpp" #include "../input/terminalInput.hpp"
#include "../parser/stateMachine.hpp"
#include "../../types/inc/IInputEvent.hpp" #include "../../types/inc/IInputEvent.hpp"
#include "../../buffer/out/LineRendition.hpp" #include "../../buffer/out/LineRendition.hpp"
#include "../../buffer/out/TextAttribute.hpp" #include "../../buffer/out/TextAttribute.hpp"
@ -50,9 +49,8 @@ namespace Microsoft::Console::VirtualTerminal
const SMALL_RECT& window) = 0; const SMALL_RECT& window) = 0;
virtual bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) = 0; virtual bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) = 0;
virtual bool SetParserMode(const StateMachine::Mode mode, const bool enabled) = 0;
virtual bool GetParserMode(const StateMachine::Mode mode) const = 0;
virtual bool PrivateSetAnsiMode(const bool ansiMode) = 0;
virtual bool PrivateSetScreenMode(const bool reverseMode) = 0; virtual bool PrivateSetScreenMode(const bool reverseMode) = 0;
virtual bool PrivateSetAutoWrapMode(const bool wrapAtEOL) = 0; virtual bool PrivateSetAutoWrapMode(const bool wrapAtEOL) = 0;
@ -72,6 +70,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool PrivateClearBuffer() = 0; virtual bool PrivateClearBuffer() = 0;
virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0; virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0;
virtual bool SetCursorStyle(const CursorType style) = 0; virtual bool SetCursorStyle(const CursorType style) = 0;
virtual bool SetCursorColor(const COLORREF color) = 0;
virtual bool PrivateWriteConsoleControlInput(const KeyEvent key) = 0; virtual bool PrivateWriteConsoleControlInput(const KeyEvent key) = 0;
virtual bool PrivateRefreshWindow() = 0; virtual bool PrivateRefreshWindow() = 0;
@ -86,8 +85,10 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool MoveToBottom() const = 0; virtual bool MoveToBottom() const = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const = 0; virtual bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) = 0; virtual bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const = 0;
virtual bool PrivateSetDefaultForeground(const COLORREF value) const = 0;
virtual bool PrivateSetDefaultBackground(const COLORREF value) const = 0;
virtual bool PrivateFillRegion(const COORD startPosition, virtual bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength, const size_t fillLength,

View file

@ -104,7 +104,6 @@ public:
bool LockingShift(const size_t /*gsetNumber*/) noexcept override { return false; } // LS0, LS1, LS2, LS3 bool LockingShift(const size_t /*gsetNumber*/) noexcept override { return false; } // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t /*gsetNumber*/) noexcept override { return false; } // LS1R, LS2R, LS3R bool LockingShiftRight(const size_t /*gsetNumber*/) noexcept override { return false; } // LS1R, LS2R, LS3R
bool SingleShift(const size_t /*gsetNumber*/) noexcept override { return false; } // SS2, SS3 bool SingleShift(const size_t /*gsetNumber*/) noexcept override { return false; } // SS2, SS3
bool AcceptC1Controls(const bool /*enabled*/) noexcept override { return false; } // DECAC1
bool SoftReset() noexcept override { return false; } // DECSTR bool SoftReset() noexcept override { return false; } // DECSTR
bool HardReset() noexcept override { return false; } // RIS bool HardReset() noexcept override { return false; } // RIS

View file

@ -125,24 +125,16 @@ public:
return _setInputModeResult; return _setInputModeResult;
} }
bool SetParserMode(const StateMachine::Mode mode, const bool enabled) override bool PrivateSetAnsiMode(const bool ansiMode) override
{ {
Log::Comment(L"SetParserMode MOCK called..."); Log::Comment(L"PrivateSetAnsiMode MOCK called...");
if (_setParserModeResult) if (_privateSetAnsiModeResult)
{ {
VERIFY_ARE_EQUAL(_expectedParserMode, mode); VERIFY_ARE_EQUAL(_expectedAnsiMode, ansiMode);
VERIFY_ARE_EQUAL(_expectedParserModeEnabled, enabled);
} }
return _setParserModeResult; return _privateSetAnsiModeResult;
}
bool GetParserMode(const StateMachine::Mode /*mode*/) const override
{
Log::Comment(L"GetParserMode MOCK called...");
return false;
} }
bool PrivateSetScreenMode(const bool /*reverseMode*/) override bool PrivateSetScreenMode(const bool /*reverseMode*/) override
@ -370,6 +362,16 @@ public:
return _setCursorStyleResult; return _setCursorStyleResult;
} }
bool SetCursorColor(const COLORREF cursorColor) override
{
Log::Comment(L"SetCursorColor MOCK called...");
if (_setCursorColorResult)
{
VERIFY_ARE_EQUAL(_expectedCursorColor, cursorColor);
}
return _setCursorColorResult;
}
bool PrivateRefreshWindow() override bool PrivateRefreshWindow() override
{ {
Log::Comment(L"PrivateRefreshWindow MOCK called..."); Log::Comment(L"PrivateRefreshWindow MOCK called...");
@ -384,14 +386,10 @@ public:
return FALSE; return FALSE;
} }
bool SetConsoleOutputCP(const unsigned int codepage) override bool SetConsoleOutputCP(const unsigned int /*codepage*/) override
{ {
Log::Comment(L"SetConsoleOutputCP MOCK called..."); Log::Comment(L"SetConsoleOutputCP MOCK called...");
if (_setConsoleOutputCPResult) return TRUE;
{
VERIFY_ARE_EQUAL(_expectedOutputCP, codepage);
}
return _setConsoleOutputCPResult;
} }
bool GetConsoleOutputCP(unsigned int& codepage) override bool GetConsoleOutputCP(unsigned int& codepage) override
@ -428,31 +426,53 @@ public:
return _moveToBottomResult; return _moveToBottomResult;
} }
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept override
{ {
Log::Comment(L"GetColorTableEntry MOCK called..."); Log::Comment(L"PrivateGetColorTableEntry MOCK called...");
if (_getColorTableEntryResult) if (_privateGetColorTableEntryResult)
{ {
VERIFY_ARE_EQUAL(_expectedColorTableIndex, tableIndex); VERIFY_ARE_EQUAL(_expectedColorTableIndex, index);
// Simply returning the index as the color value makes it easy for // Simply returning the index as the color value makes it easy for
// tests to confirm that they've received the color they expected. // tests to confirm that they've received the color they expected.
return gsl::narrow_cast<COLORREF>(tableIndex); value = gsl::narrow_cast<COLORREF>(index);
} }
return INVALID_COLOR; return _privateGetColorTableEntryResult;
} }
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept override
{ {
Log::Comment(L"SetColorTableEntry MOCK called..."); Log::Comment(L"PrivateSetColorTableEntry MOCK called...");
if (_setColorTableEntryResult) if (_privateSetColorTableEntryResult)
{ {
VERIFY_ARE_EQUAL(_expectedColorTableIndex, tableIndex); VERIFY_ARE_EQUAL(_expectedColorTableIndex, index);
VERIFY_ARE_EQUAL(_expectedColorValue, color); VERIFY_ARE_EQUAL(_expectedColorValue, value);
} }
return _setColorTableEntryResult; return _privateSetColorTableEntryResult;
}
bool PrivateSetDefaultForeground(const COLORREF value) const noexcept override
{
Log::Comment(L"PrivateSetDefaultForeground MOCK called...");
if (_privateSetDefaultForegroundResult)
{
VERIFY_ARE_EQUAL(_expectedDefaultForegroundColorValue, value);
}
return _privateSetDefaultForegroundResult;
}
bool PrivateSetDefaultBackground(const COLORREF value) const noexcept override
{
Log::Comment(L"PrivateSetDefaultForeground MOCK called...");
if (_privateSetDefaultBackgroundResult)
{
VERIFY_ARE_EQUAL(_expectedDefaultBackgroundColorValue, value);
}
return _privateSetDefaultBackgroundResult;
} }
bool PrivateFillRegion(const COORD /*startPosition*/, bool PrivateFillRegion(const COORD /*startPosition*/,
@ -692,9 +712,8 @@ public:
bool _setInputModeResult = false; bool _setInputModeResult = false;
TerminalInput::Mode _expectedInputMode; TerminalInput::Mode _expectedInputMode;
bool _expectedInputModeEnabled = false; bool _expectedInputModeEnabled = false;
bool _setParserModeResult = false; bool _privateSetAnsiModeResult = false;
StateMachine::Mode _expectedParserMode; bool _expectedAnsiMode = false;
bool _expectedParserModeEnabled = false;
bool _privateAllowCursorBlinkingResult = false; bool _privateAllowCursorBlinkingResult = false;
bool _enable = false; // for cursor blinking bool _enable = false; // for cursor blinking
bool _privateSetScrollingRegionResult = false; bool _privateSetScrollingRegionResult = false;
@ -707,15 +726,22 @@ public:
std::wstring_view _expectedWindowTitle{}; std::wstring_view _expectedWindowTitle{};
bool _setCursorStyleResult = false; bool _setCursorStyleResult = false;
CursorType _expectedCursorStyle; CursorType _expectedCursorStyle;
bool _setConsoleOutputCPResult = false; bool _setCursorColorResult = false;
COLORREF _expectedCursorColor = 0;
bool _getConsoleOutputCPResult = false; bool _getConsoleOutputCPResult = false;
bool _moveToBottomResult = false; bool _moveToBottomResult = false;
bool _getColorTableEntryResult = false; bool _privateGetColorTableEntryResult = false;
bool _setColorTableEntryResult = false; bool _privateSetColorTableEntryResult = false;
size_t _expectedColorTableIndex = SIZE_MAX; size_t _expectedColorTableIndex = SIZE_MAX;
COLORREF _expectedColorValue = INVALID_COLOR; COLORREF _expectedColorValue = INVALID_COLOR;
bool _privateSetDefaultForegroundResult = false;
COLORREF _expectedDefaultForegroundColorValue = INVALID_COLOR;
bool _privateSetDefaultBackgroundResult = false;
COLORREF _expectedDefaultBackgroundColorValue = INVALID_COLOR;
SIZE _expectedCellSize = {}; SIZE _expectedCellSize = {};
private: private:
@ -2031,17 +2057,15 @@ public:
// success cases // success cases
// set ansi mode = true // set ansi mode = true
Log::Comment(L"Test 1: ansi mode = true"); Log::Comment(L"Test 1: ansi mode = true");
_testGetSet->_setParserModeResult = true; _testGetSet->_privateSetAnsiModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::Ansi; _testGetSet->_expectedAnsiMode = true;
_testGetSet->_expectedParserModeEnabled = true;
VERIFY_IS_TRUE(_pDispatch.get()->SetAnsiMode(true)); VERIFY_IS_TRUE(_pDispatch.get()->SetAnsiMode(true));
// set ansi mode = false // set ansi mode = false
Log::Comment(L"Test 2: ansi mode = false."); Log::Comment(L"Test 2: ansi mode = false.");
_testGetSet->_setParserModeResult = true; _testGetSet->_privateSetAnsiModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::Ansi; _testGetSet->_expectedAnsiMode = false;
_testGetSet->_expectedParserModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->SetAnsiMode(false)); VERIFY_IS_TRUE(_pDispatch.get()->SetAnsiMode(false));
} }
@ -2266,7 +2290,7 @@ public:
VTParameter rgOptions[16]; VTParameter rgOptions[16];
size_t cOptions = 3; size_t cOptions = 3;
_testGetSet->_getColorTableEntryResult = true; _testGetSet->_privateGetColorTableEntryResult = true;
_testGetSet->_expectedAttribute = _testGetSet->_attribute; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
Log::Comment(L"Test 1: Change Foreground"); Log::Comment(L"Test 1: Change Foreground");
@ -2316,7 +2340,7 @@ public:
VTParameter rgOptions[16]; VTParameter rgOptions[16];
_testGetSet->_getColorTableEntryResult = true; _testGetSet->_privateGetColorTableEntryResult = true;
_testGetSet->_expectedAttribute = _testGetSet->_attribute; _testGetSet->_expectedAttribute = _testGetSet->_attribute;
Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter"); Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter");
@ -2359,7 +2383,7 @@ public:
{ {
_testGetSet->PrepData(); _testGetSet->PrepData();
_testGetSet->_setColorTableEntryResult = true; _testGetSet->_privateSetColorTableEntryResult = true;
const auto testColor = RGB(1, 2, 3); const auto testColor = RGB(1, 2, 3);
_testGetSet->_expectedColorValue = testColor; _testGetSet->_expectedColorValue = testColor;
@ -2369,7 +2393,7 @@ public:
VERIFY_IS_TRUE(_pDispatch.get()->SetColorTableEntry(i, testColor)); VERIFY_IS_TRUE(_pDispatch.get()->SetColorTableEntry(i, testColor));
} }
// Test in pty mode - we should fail, but SetColorTableEntry should still be called // Test in pty mode - we should fail, but PrivateSetColorTableEntry should still be called
_testGetSet->_isPty = true; _testGetSet->_isPty = true;
_testGetSet->_expectedColorTableIndex = 15; // Windows BRIGHT_WHITE _testGetSet->_expectedColorTableIndex = 15; // Windows BRIGHT_WHITE
@ -2599,39 +2623,6 @@ public:
VERIFY_IS_TRUE(decdld(CellMatrix::Default, 0, FontSet::Size132x24, FontUsage::FullCell, bitmapOf6x18)); VERIFY_IS_TRUE(decdld(CellMatrix::Default, 0, FontSet::Size132x24, FontUsage::FullCell, bitmapOf6x18));
} }
TEST_METHOD(TogglingC1ParserMode)
{
Log::Comment(L"1. Accept C1 controls");
_testGetSet->_setParserModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::AcceptC1;
_testGetSet->_expectedParserModeEnabled = true;
VERIFY_IS_TRUE(_pDispatch.get()->AcceptC1Controls(true));
Log::Comment(L"2. Don't accept C1 controls");
_testGetSet->_setParserModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::AcceptC1;
_testGetSet->_expectedParserModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->AcceptC1Controls(false));
Log::Comment(L"3. Designate ISO-2022 coding system");
// Code page should be set to ISO-8859-1 and C1 parsing enabled
_testGetSet->_setConsoleOutputCPResult = true;
_testGetSet->_expectedOutputCP = 28591;
_testGetSet->_setParserModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::AcceptC1;
_testGetSet->_expectedParserModeEnabled = true;
VERIFY_IS_TRUE(_pDispatch.get()->DesignateCodingSystem(DispatchTypes::CodingSystem::ISO2022));
Log::Comment(L"4. Designate UTF-8 coding system");
// Code page should be set to UTF-8 and C1 parsing disabled
_testGetSet->_setConsoleOutputCPResult = true;
_testGetSet->_expectedOutputCP = CP_UTF8;
_testGetSet->_setParserModeResult = true;
_testGetSet->_expectedParserMode = StateMachine::Mode::AcceptC1;
_testGetSet->_expectedParserModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->DesignateCodingSystem(DispatchTypes::CodingSystem::UTF8));
}
private: private:
TestGetSet* _testGetSet; // non-ownership pointer TestGetSet* _testGetSet; // non-ownership pointer
std::unique_ptr<AdaptDispatch> _pDispatch; std::unique_ptr<AdaptDispatch> _pDispatch;

Some files were not shown because too many files have changed in this diff Show more