2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "../../terminal/adapter/termDispatch.hpp"
|
|
|
|
#include "ITerminalApi.hpp"
|
|
|
|
|
|
|
|
class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatch
|
|
|
|
{
|
|
|
|
public:
|
2020-01-03 19:44:27 +01:00
|
|
|
TerminalDispatch(::Microsoft::Terminal::Core::ITerminalApi& terminalApi) noexcept;
|
|
|
|
|
|
|
|
void Execute(const wchar_t wchControl) noexcept override;
|
|
|
|
void Print(const wchar_t wchPrintable) noexcept override;
|
|
|
|
void PrintString(const std::wstring_view string) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-01-03 15:25:21 +01:00
|
|
|
bool SetGraphicsRendition(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions> options) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-01-03 19:44:27 +01:00
|
|
|
bool CursorPosition(const size_t line,
|
|
|
|
const size_t column) noexcept override; // CUP
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-03-13 18:39:42 +01:00
|
|
|
bool CursorVisibility(const bool isVisible) noexcept override; // DECTCEM
|
|
|
|
bool EnableCursorBlinking(const bool enable) noexcept override; // ATT610
|
|
|
|
|
2020-01-03 15:25:21 +01:00
|
|
|
bool CursorForward(const size_t distance) noexcept override;
|
|
|
|
bool CursorBackward(const size_t distance) noexcept override;
|
|
|
|
bool CursorUp(const size_t distance) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
Add support for all the line feed control sequences (#3271)
## Summary of the Pull Request
This adds support for the `FF` (form feed) and `VT` (vertical tab) [control characters](https://vt100.net/docs/vt510-rm/chapter4.html#T4-1), as well as the [`NEL` (Next Line)](https://vt100.net/docs/vt510-rm/NEL.html) and [`IND` (Index)](https://vt100.net/docs/vt510-rm/IND.html) escape sequences.
## References
#976 discusses the conflict between VT100 Index sequence and the VT52 cursor back sequence.
## PR Checklist
* [x] Closes #3189
* [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
* [x] 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: #3189
## Detailed Description of the Pull Request / Additional comments
I've added a `LineFeed` method to the `ITermDispatch` interface, with an enum parameter specifying the required line feed type (i.e. with carriage return, without carriage return, or dependent on the [`LNM` mode](https://vt100.net/docs/vt510-rm/LNM.html)). The output state machine can then call that method to handle the various line feed control characters (parsed in the `ActionExecute` method), as well the `NEL` and `IND` escape sequences (parsed in the `ActionEscDispatch` method).
The `AdaptDispatch` implementation of `LineFeed` then forwards the call to a new `PrivateLineFeed` method in the `ConGetSet` interface, which simply takes a bool parameter specifying whether a carriage return is required or not. In the case of mode-dependent line feeds, the `AdaptDispatch` implementation determines whether the return is necessary or not, based on the existing _AutoReturnOnNewLine_ setting (which I'm obtaining via another new `PrivateGetLineFeedMode` method).
Ultimately we'll want to support changing the mode via the [`LNM` escape sequence](https://vt100.net/docs/vt510-rm/LNM.html), but there's no urgent need for that now. And using the existing _AutoReturnOnNewLine_ setting as a substitute for the mode gives us backwards compatible behaviour, since that will be true for the Windows shells (which expect a linefeed to also generate a carriage return), and false in a WSL bash shell (which won't want the carriage return by default).
As for the actual `PrivateLineFeed` implementation, that is just a simplified version of how the line feed would previously have been executed in the `WriteCharsLegacy` function. This includes setting the cursor to "On" (with `Cursor::SetIsOn`), potentially clearing the wrap property of the line being left (with `CharRow::SetWrapForced` false), and then setting the new position using `AdjustCursorPosition` with the _fKeepCursorVisible_ parameter set to false.
I'm unsure whether the `SetIsOn` call is really necessary, and I think the way the forced wrap is handled needs a rethink in general, but for now this should at least be compatible with the existing behaviour.
Finally, in order to make this all work in the _Windows Terminal_ app, I also had to add a basic implementation of the `ITermDispatch::LineFeed` method in the `TerminalDispatch` class. There is currently no need to support mode-specific line feeds here, so this simply forwards a `\n` or `\r\n` to the `Execute` method, which is ultimately handled by the `Terminal::_WriteBuffer` implementation.
## Validation Steps Performed
I've added output engine tests which confirm that the various control characters and escape sequences trigger the dispatch method correctly. Then I've added adapter tests which confirm the various dispatch options trigger the `PrivateLineFeed` API correctly. And finally I added some screen buffer tests that check the actual results of the `NEL` and `IND` sequences, which covers both forms of the `PrivateLineFeed` API (i.e. with and without a carriage return).
I've also run the _Test of cursor movements_ in the [Vttest](https://invisible-island.net/vttest/) utility, and confirmed that screens 1, 2, and 5 are now working correctly. The first two depend on `NEL` and `IND` being supported, and screen 5 requires the `VT` control character.
2020-01-15 14:41:55 +01:00
|
|
|
bool LineFeed(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::LineFeedType lineFeedType) noexcept override;
|
|
|
|
|
2020-01-03 15:25:21 +01:00
|
|
|
bool EraseCharacters(const size_t numChars) noexcept override;
|
Dispatch more C0 control characters from the VT state machine (#4171)
This commit moves the handling of the `BEL`, `BS`, `TAB`, and `CR`
controls characters into the state machine (when in VT mode), instead of
forwarding them on to the default string writer, which would otherwise
have to parse them out all over again.
This doesn't cover all the control characters, but `ESC`, `SUB`, and
`CAN` are already an integral part of the `StateMachine` itself; `NUL`
is filtered out by the `OutputStateMachineEngine`; and `LF`, `FF`, and
`VT` are due to be implemented as part of PR #3271.
Once all of these controls are handled at the state machine level, we
can strip out all the VT-specific code from the `WriteCharsLegacy`
function, which should simplify it considerably. This would also let us
simplify the `Terminal::_WriteBuffer` implementation, and the planned
replacement stream writer for issue #780.
On the conhost side, the implementation is handled as follows:
* The `BS` control is dispatched to the existing `CursorBackward`
method, with a distance of 1.
* The `TAB` control is dispatched to the existing `ForwardTab` method,
with a tab count of 1.
* The `CR` control required a new dispatch method, but the
implementation was a simple call to the new `_CursorMovePosition` method
from PR #3628.
* The `BEL` control also required a new dispatch method, as well as an
additional private API in the `ConGetSet` interface. But that's mostly
boilerplate code - ultimately it just calls the `SendNotifyBeep` method.
On the Windows Terminal side, not all dispatch methods are implemented.
* There is an existing `CursorBackward` implementation, so `BS` works
OK.
* There isn't a `ForwardTab` implementation, but `TAB` isn't currently
required by the conpty protocol.
* I had to implement the `CarriageReturn` dispatch method, but that was
a simple call to `Terminal::SetCursorPosition`.
* The `WarningBell` method I've left unimplemented, because that
functionality wasn't previously supported anyway, and there's an
existing issue for that (#4046).
## Validation Steps Performed
I've added a state machine test to confirm that the updated control
characters are now forwarded to the appropriate dispatch handlers. But
since the actual implementation is mostly relying on existing
functionality, I'm assuming that code is already adequately tested
elsewhere. That said, I have also run various manual tests of my own,
and confirmed that everything still worked as well as before.
References #3271
References #780
References #3628
References #4046
2020-01-17 02:43:21 +01:00
|
|
|
bool CarriageReturn() noexcept override;
|
2020-01-03 15:25:21 +01:00
|
|
|
bool SetWindowTitle(std::wstring_view title) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-01-03 15:25:21 +01:00
|
|
|
bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept override;
|
|
|
|
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-01-03 15:25:21 +01:00
|
|
|
bool SetDefaultForeground(const DWORD color) noexcept override;
|
|
|
|
bool SetDefaultBackground(const DWORD color) noexcept override;
|
|
|
|
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override; // ED
|
|
|
|
bool DeleteCharacter(const size_t count) noexcept override;
|
|
|
|
bool InsertCharacter(const size_t count) noexcept override;
|
|
|
|
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
|
2019-05-24 18:53:00 +02:00
|
|
|
|
2020-03-13 01:44:28 +01:00
|
|
|
bool SetCursorKeysMode(const bool applicationMode) noexcept override; // DECCKM
|
|
|
|
bool SetKeypadMode(const bool applicationMode) noexcept override; // DECKPAM, DECKPNM
|
|
|
|
|
2020-03-16 16:32:01 +01:00
|
|
|
bool SoftReset() noexcept override; // DECSTR
|
|
|
|
bool HardReset() noexcept override; // RIS
|
|
|
|
|
2020-03-13 01:44:28 +01:00
|
|
|
bool EnableVT200MouseMode(const bool enabled) noexcept override; // ?1000
|
|
|
|
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override; // ?1005
|
|
|
|
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override; // ?1006
|
|
|
|
bool EnableButtonEventMouseMode(const bool enabled) noexcept override; // ?1002
|
|
|
|
bool EnableAnyEventMouseMode(const bool enabled) noexcept override; // ?1003
|
|
|
|
bool EnableAlternateScroll(const bool enabled) noexcept override; // ?1007
|
|
|
|
|
|
|
|
bool SetPrivateModes(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::PrivateModeParams> /*params*/) noexcept override; // DECSET
|
|
|
|
bool ResetPrivateModes(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::PrivateModeParams> /*params*/) noexcept override; // DECRST
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
private:
|
|
|
|
::Microsoft::Terminal::Core::ITerminalApi& _terminalApi;
|
|
|
|
|
2019-12-19 23:12:53 +01:00
|
|
|
bool _SetRgbColorsHelper(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions> options,
|
2020-01-03 19:44:27 +01:00
|
|
|
size_t& optionsConsumed) noexcept;
|
|
|
|
bool _SetBoldColorHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions opt) noexcept;
|
|
|
|
bool _SetDefaultColorHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions opt) noexcept;
|
|
|
|
void _SetGraphicsOptionHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions opt) noexcept;
|
2020-03-13 01:44:28 +01:00
|
|
|
|
|
|
|
bool _SetResetPrivateModes(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::PrivateModeParams> params, const bool enable) noexcept;
|
|
|
|
bool _PrivateModeParamsHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::PrivateModeParams param, const bool enable) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
};
|