terminal/src/host/settings.cpp
James Holderness b604117421
Standardize the color table order (#11602)
## Summary of the Pull Request

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

## References

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

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

## Detailed Description of the Pull Request / Additional comments

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

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

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

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

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

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

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

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

## Validation Steps Performed

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

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

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

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

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

I've also tested similar code - just filling the visible window - with SGR VT sequences of various types, and the performance seems about the same as it was before.
2021-11-04 22:13:22 +00:00

837 lines
24 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/colorTable.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(), _colorTable.size() };
::Microsoft::Console::Utils::InitializeColorTable(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(), 16 };
::Microsoft::Console::Utils::InitializeColorTable(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++)
{
SetLegacyColorTableEntry(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] = GetLegacyColorTableEntry(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;
}
}
// At this point the default fill attributes are fully initialized
// so we can pass on the final colors to the TextAttribute class.
TextAttribute::SetLegacyDefaultAttributes(_wFillAttribute);
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;
}
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;
}
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
{
_colorTable.at(index) = ColorValue;
}
COLORREF Settings::GetColorTableEntry(const size_t index) const
{
return _colorTable.at(index);
}
void Settings::SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue)
{
_colorTable.at(TextColor::TransposeLegacyIndex(index)) = ColorValue;
}
COLORREF Settings::GetLegacyColorTableEntry(const size_t index) const
{
return _colorTable.at(TextColor::TransposeLegacyIndex(index));
}
COLORREF Settings::GetCursorColor() const noexcept
{
return _CursorColor;
}
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;
}
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;
}
bool Settings::GetCopyColor() const noexcept
{
return _fCopyColor;
}