2559ed6efa
This PR introduces a mechanism via which DCS data strings can be passed through directly to the dispatch method that will be handling them, so the data can be processed as it is received, rather than being buffered in the state machine. This also simplifies the way string termination is handled, so it now more closely matches the behaviour of the original DEC terminals. * Initial support for DCS sequences was introduced in PR #6328. * Handling of DCS (and other) C1 controls was added in PR #7340. * This is a prerequisite for Sixel (#448) and Soft Font (#9164) support. The way this now works, a `DCS` sequence is dispatched as soon as the final character of the `VTID` is received. Based on that ID, the `OutputStateMachineEngine` should forward the call to the corresponding dispatch method, and its the responsibility of that method to return an appropriate handler function for the sequence. From then on, the `StateMachine` will pass on all of the remaining bytes in the data string to the handler function. When a data string is terminated (with `CAN`, `SUB`, or `ESC`), the `StateMachine` will pass on one final `ESC` character to let the handler know that the sequence is finished. The handler can also end a sequence prematurely by returning false, and then all remaining data bytes will be ignored. Note that once a `DCS` sequence has been dispatched, it's not possible to abort the data string. Both `CAN` and `SUB` are considered valid forms of termination, and an `ESC` doesn't necessarily have to be followed by a `\` for the string terminator. This is because the data string is typically processed as it's received. For example, when outputting a Sixel image, you wouldn't erase the parts that had already been displayed if the data string is terminated early. With this new way of handling the string termination, I was also able to simplify some of the `StateMachine` processing, and get rid of a few states that are no longer necessary. These changes don't apply to the `OSC` sequences, though, since we're more likely to want to match the XTerm behavior for those cases (which requires a valid `ST` control for the sequence to be accepted). ## Validation Steps Performed For the unit tests, I've had to make a few changes to some of the `OutputEngineTests` to account for the updated `StateMachine` processing. I've also added a new `StateMachineTest` to confirm that the data strings are correctly passed through to the string handler under all forms of termination. To test whether the framework is actually usable, I've been working on DRCS Soft Font support branched off of this PR, and haven't encountered any problems. To test the throughput speed, I also hacked together a basic Sixel parser, and that seemed to perform reasonably well. Closes #7316
64 lines
2.4 KiB
C++
64 lines
2.4 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT license.
|
|
|
|
/*
|
|
Module Name:
|
|
- IStateMachineEngine.hpp
|
|
|
|
Abstract:
|
|
- This is the interface for a VT state machine language
|
|
The terminal handles input sequences and output sequences differently,
|
|
almost as two separate grammars. This enables different grammars to leverage
|
|
the existing VT parsing.
|
|
*/
|
|
#pragma once
|
|
|
|
#include "../adapter/DispatchTypes.hpp"
|
|
|
|
namespace Microsoft::Console::VirtualTerminal
|
|
{
|
|
class IStateMachineEngine
|
|
{
|
|
public:
|
|
using StringHandler = std::function<bool(const wchar_t)>;
|
|
|
|
virtual ~IStateMachineEngine() = 0;
|
|
IStateMachineEngine(const IStateMachineEngine&) = default;
|
|
IStateMachineEngine(IStateMachineEngine&&) = default;
|
|
IStateMachineEngine& operator=(const IStateMachineEngine&) = default;
|
|
IStateMachineEngine& operator=(IStateMachineEngine&&) = default;
|
|
|
|
virtual bool ActionExecute(const wchar_t wch) = 0;
|
|
virtual bool ActionExecuteFromEscape(const wchar_t wch) = 0;
|
|
virtual bool ActionPrint(const wchar_t wch) = 0;
|
|
virtual bool ActionPrintString(const std::wstring_view string) = 0;
|
|
|
|
virtual bool ActionPassThroughString(const std::wstring_view string) = 0;
|
|
|
|
virtual bool ActionEscDispatch(const VTID id) = 0;
|
|
virtual bool ActionVt52EscDispatch(const VTID id, const VTParameters parameters) = 0;
|
|
virtual bool ActionCsiDispatch(const VTID id, const VTParameters parameters) = 0;
|
|
virtual StringHandler ActionDcsDispatch(const VTID id, const VTParameters parameters) = 0;
|
|
|
|
virtual bool ActionClear() = 0;
|
|
|
|
virtual bool ActionIgnore() = 0;
|
|
|
|
virtual bool ActionOscDispatch(const wchar_t wch,
|
|
const size_t parameter,
|
|
const std::wstring_view string) = 0;
|
|
|
|
virtual bool ActionSs3Dispatch(const wchar_t wch, const VTParameters parameters) = 0;
|
|
|
|
virtual bool ParseControlSequenceAfterSs3() const = 0;
|
|
virtual bool FlushAtEndOfString() const = 0;
|
|
virtual bool DispatchControlCharsFromEscape() const = 0;
|
|
virtual bool DispatchIntermediatesFromEscape() const = 0;
|
|
|
|
protected:
|
|
IStateMachineEngine() = default;
|
|
};
|
|
|
|
inline IStateMachineEngine::~IStateMachineEngine() {}
|
|
}
|