terminal/src/terminal/parser/OutputStateMachineEngine.hpp
Joel Bennett efd69990c6 Add support for OSC 10 and 11 to set the default colors (#891)
* Support OSC to set default background and foreground colors

* Update the Terminal theme when the background changes

* Fix whitespace per code-review

* Add Documentation Comments

Also fix a few outdated comments and whitespace

* Update Telemetry codes per code review

* Add Unit Tests for OSC ForegroundColor and BackgroundColor

* Add a couple additional test cases

* Minor doc and whitespace change per PR review

* Update comment help per code review

* Add another OSC 10 & 11 test case, improve output

* Comments and syntax cleanup per code reviews
2019-05-24 09:53:00 -07:00

279 lines
13 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/*
Module Name:
- OutputStateMachineEngine.hpp
Abstract:
- This is the implementation of the client VT output state machine engine.
*/
#pragma once
#include "../adapter/termDispatch.hpp"
#include "telemetry.hpp"
#include "IStateMachineEngine.hpp"
#include "../../inc/ITerminalOutputConnection.hpp"
namespace Microsoft::Console::VirtualTerminal
{
class OutputStateMachineEngine : public IStateMachineEngine
{
public:
OutputStateMachineEngine(ITermDispatch* const pDispatch);
~OutputStateMachineEngine();
bool ActionExecute(const wchar_t wch) override;
bool ActionExecuteFromEscape(const wchar_t wch) override;
bool ActionPrint(const wchar_t wch) override;
bool ActionPrintString(const wchar_t* const rgwch, const size_t cch) override;
bool ActionPassThroughString(const wchar_t* const rgwch,
size_t const cch) override;
bool ActionEscDispatch(const wchar_t wch,
const unsigned short cIntermediate,
const wchar_t wchIntermediate) override;
bool ActionCsiDispatch(const wchar_t wch,
const unsigned short cIntermediate,
const wchar_t wchIntermediate,
_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams);
bool ActionClear() override;
bool ActionIgnore() override;
bool ActionOscDispatch(const wchar_t wch,
const unsigned short sOscParam,
_Inout_updates_(cchOscString) wchar_t* const pwchOscStringBuffer,
const unsigned short cchOscString) override;
bool ActionSs3Dispatch(const wchar_t wch,
_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams) override;
bool FlushAtEndOfString() const override;
bool DispatchControlCharsFromEscape() const override;
void SetTerminalConnection(Microsoft::Console::ITerminalOutputConnection* const pTtyConnection,
std::function<bool()> pfnFlushToTerminal);
const ITermDispatch& Dispatch() const noexcept;
ITermDispatch& Dispatch() noexcept;
private:
std::unique_ptr<ITermDispatch> _dispatch;
Microsoft::Console::ITerminalOutputConnection* _pTtyConnection;
std::function<bool()> _pfnFlushToTerminal;
wchar_t _lastPrintedChar;
bool _IntermediateQuestionMarkDispatch(const wchar_t wchAction,
_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams);
bool _IntermediateExclamationDispatch(const wchar_t wch);
bool _IntermediateSpaceDispatch(const wchar_t wchAction,
_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams);
enum VTActionCodes : wchar_t
{
CUU_CursorUp = L'A',
CUD_CursorDown = L'B',
CUF_CursorForward = L'C',
CUB_CursorBackward = L'D',
CNL_CursorNextLine = L'E',
CPL_CursorPrevLine = L'F',
CHA_CursorHorizontalAbsolute = L'G',
CUP_CursorPosition = L'H',
ED_EraseDisplay = L'J',
EL_EraseLine = L'K',
SU_ScrollUp = L'S',
SD_ScrollDown = L'T',
ICH_InsertCharacter = L'@',
DCH_DeleteCharacter = L'P',
SGR_SetGraphicsRendition = L'm',
DECSC_CursorSave = L'7',
DECRC_CursorRestore = L'8',
DECSET_PrivateModeSet = L'h',
DECRST_PrivateModeReset = L'l',
ANSISYSSC_CursorSave = L's', // NOTE: Overlaps with DECLRMM/DECSLRM. Fix when/if implemented.
ANSISYSRC_CursorRestore = L'u', // NOTE: Overlaps with DECSMBV. Fix when/if implemented.
DECKPAM_KeypadApplicationMode = L'=',
DECKPNM_KeypadNumericMode = L'>',
DSR_DeviceStatusReport = L'n',
DA_DeviceAttributes = L'c',
DECSCPP_SetColumnsPerPage = L'|',
IL_InsertLine = L'L',
DL_DeleteLine = L'M', // Yes, this is the same as RI, however, RI is not preceeded by a CSI, and DL is.
VPA_VerticalLinePositionAbsolute = L'd',
DECSTBM_SetScrollingRegion = L'r',
RI_ReverseLineFeed = L'M',
HTS_HorizontalTabSet = L'H', // Not a CSI, so doesn't overlap with CUP
CHT_CursorForwardTab = L'I',
CBT_CursorBackTab = L'Z',
TBC_TabClear = L'g',
ECH_EraseCharacters = L'X',
HVP_HorizontalVerticalPosition = L'f',
DECSTR_SoftReset = L'p',
RIS_ResetToInitialState = L'c', // DA is prefaced by CSI, RIS by ESC
// 'q' is overloaded - no postfix is DECLL, ' ' postfix is DECSCUSR, and '"' is DECSCA
DECSCUSR_SetCursorStyle = L'q', // I believe we'll only ever implement DECSCUSR
DTTERM_WindowManipulation = L't',
REP_RepeatCharacter = L'b'
};
enum OscActionCodes : unsigned int
{
SetIconAndWindowTitle = 0,
SetWindowIcon = 1,
SetWindowTitle = 2,
SetWindowProperty = 3, // Not implemented
SetColor = 4,
SetForegroundColor = 10,
SetBackgroundColor = 11,
SetCursorColor = 12,
ResetForegroundColor = 110, // Not implemented
ResetBackgroundColor = 111, // Not implemented
ResetCursorColor = 112,
};
enum class DesignateCharsetTypes
{
G0,
G1,
G2,
G3
};
static const DispatchTypes::GraphicsOptions s_defaultGraphicsOption = DispatchTypes::GraphicsOptions::Off;
_Success_(return)
bool _GetGraphicsOptions(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_writes_(*pcOptions) DispatchTypes::GraphicsOptions* const rgGraphicsOptions,
_Inout_ size_t* const pcOptions) const;
static const DispatchTypes::EraseType s_defaultEraseType = DispatchTypes::EraseType::ToEnd;
_Success_(return)
bool _GetEraseOperation(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ DispatchTypes::EraseType* const pEraseType) const;
static const unsigned int s_uiDefaultCursorDistance = 1;
_Success_(return)
bool _GetCursorDistance(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiDistance) const;
static const unsigned int s_uiDefaultScrollDistance = 1;
_Success_(return)
bool _GetScrollDistance(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiDistance) const;
static const unsigned int s_uiDefaultConsoleWidth = 80;
_Success_(return)
bool _GetConsoleWidth(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiConsoleWidth) const;
static const unsigned int s_uiDefaultLine = 1;
static const unsigned int s_uiDefaultColumn = 1;
_Success_(return)
bool _GetXYPosition(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiLine,
_Out_ unsigned int* const puiColumn) const;
_Success_(return)
bool _GetDeviceStatusOperation(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ DispatchTypes::AnsiStatusType* const pStatusType) const;
_Success_(return)
bool _VerifyHasNoParameters(const unsigned short cParams) const;
_Success_(return)
bool _VerifyDeviceAttributesParams(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams) const;
_Success_(return)
bool _GetPrivateModeParams(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_writes_(*pcParams) DispatchTypes::PrivateModeParams* const rgPrivateModeParams,
_Inout_ size_t* const pcParams) const;
static const SHORT s_sDefaultTopMargin = 0;
static const SHORT s_sDefaultBottomMargin = 0;
_Success_(return)
bool _GetTopBottomMargins(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ SHORT* const psTopMargin,
_Out_ SHORT* const psBottomMargin) const;
_Success_(return)
bool _GetOscTitle(_Inout_updates_(cchOscString) wchar_t* const pwchOscStringBuffer,
const unsigned short cchOscString,
_Outptr_result_buffer_(*pcchTitle) wchar_t** const ppwchTitle,
_Out_ unsigned short * pcchTitle) const;
static const SHORT s_sDefaultTabDistance = 1;
_Success_(return)
bool _GetTabDistance(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ SHORT* const psDistance) const;
static const SHORT s_sDefaultTabClearType = 0;
_Success_(return)
bool _GetTabClearType(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ SHORT* const psClearType) const;
static const DesignateCharsetTypes s_DefaultDesignateCharsetType = DesignateCharsetTypes::G0;
_Success_(return)
bool _GetDesignateType(const wchar_t wchIntermediate,
_Out_ DesignateCharsetTypes* const pDesignateType) const;
static const DispatchTypes::WindowManipulationType s_DefaultWindowManipulationType = DispatchTypes::WindowManipulationType::Invalid;
_Success_(return)
bool _GetWindowManipulationType(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiFunction) const;
static bool s_HexToUint(const wchar_t wch,
_Out_ unsigned int * const puiValue);
static bool s_IsNumber(const wchar_t wch);
static bool s_IsHexNumber(const wchar_t wch);
bool _GetOscSetColorTable(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer,
const size_t cchOscString,
_Out_ size_t* const pTableIndex,
_Out_ DWORD* const pRgb) const;
static bool s_ParseColorSpec(_In_reads_(cchBuffer) const wchar_t* const pwchBuffer,
const size_t cchBuffer,
_Out_ DWORD* const pRgb);
bool _GetOscSetColor(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer,
const size_t cchOscString,
_Out_ DWORD* const pRgb) const;
static const DispatchTypes::CursorStyle s_defaultCursorStyle = DispatchTypes::CursorStyle::BlinkingBlockDefault;
_Success_(return)
bool _GetCursorStyle(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ DispatchTypes::CursorStyle* const pCursorStyle) const;
static const unsigned int s_uiDefaultRepeatCount = 1;
_Success_(return)
bool _GetRepeatCount(_In_reads_(cParams) const unsigned short* const rgusParams,
const unsigned short cParams,
_Out_ unsigned int* const puiRepeatCount) const noexcept;
void _ClearLastChar() noexcept;
};
}