ccea66710c
This PR provides a faster algorithm for converting 8-bit and 24-bit colors into the 4-bit legacy values that are required by the Win32 console APIs. It also fixes areas of the code that were incorrectly using a simple 16-color conversion that didn't handle 8-bit and 24-bit values. The faster conversion algorithm should be an improvement for issues #783 and #3950. One of the main points of this PR was to fix the `ReadConsoleOutputAttribute` API, which was using a simplified legacy color conversion (the original `TextAttribute:GetLegacyAttributes` method), which could only handle values from the 16-color table. RGB values, and colors from the 256-color table, would be mapped to completely nonsensical values. This API has now been updated to use the more correct `Settings::GenerateLegacyAttributes` method. But there were also a couple of other places in the code that were using `GetLegacyAttributes` when they really had no reason to be working with legacy attributes at all. This could result in colors being downgraded to 4-bit values (often badly, as explained above), when the code was already perfectly capable of displaying the full 24-bits. This included the fill colors in the IME composer (in `ConsoleImeInfo`), and the construction of the highlighting colors in the color search/selection handler (`Selection::_HandleColorSelection`). I also got rid of some legacy attribute code in the `Popup` class, which was originally intended to update colors below the popup when the settings changed, but actually caused more problems than it solved. The other major goal of this PR was to improve the performance of the `GenerateLegacyAttributes` method, since the existing implementation could be quite slow when dealing with RGB values. The simple cases are handled much the same as they were before. For an `IsDefault` color, we get the default index from the `Settings::_wFillAttribute` field. For an `IsIndex16` color, the index can just be returned as is. For an `IsRgb` color, the RGB components are compressed down to 8 bits (3 red, 3 green, 2 blue), simply by dropping the least significant bits. This 8-bit value is then used to lookup a representative 16-color value from a hard-coded table. An `IsIndex256` color is also converted with a lookup table, just using the existing 8-bit index. The RGB mapping table was calculated by taking each compressed 8-bit color, and picking a entry from the _Campbell_ palette that best approximated that color. This was done by looking at a range of 24-bit colors that mapped to the 8-bit value, finding the best _Campbell_ match for each of them (using a [CIEDE2000] color difference calculation), and then the most common match became the index that the 8-bit value would map to. The 256-color table was just a simpler version of this process. For each entry in the table, we take the default RGB palette value, and find it's closest match in the _Campbell_ palette. Because these tables are hard-coded, the results won't adjust to changes in the palette. However, they should still produce reasonable results for palettes that follow the standard ANSI color range. And since they're only a very loose approximation of the colors anyway, the exact value really isn't that important. That said, I have tried to make sure that if you take an RGB value for a particular index in a reasonable color scheme, then the legacy color mapped from that value should ideally match the same index. This will never be possible for all color schemes, but I have tweaked a few of the table entries to improve the results for some of the common schemes. One other point worth making regarding the hard-coded tables: even if we wanted to take the active palette into account, that wouldn't actually be possible over a conpty connection, because we can't easily know what color scheme the client application is using. At least this way the results in conhost are guaranteed to be the same as in the Windows Terminal. [CIEDE2000]: https://en.wikipedia.org/wiki/Color_difference#CIEDE2000 ## Validation Steps Performed This code still passes the `TextAttributeTests` that check the basic `GetLegacyAttribute` behaviour and verify the all legacy attributes roundtrip correctly. However, some of the values in the `RgbColorTests` had to be updated, since we're now intentionally returning different values as a result of the changes to the RGB conversion algorithm. I haven't added additional unit tests, but I have done a lot of manual testing to see how well the new algorithm works with a range of colors and a variety of different color schemes. It's not perfect in every situation, but I think it works well enough for the purpose it serves. I've also confirmed that the issues reported in #5940 and #6247 are now fixed by these changes. Closes #5940 Closes #6247
931 lines
28 KiB
C++
931 lines
28 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
#include "settings.hpp"
|
|
|
|
#include "..\interactivity\inc\ServiceLocator.hpp"
|
|
#include "../types/inc/utils.hpp"
|
|
|
|
#pragma hdrstop
|
|
|
|
constexpr unsigned int DEFAULT_NUMBER_OF_COMMANDS = 25;
|
|
constexpr unsigned int DEFAULT_NUMBER_OF_BUFFERS = 4;
|
|
|
|
using Microsoft::Console::Interactivity::ServiceLocator;
|
|
|
|
Settings::Settings() :
|
|
_dwHotKey(0),
|
|
_dwStartupFlags(0),
|
|
_wFillAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE), // White (not bright) on black by default
|
|
_wPopupFillAttribute(FOREGROUND_RED | FOREGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY), // Purple on white (bright) by default
|
|
_wShowWindow(SW_SHOWNORMAL),
|
|
_wReserved(0),
|
|
// dwScreenBufferSize initialized below
|
|
// dwWindowSize initialized below
|
|
// dwWindowOrigin initialized below
|
|
_nFont(0),
|
|
// dwFontSize initialized below
|
|
_uFontFamily(0),
|
|
_uFontWeight(0),
|
|
// FaceName initialized below
|
|
_uCursorSize(Cursor::CURSOR_SMALL_SIZE),
|
|
_bFullScreen(false),
|
|
_bQuickEdit(true),
|
|
_bInsertMode(true),
|
|
_bAutoPosition(true),
|
|
_uHistoryBufferSize(DEFAULT_NUMBER_OF_COMMANDS),
|
|
_uNumberOfHistoryBuffers(DEFAULT_NUMBER_OF_BUFFERS),
|
|
_bHistoryNoDup(false),
|
|
// ColorTable initialized below
|
|
_uCodePage(ServiceLocator::LocateGlobals().uiOEMCP),
|
|
_uScrollScale(1),
|
|
_bLineSelection(true),
|
|
_bWrapText(true),
|
|
_fCtrlKeyShortcutsDisabled(false),
|
|
_bWindowAlpha(BYTE_MAX), // 255 alpha = opaque. 0 = transparent.
|
|
_fFilterOnPaste(false),
|
|
_LaunchFaceName{},
|
|
_fTrimLeadingZeros(FALSE),
|
|
_fEnableColorSelection(FALSE),
|
|
_fAllowAltF4Close(true),
|
|
_dwVirtTermLevel(0),
|
|
_fUseWindowSizePixels(false),
|
|
_fAutoReturnOnNewline(true), // the historic Windows behavior defaults this to on.
|
|
_fRenderGridWorldwide(false), // historically grid lines were only rendered in DBCS codepages, so this is false by default unless otherwise specified.
|
|
_fScreenReversed(false),
|
|
// window size pixels initialized below
|
|
_fInterceptCopyPaste(0),
|
|
_DefaultForeground(INVALID_COLOR),
|
|
_DefaultBackground(INVALID_COLOR),
|
|
_fUseDx(false),
|
|
_fCopyColor(false)
|
|
{
|
|
_dwScreenBufferSize.X = 80;
|
|
_dwScreenBufferSize.Y = 25;
|
|
|
|
_dwWindowSize.X = _dwScreenBufferSize.X;
|
|
_dwWindowSize.Y = _dwScreenBufferSize.Y;
|
|
|
|
_dwWindowSizePixels = { 0 };
|
|
|
|
_dwWindowOrigin.X = 0;
|
|
_dwWindowOrigin.Y = 0;
|
|
|
|
_dwFontSize.X = 0;
|
|
_dwFontSize.Y = 16;
|
|
|
|
ZeroMemory((void*)&_FaceName, sizeof(_FaceName));
|
|
wcscpy_s(_FaceName, DEFAULT_TT_FONT_FACENAME);
|
|
|
|
_CursorColor = Cursor::s_InvertCursorColor;
|
|
_CursorType = CursorType::Legacy;
|
|
|
|
gsl::span<COLORREF> tableView = { _colorTable.data(), gsl::narrow<ptrdiff_t>(_colorTable.size()) };
|
|
::Microsoft::Console::Utils::Initialize256ColorTable(tableView);
|
|
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Applies hardcoded default settings that are in line with what is defined
|
|
// in our Windows edition manifest (living in win32k-settings.man).
|
|
// - NOTE: This exists in case we cannot access the registry on desktop platforms.
|
|
// We will use this to provide better defaults than the constructor values which
|
|
// are optimized for OneCore.
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - <none> - Adjusts internal state only.
|
|
void Settings::ApplyDesktopSpecificDefaults()
|
|
{
|
|
_dwFontSize.X = 0;
|
|
_dwFontSize.Y = 16;
|
|
_uFontFamily = 0;
|
|
_dwScreenBufferSize.X = 120;
|
|
_dwScreenBufferSize.Y = 9001;
|
|
_uCursorSize = 25;
|
|
_dwWindowSize.X = 120;
|
|
_dwWindowSize.Y = 30;
|
|
_wFillAttribute = 0x7;
|
|
_wPopupFillAttribute = 0xf5;
|
|
wcscpy_s(_FaceName, L"__DefaultTTFont__");
|
|
_uFontWeight = 0;
|
|
_bInsertMode = TRUE;
|
|
_bFullScreen = FALSE;
|
|
_fCtrlKeyShortcutsDisabled = false;
|
|
_bWrapText = true;
|
|
_bLineSelection = TRUE;
|
|
_bWindowAlpha = 255;
|
|
_fFilterOnPaste = TRUE;
|
|
_bQuickEdit = TRUE;
|
|
_uHistoryBufferSize = 50;
|
|
_uNumberOfHistoryBuffers = 4;
|
|
_bHistoryNoDup = FALSE;
|
|
|
|
gsl::span<COLORREF> tableView = { _colorTable.data(), gsl::narrow<ptrdiff_t>(_colorTable.size()) };
|
|
::Microsoft::Console::Utils::InitializeCampbellColorTableForConhost(tableView);
|
|
|
|
_fTrimLeadingZeros = false;
|
|
_fEnableColorSelection = false;
|
|
_uScrollScale = 1;
|
|
}
|
|
|
|
void Settings::ApplyStartupInfo(const Settings* const pStartupSettings)
|
|
{
|
|
const DWORD dwFlags = pStartupSettings->_dwStartupFlags;
|
|
|
|
// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx
|
|
|
|
// Note: These attributes do not get sent to us if we started conhost
|
|
// directly. See minkernel/console/client/dllinit for the
|
|
// initialization of these values for cmdline applications.
|
|
|
|
if (WI_IsFlagSet(dwFlags, STARTF_USECOUNTCHARS))
|
|
{
|
|
_dwScreenBufferSize = pStartupSettings->_dwScreenBufferSize;
|
|
}
|
|
|
|
if (WI_IsFlagSet(dwFlags, STARTF_USESIZE))
|
|
{
|
|
// WARNING: This size is in pixels when passed in the create process call.
|
|
// It will need to be divided by the font size before use.
|
|
// All other Window Size values (from registry/shortcuts) are stored in characters.
|
|
_dwWindowSizePixels = pStartupSettings->_dwWindowSize;
|
|
_fUseWindowSizePixels = true;
|
|
}
|
|
|
|
if (WI_IsFlagSet(dwFlags, STARTF_USEPOSITION))
|
|
{
|
|
_dwWindowOrigin = pStartupSettings->_dwWindowOrigin;
|
|
_bAutoPosition = FALSE;
|
|
}
|
|
|
|
if (WI_IsFlagSet(dwFlags, STARTF_USEFILLATTRIBUTE))
|
|
{
|
|
_wFillAttribute = pStartupSettings->_wFillAttribute;
|
|
}
|
|
|
|
if (WI_IsFlagSet(dwFlags, STARTF_USESHOWWINDOW))
|
|
{
|
|
_wShowWindow = pStartupSettings->_wShowWindow;
|
|
}
|
|
}
|
|
|
|
// Method Description:
|
|
// - Applies settings passed on the commandline to this settings structure.
|
|
// Currently, the only settings that can be passed on the commandline are
|
|
// the initial width and height of the screenbuffer/viewport.
|
|
// Arguments:
|
|
// - consoleArgs: A reference to a parsed command-line args object.
|
|
// Return Value:
|
|
// - <none>
|
|
void Settings::ApplyCommandlineArguments(const ConsoleArguments& consoleArgs)
|
|
{
|
|
const short width = consoleArgs.GetWidth();
|
|
const short height = consoleArgs.GetHeight();
|
|
|
|
if (width > 0 && height > 0)
|
|
{
|
|
_dwScreenBufferSize.X = width;
|
|
_dwWindowSize.X = width;
|
|
|
|
_dwScreenBufferSize.Y = height;
|
|
_dwWindowSize.Y = height;
|
|
}
|
|
else if (ServiceLocator::LocateGlobals().getConsoleInformation().IsInVtIoMode())
|
|
{
|
|
// If we're a PTY but we weren't explicitly told a size, use the window size as the buffer size.
|
|
_dwScreenBufferSize = _dwWindowSize;
|
|
}
|
|
}
|
|
|
|
// WARNING: this function doesn't perform any validation or conversion
|
|
void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
|
|
{
|
|
_wFillAttribute = pStateInfo->ScreenAttributes;
|
|
_wPopupFillAttribute = pStateInfo->PopupAttributes;
|
|
_dwScreenBufferSize = pStateInfo->ScreenBufferSize;
|
|
_dwWindowSize = pStateInfo->WindowSize;
|
|
_dwWindowOrigin.X = (SHORT)pStateInfo->WindowPosX;
|
|
_dwWindowOrigin.Y = (SHORT)pStateInfo->WindowPosY;
|
|
_dwFontSize = pStateInfo->FontSize;
|
|
_uFontFamily = pStateInfo->FontFamily;
|
|
_uFontWeight = pStateInfo->FontWeight;
|
|
StringCchCopyW(_FaceName, ARRAYSIZE(_FaceName), pStateInfo->FaceName);
|
|
_uCursorSize = pStateInfo->CursorSize;
|
|
_bFullScreen = pStateInfo->FullScreen;
|
|
_bQuickEdit = pStateInfo->QuickEdit;
|
|
_bAutoPosition = pStateInfo->AutoPosition;
|
|
_bInsertMode = pStateInfo->InsertMode;
|
|
_bHistoryNoDup = pStateInfo->HistoryNoDup;
|
|
_uHistoryBufferSize = pStateInfo->HistoryBufferSize;
|
|
_uNumberOfHistoryBuffers = pStateInfo->NumberOfHistoryBuffers;
|
|
for (size_t i = 0; i < std::size(pStateInfo->ColorTable); i++)
|
|
{
|
|
SetColorTableEntry(i, pStateInfo->ColorTable[i]);
|
|
}
|
|
_uCodePage = pStateInfo->CodePage;
|
|
_bWrapText = !!pStateInfo->fWrapText;
|
|
_fFilterOnPaste = pStateInfo->fFilterOnPaste;
|
|
_fCtrlKeyShortcutsDisabled = pStateInfo->fCtrlKeyShortcutsDisabled;
|
|
_bLineSelection = pStateInfo->fLineSelection;
|
|
_bWindowAlpha = pStateInfo->bWindowTransparency;
|
|
_CursorColor = pStateInfo->CursorColor;
|
|
_CursorType = static_cast<CursorType>(pStateInfo->CursorType);
|
|
_fInterceptCopyPaste = pStateInfo->InterceptCopyPaste;
|
|
_DefaultForeground = pStateInfo->DefaultForeground;
|
|
_DefaultBackground = pStateInfo->DefaultBackground;
|
|
_TerminalScrolling = pStateInfo->TerminalScrolling;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Create a CONSOLE_STATE_INFO with the current state of this settings structure.
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - a CONSOLE_STATE_INFO with the current state of this settings structure.
|
|
CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
|
|
{
|
|
CONSOLE_STATE_INFO csi = { 0 };
|
|
csi.ScreenAttributes = _wFillAttribute;
|
|
csi.PopupAttributes = _wPopupFillAttribute;
|
|
csi.ScreenBufferSize = _dwScreenBufferSize;
|
|
csi.WindowSize = _dwWindowSize;
|
|
csi.WindowPosX = (SHORT)_dwWindowOrigin.X;
|
|
csi.WindowPosY = (SHORT)_dwWindowOrigin.Y;
|
|
csi.FontSize = _dwFontSize;
|
|
csi.FontFamily = _uFontFamily;
|
|
csi.FontWeight = _uFontWeight;
|
|
StringCchCopyW(csi.FaceName, ARRAYSIZE(_FaceName), _FaceName);
|
|
csi.CursorSize = _uCursorSize;
|
|
csi.FullScreen = _bFullScreen;
|
|
csi.QuickEdit = _bQuickEdit;
|
|
csi.AutoPosition = _bAutoPosition;
|
|
csi.InsertMode = _bInsertMode;
|
|
csi.HistoryNoDup = _bHistoryNoDup;
|
|
csi.HistoryBufferSize = _uHistoryBufferSize;
|
|
csi.NumberOfHistoryBuffers = _uNumberOfHistoryBuffers;
|
|
for (size_t i = 0; i < std::size(csi.ColorTable); i++)
|
|
{
|
|
csi.ColorTable[i] = GetColorTableEntry(i);
|
|
}
|
|
csi.CodePage = _uCodePage;
|
|
csi.fWrapText = !!_bWrapText;
|
|
csi.fFilterOnPaste = _fFilterOnPaste;
|
|
csi.fCtrlKeyShortcutsDisabled = _fCtrlKeyShortcutsDisabled;
|
|
csi.fLineSelection = _bLineSelection;
|
|
csi.bWindowTransparency = _bWindowAlpha;
|
|
csi.CursorColor = _CursorColor;
|
|
csi.CursorType = static_cast<unsigned int>(_CursorType);
|
|
csi.InterceptCopyPaste = _fInterceptCopyPaste;
|
|
csi.DefaultForeground = _DefaultForeground;
|
|
csi.DefaultBackground = _DefaultBackground;
|
|
csi.TerminalScrolling = _TerminalScrolling;
|
|
return csi;
|
|
}
|
|
|
|
void Settings::Validate()
|
|
{
|
|
// If we were explicitly given a size in pixels from the startup info, divide by the font to turn it into characters.
|
|
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331%28v=vs.85%29.aspx
|
|
if (WI_IsFlagSet(_dwStartupFlags, STARTF_USESIZE))
|
|
{
|
|
// TODO: FIX
|
|
//// Get the font that we're going to use to convert pixels to characters.
|
|
//DWORD const dwFontIndexWant = FindCreateFont(_uFontFamily,
|
|
// _FaceName,
|
|
// _dwFontSize,
|
|
// _uFontWeight,
|
|
// _uCodePage);
|
|
|
|
//_dwWindowSize.X /= g_pfiFontInfo[dwFontIndexWant].Size.X;
|
|
//_dwWindowSize.Y /= g_pfiFontInfo[dwFontIndexWant].Size.Y;
|
|
}
|
|
|
|
// minimum screen buffer size 1x1
|
|
_dwScreenBufferSize.X = std::max(_dwScreenBufferSize.X, 1i16);
|
|
_dwScreenBufferSize.Y = std::max(_dwScreenBufferSize.Y, 1i16);
|
|
|
|
// minimum window size size 1x1
|
|
_dwWindowSize.X = std::max(_dwWindowSize.X, 1i16);
|
|
_dwWindowSize.Y = std::max(_dwWindowSize.Y, 1i16);
|
|
|
|
// if buffer size is less than window size, increase buffer size to meet window size
|
|
_dwScreenBufferSize.X = std::max(_dwWindowSize.X, _dwScreenBufferSize.X);
|
|
_dwScreenBufferSize.Y = std::max(_dwWindowSize.Y, _dwScreenBufferSize.Y);
|
|
|
|
// ensure that the window alpha value is not below the minimum. (no invisible windows)
|
|
// if it's below minimum, just set it to the opaque value
|
|
if (_bWindowAlpha < MIN_WINDOW_OPACITY)
|
|
{
|
|
_bWindowAlpha = BYTE_MAX;
|
|
}
|
|
|
|
// If text wrapping is on, ensure that the window width is the same as the buffer width.
|
|
if (_bWrapText)
|
|
{
|
|
_dwWindowSize.X = _dwScreenBufferSize.X;
|
|
}
|
|
|
|
// Ensure that our fill attributes only contain colors and not any box drawing or invert attributes.
|
|
WI_ClearAllFlags(_wFillAttribute, ~(FG_ATTRS | BG_ATTRS));
|
|
WI_ClearAllFlags(_wPopupFillAttribute, ~(FG_ATTRS | BG_ATTRS));
|
|
|
|
// If the extended color options are set to invalid values (all the same color), reset them.
|
|
if (_CursorColor != Cursor::s_InvertCursorColor && _CursorColor == _DefaultBackground)
|
|
{
|
|
_CursorColor = Cursor::s_InvertCursorColor;
|
|
}
|
|
|
|
if (_DefaultForeground != INVALID_COLOR && _DefaultForeground == _DefaultBackground)
|
|
{
|
|
// INVALID_COLOR is used as an "unset" sentinel in future attribute functions.
|
|
_DefaultForeground = _DefaultBackground = INVALID_COLOR;
|
|
// If the damaged settings _further_ propagated to the default fill attribute, fix it.
|
|
if (_wFillAttribute == 0)
|
|
{
|
|
// These attributes were taken from the Settings ctor and equal "gray on black"
|
|
_wFillAttribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
}
|
|
}
|
|
|
|
FAIL_FAST_IF(!(_dwWindowSize.X > 0));
|
|
FAIL_FAST_IF(!(_dwWindowSize.Y > 0));
|
|
FAIL_FAST_IF(!(_dwScreenBufferSize.X > 0));
|
|
FAIL_FAST_IF(!(_dwScreenBufferSize.Y > 0));
|
|
}
|
|
|
|
DWORD Settings::GetVirtTermLevel() const
|
|
{
|
|
return _dwVirtTermLevel;
|
|
}
|
|
void Settings::SetVirtTermLevel(const DWORD dwVirtTermLevel)
|
|
{
|
|
_dwVirtTermLevel = dwVirtTermLevel;
|
|
}
|
|
|
|
bool Settings::IsAltF4CloseAllowed() const
|
|
{
|
|
return _fAllowAltF4Close;
|
|
}
|
|
void Settings::SetAltF4CloseAllowed(const bool fAllowAltF4Close)
|
|
{
|
|
_fAllowAltF4Close = fAllowAltF4Close;
|
|
}
|
|
|
|
bool Settings::IsReturnOnNewlineAutomatic() const
|
|
{
|
|
return _fAutoReturnOnNewline;
|
|
}
|
|
void Settings::SetAutomaticReturnOnNewline(const bool fAutoReturnOnNewline)
|
|
{
|
|
_fAutoReturnOnNewline = fAutoReturnOnNewline;
|
|
}
|
|
|
|
bool Settings::IsGridRenderingAllowedWorldwide() const
|
|
{
|
|
return _fRenderGridWorldwide;
|
|
}
|
|
void Settings::SetGridRenderingAllowedWorldwide(const bool fGridRenderingAllowed)
|
|
{
|
|
// Only trigger a notification and update the status if something has changed.
|
|
if (_fRenderGridWorldwide != fGridRenderingAllowed)
|
|
{
|
|
_fRenderGridWorldwide = fGridRenderingAllowed;
|
|
|
|
if (ServiceLocator::LocateGlobals().pRender != nullptr)
|
|
{
|
|
ServiceLocator::LocateGlobals().pRender->TriggerRedrawAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Settings::IsScreenReversed() const
|
|
{
|
|
return _fScreenReversed;
|
|
}
|
|
void Settings::SetScreenReversed(const bool fScreenReversed)
|
|
{
|
|
_fScreenReversed = fScreenReversed;
|
|
}
|
|
|
|
bool Settings::GetFilterOnPaste() const
|
|
{
|
|
return _fFilterOnPaste;
|
|
}
|
|
void Settings::SetFilterOnPaste(const bool fFilterOnPaste)
|
|
{
|
|
_fFilterOnPaste = fFilterOnPaste;
|
|
}
|
|
|
|
const std::wstring_view Settings::GetLaunchFaceName() const
|
|
{
|
|
return _LaunchFaceName;
|
|
}
|
|
void Settings::SetLaunchFaceName(const std::wstring_view launchFaceName)
|
|
{
|
|
_LaunchFaceName = launchFaceName;
|
|
}
|
|
|
|
UINT Settings::GetCodePage() const
|
|
{
|
|
return _uCodePage;
|
|
}
|
|
void Settings::SetCodePage(const UINT uCodePage)
|
|
{
|
|
_uCodePage = uCodePage;
|
|
}
|
|
|
|
UINT Settings::GetScrollScale() const
|
|
{
|
|
return _uScrollScale;
|
|
}
|
|
void Settings::SetScrollScale(const UINT uScrollScale)
|
|
{
|
|
_uScrollScale = uScrollScale;
|
|
}
|
|
|
|
bool Settings::GetTrimLeadingZeros() const
|
|
{
|
|
return _fTrimLeadingZeros;
|
|
}
|
|
void Settings::SetTrimLeadingZeros(const bool fTrimLeadingZeros)
|
|
{
|
|
_fTrimLeadingZeros = fTrimLeadingZeros;
|
|
}
|
|
|
|
bool Settings::GetEnableColorSelection() const
|
|
{
|
|
return _fEnableColorSelection;
|
|
}
|
|
void Settings::SetEnableColorSelection(const bool fEnableColorSelection)
|
|
{
|
|
_fEnableColorSelection = fEnableColorSelection;
|
|
}
|
|
|
|
bool Settings::GetLineSelection() const
|
|
{
|
|
return _bLineSelection;
|
|
}
|
|
void Settings::SetLineSelection(const bool bLineSelection)
|
|
{
|
|
_bLineSelection = bLineSelection;
|
|
}
|
|
|
|
bool Settings::GetWrapText() const
|
|
{
|
|
return _bWrapText;
|
|
}
|
|
void Settings::SetWrapText(const bool bWrapText)
|
|
{
|
|
_bWrapText = bWrapText;
|
|
}
|
|
|
|
bool Settings::GetCtrlKeyShortcutsDisabled() const
|
|
{
|
|
return _fCtrlKeyShortcutsDisabled;
|
|
}
|
|
void Settings::SetCtrlKeyShortcutsDisabled(const bool fCtrlKeyShortcutsDisabled)
|
|
{
|
|
_fCtrlKeyShortcutsDisabled = fCtrlKeyShortcutsDisabled;
|
|
}
|
|
|
|
BYTE Settings::GetWindowAlpha() const
|
|
{
|
|
return _bWindowAlpha;
|
|
}
|
|
void Settings::SetWindowAlpha(const BYTE bWindowAlpha)
|
|
{
|
|
// if we're out of bounds, set it to 100% opacity so it appears as if nothing happened.
|
|
_bWindowAlpha = (bWindowAlpha < MIN_WINDOW_OPACITY) ? BYTE_MAX : bWindowAlpha;
|
|
}
|
|
|
|
DWORD Settings::GetHotKey() const
|
|
{
|
|
return _dwHotKey;
|
|
}
|
|
void Settings::SetHotKey(const DWORD dwHotKey)
|
|
{
|
|
_dwHotKey = dwHotKey;
|
|
}
|
|
|
|
DWORD Settings::GetStartupFlags() const
|
|
{
|
|
return _dwStartupFlags;
|
|
}
|
|
void Settings::SetStartupFlags(const DWORD dwStartupFlags)
|
|
{
|
|
_dwStartupFlags = dwStartupFlags;
|
|
}
|
|
|
|
WORD Settings::GetFillAttribute() const
|
|
{
|
|
return _wFillAttribute;
|
|
}
|
|
void Settings::SetFillAttribute(const WORD wFillAttribute)
|
|
{
|
|
_wFillAttribute = wFillAttribute;
|
|
|
|
// Do not allow the default fill attribute to use any attrs other than fg/bg colors.
|
|
// This prevents us from accidentally inverting everything or suddenly drawing lines
|
|
// everywhere by default.
|
|
WI_ClearAllFlags(_wFillAttribute, ~(FG_ATTRS | BG_ATTRS));
|
|
}
|
|
|
|
WORD Settings::GetPopupFillAttribute() const
|
|
{
|
|
return _wPopupFillAttribute;
|
|
}
|
|
void Settings::SetPopupFillAttribute(const WORD wPopupFillAttribute)
|
|
{
|
|
_wPopupFillAttribute = wPopupFillAttribute;
|
|
|
|
// Do not allow the default popup fill attribute to use any attrs other than fg/bg colors.
|
|
// This prevents us from accidentally inverting everything or suddenly drawing lines
|
|
// everywhere by default.
|
|
WI_ClearAllFlags(_wPopupFillAttribute, ~(FG_ATTRS | BG_ATTRS));
|
|
}
|
|
|
|
WORD Settings::GetShowWindow() const
|
|
{
|
|
return _wShowWindow;
|
|
}
|
|
void Settings::SetShowWindow(const WORD wShowWindow)
|
|
{
|
|
_wShowWindow = wShowWindow;
|
|
}
|
|
|
|
WORD Settings::GetReserved() const
|
|
{
|
|
return _wReserved;
|
|
}
|
|
void Settings::SetReserved(const WORD wReserved)
|
|
{
|
|
_wReserved = wReserved;
|
|
}
|
|
|
|
COORD Settings::GetScreenBufferSize() const
|
|
{
|
|
return _dwScreenBufferSize;
|
|
}
|
|
void Settings::SetScreenBufferSize(const COORD dwScreenBufferSize)
|
|
{
|
|
_dwScreenBufferSize = dwScreenBufferSize;
|
|
}
|
|
|
|
COORD Settings::GetWindowSize() const
|
|
{
|
|
return _dwWindowSize;
|
|
}
|
|
void Settings::SetWindowSize(const COORD dwWindowSize)
|
|
{
|
|
_dwWindowSize = dwWindowSize;
|
|
}
|
|
|
|
bool Settings::IsWindowSizePixelsValid() const
|
|
{
|
|
return _fUseWindowSizePixels;
|
|
}
|
|
COORD Settings::GetWindowSizePixels() const
|
|
{
|
|
return _dwWindowSizePixels;
|
|
}
|
|
void Settings::SetWindowSizePixels(const COORD dwWindowSizePixels)
|
|
{
|
|
_dwWindowSizePixels = dwWindowSizePixels;
|
|
}
|
|
|
|
COORD Settings::GetWindowOrigin() const
|
|
{
|
|
return _dwWindowOrigin;
|
|
}
|
|
void Settings::SetWindowOrigin(const COORD dwWindowOrigin)
|
|
{
|
|
_dwWindowOrigin = dwWindowOrigin;
|
|
}
|
|
|
|
DWORD Settings::GetFont() const
|
|
{
|
|
return _nFont;
|
|
}
|
|
void Settings::SetFont(const DWORD nFont)
|
|
{
|
|
_nFont = nFont;
|
|
}
|
|
|
|
COORD Settings::GetFontSize() const
|
|
{
|
|
return _dwFontSize;
|
|
}
|
|
void Settings::SetFontSize(const COORD dwFontSize)
|
|
{
|
|
_dwFontSize = dwFontSize;
|
|
}
|
|
|
|
UINT Settings::GetFontFamily() const
|
|
{
|
|
return _uFontFamily;
|
|
}
|
|
void Settings::SetFontFamily(const UINT uFontFamily)
|
|
{
|
|
_uFontFamily = uFontFamily;
|
|
}
|
|
|
|
UINT Settings::GetFontWeight() const
|
|
{
|
|
return _uFontWeight;
|
|
}
|
|
void Settings::SetFontWeight(const UINT uFontWeight)
|
|
{
|
|
_uFontWeight = uFontWeight;
|
|
}
|
|
|
|
const WCHAR* const Settings::GetFaceName() const
|
|
{
|
|
return _FaceName;
|
|
}
|
|
void Settings::SetFaceName(const std::wstring_view faceName)
|
|
{
|
|
auto extent = std::min<size_t>(faceName.size(), ARRAYSIZE(_FaceName));
|
|
StringCchCopyW(_FaceName, extent, faceName.data());
|
|
}
|
|
|
|
UINT Settings::GetCursorSize() const
|
|
{
|
|
return _uCursorSize;
|
|
}
|
|
void Settings::SetCursorSize(const UINT uCursorSize)
|
|
{
|
|
_uCursorSize = uCursorSize;
|
|
}
|
|
|
|
bool Settings::GetFullScreen() const
|
|
{
|
|
return _bFullScreen;
|
|
}
|
|
void Settings::SetFullScreen(const bool bFullScreen)
|
|
{
|
|
_bFullScreen = bFullScreen;
|
|
}
|
|
|
|
bool Settings::GetQuickEdit() const
|
|
{
|
|
return _bQuickEdit;
|
|
}
|
|
void Settings::SetQuickEdit(const bool bQuickEdit)
|
|
{
|
|
_bQuickEdit = bQuickEdit;
|
|
}
|
|
|
|
bool Settings::GetInsertMode() const
|
|
{
|
|
return _bInsertMode;
|
|
}
|
|
void Settings::SetInsertMode(const bool bInsertMode)
|
|
{
|
|
_bInsertMode = bInsertMode;
|
|
}
|
|
|
|
bool Settings::GetAutoPosition() const
|
|
{
|
|
return _bAutoPosition;
|
|
}
|
|
void Settings::SetAutoPosition(const bool bAutoPosition)
|
|
{
|
|
_bAutoPosition = bAutoPosition;
|
|
}
|
|
|
|
UINT Settings::GetHistoryBufferSize() const
|
|
{
|
|
return _uHistoryBufferSize;
|
|
}
|
|
void Settings::SetHistoryBufferSize(const UINT uHistoryBufferSize)
|
|
{
|
|
_uHistoryBufferSize = uHistoryBufferSize;
|
|
}
|
|
|
|
UINT Settings::GetNumberOfHistoryBuffers() const
|
|
{
|
|
return _uNumberOfHistoryBuffers;
|
|
}
|
|
void Settings::SetNumberOfHistoryBuffers(const UINT uNumberOfHistoryBuffers)
|
|
{
|
|
_uNumberOfHistoryBuffers = uNumberOfHistoryBuffers;
|
|
}
|
|
|
|
bool Settings::GetHistoryNoDup() const
|
|
{
|
|
return _bHistoryNoDup;
|
|
}
|
|
void Settings::SetHistoryNoDup(const bool bHistoryNoDup)
|
|
{
|
|
_bHistoryNoDup = bHistoryNoDup;
|
|
}
|
|
|
|
std::basic_string_view<COLORREF> Settings::Get16ColorTable() const
|
|
{
|
|
return Get256ColorTable().substr(0, 16);
|
|
}
|
|
|
|
std::basic_string_view<COLORREF> Settings::Get256ColorTable() const
|
|
{
|
|
return { _colorTable.data(), _colorTable.size() };
|
|
}
|
|
|
|
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
|
|
{
|
|
_colorTable.at(index) = ColorValue;
|
|
}
|
|
|
|
bool Settings::IsStartupTitleIsLinkNameSet() const
|
|
{
|
|
return WI_IsFlagSet(_dwStartupFlags, STARTF_TITLEISLINKNAME);
|
|
}
|
|
|
|
bool Settings::IsFaceNameSet() const
|
|
{
|
|
return GetFaceName()[0] != '\0';
|
|
}
|
|
|
|
void Settings::UnsetStartupFlag(const DWORD dwFlagToUnset)
|
|
{
|
|
_dwStartupFlags &= ~dwFlagToUnset;
|
|
}
|
|
|
|
COLORREF Settings::GetColorTableEntry(const size_t index) const
|
|
{
|
|
return _colorTable.at(index);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Generates a legacy attribute from the given TextAttributes.
|
|
// This needs to be a method on the Settings because the generated index
|
|
// is dependent upon the default fill attributes.
|
|
// Parameters:
|
|
// - attributes - The TextAttributes to generate a legacy attribute for.
|
|
// Return value:
|
|
// - A WORD representing the legacy attributes that most closely represent the given fullcolor attributes.
|
|
WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const
|
|
{
|
|
return attributes.GetLegacyAttributes(_wFillAttribute);
|
|
}
|
|
|
|
COLORREF Settings::GetCursorColor() const noexcept
|
|
{
|
|
return _CursorColor;
|
|
}
|
|
|
|
CursorType Settings::GetCursorType() const noexcept
|
|
{
|
|
return _CursorType;
|
|
}
|
|
|
|
void Settings::SetCursorColor(const COLORREF CursorColor) noexcept
|
|
{
|
|
_CursorColor = CursorColor;
|
|
}
|
|
|
|
void Settings::SetCursorType(const CursorType cursorType) noexcept
|
|
{
|
|
_CursorType = cursorType;
|
|
}
|
|
|
|
bool Settings::GetInterceptCopyPaste() const noexcept
|
|
{
|
|
return _fInterceptCopyPaste;
|
|
}
|
|
|
|
void Settings::SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept
|
|
{
|
|
_fInterceptCopyPaste = interceptCopyPaste;
|
|
}
|
|
|
|
COLORREF Settings::GetDefaultForegroundColor() const noexcept
|
|
{
|
|
return _DefaultForeground;
|
|
}
|
|
|
|
void Settings::SetDefaultForegroundColor(const COLORREF defaultForeground) noexcept
|
|
{
|
|
_DefaultForeground = defaultForeground;
|
|
}
|
|
|
|
COLORREF Settings::GetDefaultBackgroundColor() const noexcept
|
|
{
|
|
return _DefaultBackground;
|
|
}
|
|
|
|
void Settings::SetDefaultBackgroundColor(const COLORREF defaultBackground) noexcept
|
|
{
|
|
_DefaultBackground = defaultBackground;
|
|
}
|
|
|
|
TextAttribute Settings::GetDefaultAttributes() const noexcept
|
|
{
|
|
auto attrs = TextAttribute{ _wFillAttribute };
|
|
if (_DefaultForeground != INVALID_COLOR)
|
|
{
|
|
attrs.SetDefaultForeground();
|
|
}
|
|
if (_DefaultBackground != INVALID_COLOR)
|
|
{
|
|
attrs.SetDefaultBackground();
|
|
}
|
|
return attrs;
|
|
}
|
|
|
|
bool Settings::IsTerminalScrolling() const noexcept
|
|
{
|
|
return _TerminalScrolling;
|
|
}
|
|
|
|
void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept
|
|
{
|
|
_TerminalScrolling = terminalScrollingEnabled;
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Determines whether our primary renderer should be DirectX or GDI.
|
|
// - This is based on user preference and velocity hold back state.
|
|
// Return Value:
|
|
// - True means use DirectX renderer. False means use GDI renderer.
|
|
bool Settings::GetUseDx() const noexcept
|
|
{
|
|
return _fUseDx;
|
|
}
|
|
|
|
// 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 legacy attributes.
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - the default foreground color of the console.
|
|
COLORREF Settings::CalculateDefaultForeground() const noexcept
|
|
{
|
|
const auto fg = GetDefaultForegroundColor();
|
|
return fg != INVALID_COLOR ? fg : GetColorTableEntry(LOBYTE(_wFillAttribute) & 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 legacy attributes.
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - the default background color of the console.
|
|
COLORREF Settings::CalculateDefaultBackground() const noexcept
|
|
{
|
|
const auto bg = GetDefaultBackgroundColor();
|
|
return bg != INVALID_COLOR ? bg : GetColorTableEntry((LOBYTE(_wFillAttribute) & BG_ATTRS) >> 4);
|
|
}
|
|
|
|
// Method Description:
|
|
// - Get the foreground color of a particular text attribute, using our color
|
|
// table, and our configured default attributes.
|
|
// Arguments:
|
|
// - attr: the TextAttribute to retrieve the foreground color of.
|
|
// Return Value:
|
|
// - The color value of the attribute's foreground TextColor.
|
|
COLORREF Settings::LookupForegroundColor(const TextAttribute& attr) const noexcept
|
|
{
|
|
const auto tableView = Get256ColorTable();
|
|
if (_fScreenReversed)
|
|
{
|
|
return attr.CalculateRgbBackground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
|
|
}
|
|
else
|
|
{
|
|
return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
|
|
}
|
|
}
|
|
|
|
// Method Description:
|
|
// - Get the background color of a particular text attribute, using our color
|
|
// table, and our configured default attributes.
|
|
// Arguments:
|
|
// - attr: the TextAttribute to retrieve the background color of.
|
|
// Return Value:
|
|
// - The color value of the attribute's background TextColor.
|
|
COLORREF Settings::LookupBackgroundColor(const TextAttribute& attr) const noexcept
|
|
{
|
|
const auto tableView = Get256ColorTable();
|
|
if (_fScreenReversed)
|
|
{
|
|
return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
|
|
}
|
|
else
|
|
{
|
|
return attr.CalculateRgbBackground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
|
|
}
|
|
}
|
|
|
|
bool Settings::GetCopyColor() const noexcept
|
|
{
|
|
return _fCopyColor;
|
|
}
|