efd69990c6
* 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
279 lines
13 KiB
C++
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;
|
|
|
|
};
|
|
}
|