terminal/src/host/settings.cpp

989 lines
30 KiB
C++
Raw Normal View History

// 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.
Add support for the DECSCNM screen mode (#3817) ## Summary of the Pull Request This adds support for the [`DECSCNM`](https://vt100.net/docs/vt510-rm/DECSCNM.html) private mode escape sequence, which toggles the display between normal and reverse screen modes. When reversed, the background and foreground colors are switched. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests. ## References This also fixes issue #72 for the most part, although if you toggle the mode too fast, there is no discernible flash. ## PR Checklist * [x] Closes #3773 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments I've implemented this as a new flag in the `Settings` class, along with updates to the `LookupForegroundColor` and `LookupBackgroundColor` methods, to switch the returned foreground and background colors when that flag is set. It also required a new private API in the `ConGetSet` interface to toggle the setting. And that API is then called from the `AdaptDispatch` class when the screen mode escape sequence is received. The last thing needed was to add a step to the `HardReset` method, to reset the mode back to normal, which is one of the `RIS` requirements. Note that this does currently work in the Windows Terminal, but once #2661 is implemented that may no longer be the case. It might become necessary to let the mode change sequences pass through conpty, and handle the color reversing on the client side. ## Validation Steps Performed I've added a state machine test to make sure the escape sequence is dispatched correctly, and a screen buffer test to confirm that the mode change does alter the interpretation of colors as expected. I've also confirmed that the various "light background" tests in Vttest now display correctly, and that the `tput flash` command (in a bash shell) does actually cause the screen to flash.
2020-01-22 23:29:50 +01:00
_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, gsl::narrow<ptrdiff_t>(COLOR_TABLE_SIZE) };
gsl::span<COLORREF> xtermTableView = { _XtermColorTable, gsl::narrow<ptrdiff_t>(XTERM_COLOR_TABLE_SIZE) };
::Microsoft::Console::Utils::Initialize256ColorTable(xtermTableView);
::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, gsl::narrow<ptrdiff_t>(COLOR_TABLE_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;
memmove(_ColorTable, pStateInfo->ColorTable, sizeof(_ColorTable));
_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;
memmove(csi.ColorTable, _ColorTable, sizeof(_ColorTable));
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();
}
}
}
Add support for the DECSCNM screen mode (#3817) ## Summary of the Pull Request This adds support for the [`DECSCNM`](https://vt100.net/docs/vt510-rm/DECSCNM.html) private mode escape sequence, which toggles the display between normal and reverse screen modes. When reversed, the background and foreground colors are switched. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests. ## References This also fixes issue #72 for the most part, although if you toggle the mode too fast, there is no discernible flash. ## PR Checklist * [x] Closes #3773 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments I've implemented this as a new flag in the `Settings` class, along with updates to the `LookupForegroundColor` and `LookupBackgroundColor` methods, to switch the returned foreground and background colors when that flag is set. It also required a new private API in the `ConGetSet` interface to toggle the setting. And that API is then called from the `AdaptDispatch` class when the screen mode escape sequence is received. The last thing needed was to add a step to the `HardReset` method, to reset the mode back to normal, which is one of the `RIS` requirements. Note that this does currently work in the Windows Terminal, but once #2661 is implemented that may no longer be the case. It might become necessary to let the mode change sequences pass through conpty, and handle the color reversing on the client side. ## Validation Steps Performed I've added a state machine test to make sure the escape sequence is dispatched correctly, and a screen buffer test to confirm that the mode change does alter the interpretation of colors as expected. I've also confirmed that the various "light background" tests in Vttest now display correctly, and that the `tput flash` command (in a bash shell) does actually cause the screen to flash.
2020-01-22 23:29:50 +01:00
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;
}
const COLORREF* const Settings::GetColorTable() const
{
return _ColorTable;
}
void Settings::SetColorTable(_In_reads_(cSize) const COLORREF* const pColorTable, const size_t cSize)
{
size_t cSizeWritten = std::min(cSize, static_cast<size_t>(COLOR_TABLE_SIZE));
memmove(_ColorTable, pColorTable, cSizeWritten * sizeof(COLORREF));
}
void Settings::SetColorTableEntry(const size_t index, const COLORREF ColorValue)
{
if (index < ARRAYSIZE(_ColorTable))
{
_ColorTable[index] = ColorValue;
}
else
{
_XtermColorTable[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;
}
const size_t Settings::GetColorTableSize() const
{
return ARRAYSIZE(_ColorTable);
}
COLORREF Settings::GetColorTableEntry(const size_t index) const
{
if (index < ARRAYSIZE(_ColorTable))
{
return _ColorTable[index];
}
else
{
return _XtermColorTable[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 particular values of the color table at the time of reading.
// Parameters:
// - attributes - The TextAttributes to generate a legacy attribute for.
// Return value:
// - A WORD representing the entry in the color table that most closely represents the given fullcolor attributes.
WORD Settings::GenerateLegacyAttributes(const TextAttribute attributes) const
{
const WORD wLegacyOriginal = attributes.GetLegacyAttributes();
if (attributes.IsLegacy())
{
return wLegacyOriginal;
}
// We need to construct the legacy attributes manually
// First start with whatever our default legacy attributes are
BYTE fgIndex = static_cast<BYTE>((_wFillAttribute & FG_ATTRS));
BYTE bgIndex = static_cast<BYTE>((_wFillAttribute & BG_ATTRS) >> 4);
// If the attributes have any RGB components, we need to match that RGB
// color to a color table value.
if (attributes.IsRgb())
{
// If the attribute doesn't have a "default" colored *ground, look up
2019-05-21 08:15:44 +02:00
// the nearest color table value for its *ground.
const COLORREF rgbForeground = LookupForegroundColor(attributes);
fgIndex = attributes.ForegroundIsDefault() ?
fgIndex :
static_cast<BYTE>(FindNearestTableIndex(rgbForeground));
const COLORREF rgbBackground = LookupBackgroundColor(attributes);
bgIndex = attributes.BackgroundIsDefault() ?
bgIndex :
static_cast<BYTE>(FindNearestTableIndex(rgbBackground));
}
// TextAttribute::GetLegacyAttributes(BYTE, BYTE) will use the legacy value
// it has if the component is a legacy index, otherwise it will use the
// provided byte for each index. In this way, we can provide a value to
// use should it not already have one.
const WORD wCompleteAttr = attributes.GetLegacyAttributes(fgIndex, bgIndex);
return wCompleteAttr;
}
//Routine Description:
// For a given RGB color Color, finds the nearest color from the array ColorTable, and returns the index of that match.
//Arguments:
// - Color - The RGB color to fine the nearest color to.
// - ColorTable - The array of colors to find a nearest color from.
// - cColorTable - The number of elements in ColorTable
// Return value:
// The index in ColorTable of the nearest match to Color.
WORD Settings::FindNearestTableIndex(const COLORREF Color) const
{
return ::FindNearestTableIndex(Color, _ColorTable, ARRAYSIZE(_ColorTable));
}
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 : ForegroundColor(GetFillAttribute(), GetColorTable(), GetColorTableSize());
}
// 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 : BackgroundColor(GetFillAttribute(), GetColorTable(), GetColorTableSize());
}
// 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 = std::basic_string_view<COLORREF>(&GetColorTable()[0], GetColorTableSize());
Add support for the DECSCNM screen mode (#3817) ## Summary of the Pull Request This adds support for the [`DECSCNM`](https://vt100.net/docs/vt510-rm/DECSCNM.html) private mode escape sequence, which toggles the display between normal and reverse screen modes. When reversed, the background and foreground colors are switched. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests. ## References This also fixes issue #72 for the most part, although if you toggle the mode too fast, there is no discernible flash. ## PR Checklist * [x] Closes #3773 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments I've implemented this as a new flag in the `Settings` class, along with updates to the `LookupForegroundColor` and `LookupBackgroundColor` methods, to switch the returned foreground and background colors when that flag is set. It also required a new private API in the `ConGetSet` interface to toggle the setting. And that API is then called from the `AdaptDispatch` class when the screen mode escape sequence is received. The last thing needed was to add a step to the `HardReset` method, to reset the mode back to normal, which is one of the `RIS` requirements. Note that this does currently work in the Windows Terminal, but once #2661 is implemented that may no longer be the case. It might become necessary to let the mode change sequences pass through conpty, and handle the color reversing on the client side. ## Validation Steps Performed I've added a state machine test to make sure the escape sequence is dispatched correctly, and a screen buffer test to confirm that the mode change does alter the interpretation of colors as expected. I've also confirmed that the various "light background" tests in Vttest now display correctly, and that the `tput flash` command (in a bash shell) does actually cause the screen to flash.
2020-01-22 23:29:50 +01:00
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 = std::basic_string_view<COLORREF>(&GetColorTable()[0], GetColorTableSize());
Add support for the DECSCNM screen mode (#3817) ## Summary of the Pull Request This adds support for the [`DECSCNM`](https://vt100.net/docs/vt510-rm/DECSCNM.html) private mode escape sequence, which toggles the display between normal and reverse screen modes. When reversed, the background and foreground colors are switched. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests. ## References This also fixes issue #72 for the most part, although if you toggle the mode too fast, there is no discernible flash. ## PR Checklist * [x] Closes #3773 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments I've implemented this as a new flag in the `Settings` class, along with updates to the `LookupForegroundColor` and `LookupBackgroundColor` methods, to switch the returned foreground and background colors when that flag is set. It also required a new private API in the `ConGetSet` interface to toggle the setting. And that API is then called from the `AdaptDispatch` class when the screen mode escape sequence is received. The last thing needed was to add a step to the `HardReset` method, to reset the mode back to normal, which is one of the `RIS` requirements. Note that this does currently work in the Windows Terminal, but once #2661 is implemented that may no longer be the case. It might become necessary to let the mode change sequences pass through conpty, and handle the color reversing on the client side. ## Validation Steps Performed I've added a state machine test to make sure the escape sequence is dispatched correctly, and a screen buffer test to confirm that the mode change does alter the interpretation of colors as expected. I've also confirmed that the various "light background" tests in Vttest now display correctly, and that the `tput flash` command (in a bash shell) does actually cause the screen to flash.
2020-01-22 23:29:50 +01:00
if (_fScreenReversed)
{
return attr.CalculateRgbForeground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
}
else
{
return attr.CalculateRgbBackground(tableView, CalculateDefaultForeground(), CalculateDefaultBackground());
}
}
bool Settings::GetCopyColor() const noexcept
{
return _fCopyColor;
}