64ac0d25e0
When we had to flush unknown sequences to the terminal, we were only taking the _most recent run_ with us; therefore, if we received `\e[?12` and `34h` in separate packets we would _only_ send out `34h`. This change fixes that issue by ensuring that we cache partial bits of sequences we haven't yet completed, just in case we need to flush them. Fixes #3080. Fixes #3081.
125 lines
3.8 KiB
C++
125 lines
3.8 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
/*
|
|
Module Name:
|
|
- stateMachine.hpp
|
|
|
|
Abstract:
|
|
- This declares the entire state machine for handling Virtual Terminal Sequences
|
|
- The design is based from the specifications at http://vt100.net
|
|
- The actual implementation of actions decoded by the StateMachine should be
|
|
implemented in an IStateMachineEngine.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "IStateMachineEngine.hpp"
|
|
#include "telemetry.hpp"
|
|
#include "tracing.hpp"
|
|
#include <memory>
|
|
|
|
namespace Microsoft::Console::VirtualTerminal
|
|
{
|
|
class StateMachine final
|
|
{
|
|
#ifdef UNIT_TESTING
|
|
friend class OutputEngineTest;
|
|
friend class InputEngineTest;
|
|
#endif
|
|
|
|
public:
|
|
StateMachine(std::unique_ptr<IStateMachineEngine> engine);
|
|
|
|
void ProcessCharacter(const wchar_t wch);
|
|
void ProcessString(const std::wstring_view string);
|
|
|
|
void ResetState() noexcept;
|
|
|
|
bool FlushToTerminal();
|
|
|
|
const IStateMachineEngine& Engine() const noexcept;
|
|
IStateMachineEngine& Engine() noexcept;
|
|
|
|
private:
|
|
void _ActionExecute(const wchar_t wch);
|
|
void _ActionExecuteFromEscape(const wchar_t wch);
|
|
void _ActionPrint(const wchar_t wch);
|
|
void _ActionEscDispatch(const wchar_t wch);
|
|
void _ActionCollect(const wchar_t wch);
|
|
void _ActionParam(const wchar_t wch);
|
|
void _ActionCsiDispatch(const wchar_t wch);
|
|
void _ActionOscParam(const wchar_t wch);
|
|
void _ActionOscPut(const wchar_t wch);
|
|
void _ActionOscDispatch(const wchar_t wch);
|
|
void _ActionSs3Dispatch(const wchar_t wch);
|
|
|
|
void _ActionClear();
|
|
void _ActionIgnore() noexcept;
|
|
|
|
void _EnterGround() noexcept;
|
|
void _EnterEscape();
|
|
void _EnterEscapeIntermediate() noexcept;
|
|
void _EnterCsiEntry();
|
|
void _EnterCsiParam() noexcept;
|
|
void _EnterCsiIgnore() noexcept;
|
|
void _EnterCsiIntermediate() noexcept;
|
|
void _EnterOscParam() noexcept;
|
|
void _EnterOscString() noexcept;
|
|
void _EnterOscTermination() noexcept;
|
|
void _EnterSs3Entry();
|
|
void _EnterSs3Param() noexcept;
|
|
|
|
void _EventGround(const wchar_t wch);
|
|
void _EventEscape(const wchar_t wch);
|
|
void _EventEscapeIntermediate(const wchar_t wch);
|
|
void _EventCsiEntry(const wchar_t wch);
|
|
void _EventCsiIntermediate(const wchar_t wch);
|
|
void _EventCsiIgnore(const wchar_t wch);
|
|
void _EventCsiParam(const wchar_t wch);
|
|
void _EventOscParam(const wchar_t wch);
|
|
void _EventOscString(const wchar_t wch);
|
|
void _EventOscTermination(const wchar_t wch);
|
|
void _EventSs3Entry(const wchar_t wch);
|
|
void _EventSs3Param(const wchar_t wch);
|
|
|
|
void _AccumulateTo(const wchar_t wch, size_t& value);
|
|
|
|
enum class VTStates
|
|
{
|
|
Ground,
|
|
Escape,
|
|
EscapeIntermediate,
|
|
CsiEntry,
|
|
CsiIntermediate,
|
|
CsiIgnore,
|
|
CsiParam,
|
|
OscParam,
|
|
OscString,
|
|
OscTermination,
|
|
Ss3Entry,
|
|
Ss3Param
|
|
};
|
|
|
|
Microsoft::Console::VirtualTerminal::ParserTracing _trace;
|
|
|
|
std::unique_ptr<IStateMachineEngine> _engine;
|
|
|
|
VTStates _state;
|
|
|
|
std::wstring_view _run;
|
|
|
|
std::vector<wchar_t> _intermediates;
|
|
std::vector<size_t> _parameters;
|
|
|
|
std::wstring _oscString;
|
|
size_t _oscParameter;
|
|
|
|
std::optional<std::wstring> _cachedSequence;
|
|
|
|
// This is tracked per state machine instance so that separate calls to Process*
|
|
// can start and finish a sequence.
|
|
bool _processingIndividually;
|
|
};
|
|
}
|