terminal/src/terminal/adapter/termDispatch.hpp

138 lines
9.8 KiB
C++
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/*
Module Name:
- termDispatch.hpp
Abstract:
- This is a useful default implementation of all of the ITermDispatch callbacks.
Fails on every callback, but handy for tests.
*/
#include "ITermDispatch.hpp"
#pragma once
namespace Microsoft::Console::VirtualTerminal
{
class TermDispatch;
};
class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Console::VirtualTerminal::ITermDispatch
{
public:
void Execute(const wchar_t wchControl) override = 0;
void Print(const wchar_t wchPrintable) override = 0;
void PrintString(const std::wstring_view string) override = 0;
bool CursorUp(const size_t /*distance*/) noexcept override { return false; } // CUU
bool CursorDown(const size_t /*distance*/) noexcept override { return false; } // CUD
bool CursorForward(const size_t /*distance*/) noexcept override { return false; } // CUF
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool CursorBackward(const size_t /*distance*/) noexcept override { return false; } // CUB, BS
bool CursorNextLine(const size_t /*distance*/) noexcept override { return false; } // CNL
bool CursorPrevLine(const size_t /*distance*/) noexcept override { return false; } // CPL
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool CursorHorizontalPositionAbsolute(const size_t /*column*/) noexcept override { return false; } // HPA, CHA
bool VerticalLinePositionAbsolute(const size_t /*line*/) noexcept override { return false; } // VPA
Add support for the HPR and VPR escape sequences (#4297) ## Summary of the Pull Request This PR adds support for the `HPR` and `VPR` escape sequences from the VT510 terminal. `HPR` moves the cursor position forward by a given number of columns, and `VPR` moves the cursor position downward by a given number of rows. They're similar in function to the `CUF` and `CUD` escape sequences, except that they're not constrained by the scrolling margins. ## References #3628 provided the new `_CursorMovePosition` method that made these operations possible ## PR Checklist * [x] Closes #3428 * [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 * [ ] 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: #xxx ## Detailed Description of the Pull Request / Additional comments Most of the implementation is in the new `_CursorMovePosition` method that was created in PR #3628, so all we're really doing here is hooking up the escape sequences to call that method with the appropriate parameters. ## Validation Steps Performed I've extended the existing state machine tests for CSI cursor movement to confirm that the `HPR` and `VPR` sequences are dispatched correctly, and also added screen buffer tests to make sure the movement is clamped by the screen boundaries and not the scrolling margins (we don't yet support horizontal margins, but the test is at least in place for when we do eventually add that support). I've also checked the `HPR` and `VPR` tests in Vttest (under _Test non-VT100 / ISO-6429 cursor-movement_) and confirmed that they are now working as expected.
2020-01-21 23:39:15 +01:00
bool HorizontalPositionRelative(const size_t /*distance*/) noexcept override { return false; } // HPR
bool VerticalPositionRelative(const size_t /*distance*/) noexcept override { return false; } // VPR
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool CursorPosition(const size_t /*line*/, const size_t /*column*/) noexcept override { return false; } // CUP, HVP
bool CursorSaveState() noexcept override { return false; } // DECSC
bool CursorRestoreState() noexcept override { return false; } // DECRC
bool CursorVisibility(const bool /*isVisible*/) noexcept override { return false; } // DECTCEM
bool InsertCharacter(const size_t /*count*/) noexcept override { return false; } // ICH
bool DeleteCharacter(const size_t /*count*/) noexcept override { return false; } // DCH
bool ScrollUp(const size_t /*distance*/) noexcept override { return false; } // SU
bool ScrollDown(const size_t /*distance*/) noexcept override { return false; } // SD
bool InsertLine(const size_t /*distance*/) noexcept override { return false; } // IL
bool DeleteLine(const size_t /*distance*/) noexcept override { return false; } // DL
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool SetColumns(const size_t /*columns*/) noexcept override { return false; } // DECCOLM
bool SetCursorKeysMode(const bool /*applicationMode*/) noexcept override { return false; } // DECCKM
bool SetKeypadMode(const bool /*applicationMode*/) noexcept override { return false; } // DECKPAM, DECKPNM
bool EnableWin32InputMode(const bool /*win32InputMode*/) noexcept override { return false; } // win32-input-mode
bool EnableCursorBlinking(const bool /*enable*/) noexcept override { return false; } // ATT610
Add support for VT52 emulation (#4789) ## Summary of the Pull Request This PR adds support for the core VT52 commands, and implements the `DECANM` private mode sequence, which switches the terminal between ANSI mode and VT52-compatible mode. ## References PR #2017 defined the initial specification for VT52 support. PR #4044 removed the original VT52 cursor ops that conflicted with VT100 sequences. ## PR Checklist * [x] Closes #976 * [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: #2017 ## Detailed Description of the Pull Request / Additional comments Most of the work involves updates to the parsing state machine, which behaves differently in VT52 mode. `CSI`, `OSC`, and `SS3` sequences are not applicable, and there is one special-case escape sequence (_Direct Cursor Address_), which requires an additional state to handle parameters that come _after_ the final character. Once the parsing is handled though, it's mostly just a matter of dispatching the commands to existing methods in the `ITermDispatch` interface. Only one new method was required in the interface to handle the _Identify_ command. The only real new functionality is in the `TerminalInput` class, which needs to generate different escape sequences for certain keys in VT52 mode. This does not yet support _all_ of the VT52 key sequences, because the VT100 support is itself not yet complete. But the basics are in place, and I think the rest is best left for a follow-up issue, and potentially a refactor of the `TerminalInput` class. I should point out that the original spec called for a new _Graphic Mode_ character set, but I've since discovered that the VT terminals that _emulate_ VT52 just use the existing VT100 _Special Graphics_ set, so that is really what we should be doing too. We can always consider adding the VT52 graphic set as a option later, if there is demand for strict VT52 compatibility. ## Validation Steps Performed I've added state machine and adapter tests to confirm that the `DECANM` mode changing sequences are correctly dispatched and forwarded to the `ConGetSet` handler. I've also added state machine tests that confirm the VT52 escape sequences are dispatched correctly when the ANSI mode is reset. For fuzzing support, I've extended the VT command fuzzer to generate the different kinds of VT52 sequences, as well as mode change sequences to switch between the ANSI and VT52 modes. In terms of manual testing, I've confirmed that the _Test of VT52 mode_ in Vttest now works as expected.
2020-06-01 23:20:40 +02:00
bool SetAnsiMode(const bool /*ansiMode*/) noexcept override { return false; } // DECANM
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool SetScreenMode(const bool /*reverseMode*/) noexcept override { return false; } // DECSCNM
bool SetOriginMode(const bool /*relativeMode*/) noexcept override { return false; }; // DECOM
Add support for VT100 Auto Wrap Mode (DECAWM) (#3943) ## Summary of the Pull Request This adds support for the [`DECAWM`](https://vt100.net/docs/vt510-rm/DECAWM) private mode escape sequence, which controls whether or not the output wraps to the next line when the cursor reaches the right edge of the screen. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests. ## PR Checklist * [x] Closes #3826 * [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: #3826 ## Detailed Description of the Pull Request / Additional comments The idea was to repurpose the existing `ENABLE_WRAP_AT_EOL_OUTPUT` mode, but the problem with that was it didn't work in VT mode - specifically, disabling it didn't prevent the wrapping from happening. This was because in VT mode the `WC_DELAY_EOL_WRAP` behaviour takes affect, and that bypasses the usual codepath where `ENABLE_WRAP_AT_EOL_OUTPUT` is checked, To fix this, I had to add additional checks in the `WriteCharsLegacy` function (7dbefe06e41f191a0e83cfefe4896b66094c4089) to make sure the `WC_DELAY_EOL_WRAP` mode is only activated when `ENABLE_WRAP_AT_EOL_OUTPUT` is also set. Once that was fixed, though, another issue came to light: the `ENABLE_WRAP_AT_EOL_OUTPUT` mode doesn't actually work as documented. According to the docs, "if this mode is disabled, the last character in the row is overwritten with any subsequent characters". What actually happens is the cursor jumps back to the position at the start of the write, which could be anywhere on the line. This seems completely broken to me, but I've checked in the Windows XP, and it has the same behaviour, so it looks like that's the way it has always been. So I've added a fix for this (9df98497ca38f7d0ea42623b723a8e2ecf9a4ab9), but it is only applied in VT mode. Once that basic functionality was in place, though, we just needed a private API in the `ConGetSet` interface to toggle the mode, and then that API could be called from the `AdaptDispatch` class when the `DECAWM` escape sequence was received. One last thing was to reenable the mode in reponse to a `DECSTR` soft reset. Technically the auto wrap mode was disabled by default on many of the DEC terminals, and some documentation suggests that `DECSTR` should reset it to that state, But most modern terminals (including XTerm) expect the wrapping to be enabled by default, and `DECSTR` reenables that state, so that's the behaviour I've copied. ## Validation Steps Performed I've add a state machine test to confirm the `DECAWM` escape is dispatched correctly, and a screen buffer test to make sure the output is wrapped or clamped as appropriate for the two states. I've also confirmed that the "wrap around" test is now working correctly in the _Test of screen features_ in Vttest.
2020-02-04 01:20:21 +01:00
bool SetAutoWrapMode(const bool /*wrapAtEOL*/) noexcept override { return false; }; // DECAWM
bool SetTopBottomScrollingMargins(const size_t /*topMargin*/, const size_t /*bottomMargin*/) noexcept override { return false; } // DECSTBM
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 WarningBell() noexcept override { return false; } // BEL
bool CarriageReturn() noexcept override { return false; } // CR
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool LineFeed(const DispatchTypes::LineFeedType /*lineFeedType*/) noexcept override { return false; } // IND, NEL, LF, FF, VT
bool ReverseLineFeed() noexcept override { return false; } // RI
bool SetWindowTitle(std::wstring_view /*title*/) noexcept override { return false; } // OscWindowTitle
bool UseAlternateScreenBuffer() noexcept override { return false; } // ASBSET
bool UseMainScreenBuffer() noexcept override { return false; } // ASBRST
bool HorizontalTabSet() noexcept override { return false; } // HTS
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool ForwardTab(const size_t /*numTabs*/) noexcept override { return false; } // CHT, HT
bool BackwardsTab(const size_t /*numTabs*/) noexcept override { return false; } // CBT
Refactor VT parameter handling (#7799) This PR introduces a pair of classes for managing VT parameters that automatically handle range checking and default fallback values, so the individual operations don't have to do that validation themselves. In addition to simplifying the code, this fixes a few cases where we were mishandling missing or extraneous parameters, and adds support for parameter sequences on commands that couldn't previously handle them. This PR also sets a limit on the number of parameters allowed, to help thwart DoS memory consumption attacks. ## References * The new parameter class also introduces the concept of an omitted/default parameter which is not necessarily zero, which is a prerequisite for addressing issue #4417. ## Detailed Description of the Pull Request / Additional comments There are two new classes provide by this PR: a `VTParameter` class, similar in function to a `std::optional<size_t>`, which holds an individual parameter (which may be an omitted/default value); and a `VTParameters` class, similar in function to `gsl:span<VTParameter>`, which holds a sequence of those parameters. Where `VTParameter` differs from `std::optional` is with the inclusion of two cast operators. There is a `size_t` cast that interprets omitted and zero values as 1 (the expected behaviour for most numeric parameters). And there is a generic cast, for use with the enum parameter types, which interprets omitted values as 0 (the expected behaviour for most selective parameters). The advantage of `VTParameters` class is that it has an `at` method that can never fail - out of range values simply return the a default `VTParameter` instance (this is standard behaviour in VT terminals). It also has a `size` method that will always return a minimum count of 1, since an empty parameter list is typically the equivalent of a single "default" parameter, so this guarantees you'll get at least one value when iterating over the list with `size()`. For cases where we just need to call the same dispatch method for every parameter, there is a helper `for_each` method, which repeatedly calls a given predicate function with each value in the sequence. It also collates the returned success values to determine the overall result of the sequence. As with the `size` method, this will always make at least one call, so it correctly handles empty sequences. With those two classes in place, we could get rid of all the parameter validation and default handling code in the `OutputStateMachineEngine`. We now just use the `VTParameters::at` method to grab a parameter and typically pass it straight to the appropriate dispatch method, letting the cast operators automatically handle the assignment of default values. Occasionally we might need a `value_or` call to specify a non-standard default value, but those cases are fairly rare. In some case the `OutputStateMachineEngine` was also checking whether parameters values were in range, but for the most part this shouldn't have been necessary, since that is something the dispatch classes would already have been doing themselves (in the few cases that they weren't, I've now updated them to do so). I've also updated the `InputStateMachineEngine` in a similar way to the `OutputStateMachineEngine`, getting rid of a few of the parameter extraction methods, and simplifying other parts of the implementation. It's not as clean a replacement as the output engine, but there are still benefits in using the new classes. ## Validation Steps Performed For the most part I haven't had to alter existing tests other than accounting for changes to the API. There were a couple of tests I needed to drop because they were checking for failure cases which shouldn't have been failing (unexpected parameters should never be an error), or testing output engine validation that is no longer handled at that level. I've added a few new tests to cover operations that take sequences of selective parameters (`ED`, `EL`, `TBC`, `SM`, and `RM`). And I've extended the cursor movement tests to make sure those operations can handle extraneous parameters that weren't expected. I've also added a test to verify that the state machine will correctly ignore parameters beyond the maximum 32 parameter count limit. I've also manual confirmed that the various test cases given in issues #2101 are now working as expected. Closes #2101
2020-10-15 18:12:52 +02:00
bool TabClear(const DispatchTypes::TabClearType /*clearType*/) noexcept override { return false; } // TBC
bool EnableDECCOLMSupport(const bool /*enabled*/) noexcept override { return false; } // ?40
bool EnableVT200MouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1000
bool EnableUTF8ExtendedMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1005
bool EnableSGRExtendedMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1006
bool EnableButtonEventMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1002
bool EnableAnyEventMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1003
bool EnableAlternateScroll(const bool /*enabled*/) noexcept override { return false; } // ?1007
bool EnableXtermBracketedPasteMode(const bool /*enabled*/) noexcept override { return false; } // ?2004
bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*color*/) noexcept override { return false; } // OSCColorTable
bool SetDefaultForeground(const DWORD /*color*/) noexcept override { return false; } // OSCDefaultForeground
bool SetDefaultBackground(const DWORD /*color*/) noexcept override { return false; } // OSCDefaultBackground
bool EraseInDisplay(const DispatchTypes::EraseType /* eraseType*/) noexcept override { return false; } // ED
bool EraseInLine(const DispatchTypes::EraseType /* eraseType*/) noexcept override { return false; } // EL
bool EraseCharacters(const size_t /*numChars*/) noexcept override { return false; } // ECH
Refactor VT parameter handling (#7799) This PR introduces a pair of classes for managing VT parameters that automatically handle range checking and default fallback values, so the individual operations don't have to do that validation themselves. In addition to simplifying the code, this fixes a few cases where we were mishandling missing or extraneous parameters, and adds support for parameter sequences on commands that couldn't previously handle them. This PR also sets a limit on the number of parameters allowed, to help thwart DoS memory consumption attacks. ## References * The new parameter class also introduces the concept of an omitted/default parameter which is not necessarily zero, which is a prerequisite for addressing issue #4417. ## Detailed Description of the Pull Request / Additional comments There are two new classes provide by this PR: a `VTParameter` class, similar in function to a `std::optional<size_t>`, which holds an individual parameter (which may be an omitted/default value); and a `VTParameters` class, similar in function to `gsl:span<VTParameter>`, which holds a sequence of those parameters. Where `VTParameter` differs from `std::optional` is with the inclusion of two cast operators. There is a `size_t` cast that interprets omitted and zero values as 1 (the expected behaviour for most numeric parameters). And there is a generic cast, for use with the enum parameter types, which interprets omitted values as 0 (the expected behaviour for most selective parameters). The advantage of `VTParameters` class is that it has an `at` method that can never fail - out of range values simply return the a default `VTParameter` instance (this is standard behaviour in VT terminals). It also has a `size` method that will always return a minimum count of 1, since an empty parameter list is typically the equivalent of a single "default" parameter, so this guarantees you'll get at least one value when iterating over the list with `size()`. For cases where we just need to call the same dispatch method for every parameter, there is a helper `for_each` method, which repeatedly calls a given predicate function with each value in the sequence. It also collates the returned success values to determine the overall result of the sequence. As with the `size` method, this will always make at least one call, so it correctly handles empty sequences. With those two classes in place, we could get rid of all the parameter validation and default handling code in the `OutputStateMachineEngine`. We now just use the `VTParameters::at` method to grab a parameter and typically pass it straight to the appropriate dispatch method, letting the cast operators automatically handle the assignment of default values. Occasionally we might need a `value_or` call to specify a non-standard default value, but those cases are fairly rare. In some case the `OutputStateMachineEngine` was also checking whether parameters values were in range, but for the most part this shouldn't have been necessary, since that is something the dispatch classes would already have been doing themselves (in the few cases that they weren't, I've now updated them to do so). I've also updated the `InputStateMachineEngine` in a similar way to the `OutputStateMachineEngine`, getting rid of a few of the parameter extraction methods, and simplifying other parts of the implementation. It's not as clean a replacement as the output engine, but there are still benefits in using the new classes. ## Validation Steps Performed For the most part I haven't had to alter existing tests other than accounting for changes to the API. There were a couple of tests I needed to drop because they were checking for failure cases which shouldn't have been failing (unexpected parameters should never be an error), or testing output engine validation that is no longer handled at that level. I've added a few new tests to cover operations that take sequences of selective parameters (`ED`, `EL`, `TBC`, `SM`, and `RM`). And I've extended the cursor movement tests to make sure those operations can handle extraneous parameters that weren't expected. I've also added a test to verify that the state machine will correctly ignore parameters beyond the maximum 32 parameter count limit. I've also manual confirmed that the various test cases given in issues #2101 are now working as expected. Closes #2101
2020-10-15 18:12:52 +02:00
bool SetGraphicsRendition(const VTParameters /*options*/) noexcept override { return false; } // SGR
Add support for double-width/double-height lines in conhost (#8664) This PR adds support for the VT line rendition attributes, which allow for double-width and double-height line renditions. These renditions are enabled with the `DECDWL` (double-width line) and `DECDHL` (double-height line) escape sequences. Both reset to the default rendition with the `DECSWL` (single-width line) escape sequence. For now this functionality is only supported by the GDI renderer in conhost. There are a lot of changes, so this is just a general overview of the main areas affected. Previously it was safe to assume that the screen had a fixed width, at least for a given point in time. But now we need to deal with the possibility of different lines have different widths, so all the functions that are constrained by the right border (text wrapping, cursor movement operations, and sequences like `EL` and `ICH`) now need to lookup the width of the active line in order to behave correctly. Similarly it used to be safe to assume that buffer and screen coordinates were the same thing, but that is no longer true. Lots of places now need to translate back and forth between coordinate systems dependent on the line rendition. This includes clipboard handling, the conhost color selection and search, accessibility location tracking and screen reading, IME editor positioning, "snapping" the viewport, and of course all the rendering calculations. For the rendering itself, I've had to introduce a new `PrepareLineTransform` method that the render engines can use to setup the necessary transform matrix for a given line rendition. This is also now used to handle the horizontal viewport offset, since that could no longer be achieved just by changing the target coordinates (on a double width line, the viewport offset may be halfway through a character). I've also had to change the renderer's existing `InvalidateCursor` method to take a `SMALL_RECT` rather than a `COORD`, to allow for the cursor being a variable width. Technically this was already a problem, because the cursor could occupy two screen cells when over a double-width character, but now it can be anything between one and four screen cells (e.g. a double-width character on the double-width line). In terms of architectural changes, there is now a new `lineRendition` field in the `ROW` class that keeps track of the line rendition for each row, and several new methods in the `ROW` and `TextBuffer` classes for manipulating that state. This includes a few helper methods for handling the various issues discussed above, e.g. position clamping and translating between coordinate systems. ## Validation Steps Performed I've manually confirmed all the double-width and double-height tests in _Vttest_ are now working as expected, and the _VT100 Torture Test_ now renders correctly (at least the line rendition aspects). I've also got my own test scripts that check many of the line rendition boundary cases and have confirmed that those are now passing. I've manually tested as many areas of the conhost UI that I could think of, that might be affected by line rendition, including things like searching, selection, copying, and color highlighting. For accessibility, I've confirmed that the _Magnifier_ and _Narrator_ correctly handle double-width lines. And I've also tested the Japanese IME, which while not perfect, is at least useable. Closes #7865
2021-02-18 06:44:50 +01:00
bool SetLineRendition(const LineRendition /*rendition*/) noexcept override { return false; } // DECSWL, DECDWL, DECDHL
bool PushGraphicsRendition(const VTParameters /*options*/) noexcept override { return false; } // XTPUSHSGR
bool PopGraphicsRendition() noexcept override { return false; } // XTPOPSGR
bool SetMode(const DispatchTypes::ModeParams /*param*/) noexcept override { return false; } // DECSET
bool ResetMode(const DispatchTypes::ModeParams /*param*/) noexcept override { return false; } // DECRST
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) noexcept override { return false; } // DSR, DSR-OS, DSR-CPR
Update comments in the ITermDispatch interface to better indicate the VT commands that are supported. (#4752) ## Summary of the Pull Request Most of the methods in the `ITermDispatch` interface have a comment following them that indicates the VT function that they implement. These comments are then used by the script in PR #1884 to generate a table of supported VT functions. This PR updates some of those comments, to more accurately reflect the functions that are actually supported. ## References PR #1884 ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. * [x] No new tests. * [x] No new docs. * [ ] 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: #1884 ## Detailed Description of the Pull Request / Additional comments In some cases there are methods that implement multiple VT functions which are essentially aliases. Originally the comments listed only one of the functions, so I've now updated them to list both. This includes `HPA` as an alias of `CHA`, and `HVP` as an alias of `CUP`. Similarly, some control characters are implemented in terms of another VT function, but only the main function was listed in the comment. Again I've now updated the comments to list both the main function and any related control characters. This includes `BS` (sharing the same method as `CUB`), `HT` (the same method as `CHT`), and `LF`, `FF`, and `VT` (the same method as `IND` and `NEL`). Then there were some minor corrections. The `DeviceAttributes` method was commented as `DA`, but it really should be `DA1`. `DesignateCharset` was simply commented as _DesignateCharset_, when it should be `SCS`. The `DECSCNM` comment was missing a space, so it wasn't picked up by the script. And the `SetColumns` comment mistakenly included `DECSCPP`, but we don't actually support that. Finally there is the `DeviceStatusReport` method, which potentially covers a wide range of different reports. But for now we only support the _Cursor Position Report_, so I've commented it as `DSR, DSR-CPR` to more clearly indicate our level of support. In the long term we'll probably need a better way of handling these reports though. ## Validation Steps Performed I've run the script from PR #1884 and confirmed that the output is now a more accurate reflection of our actual VT support.
2020-03-17 16:55:22 +01:00
bool DeviceAttributes() noexcept override { return false; } // DA1
Add support for DA2 and DA3 device attributes reports (#6850) This PR adds support for the `DA2` (Secondary Device Attributes) and `DA3` (Tertiary Device Attributes) escape sequences, which are standard VT queries reporting basic information about the terminal. The _Secondary Device Attributes_ response is made up of a number of parameters: 1. An identification code, for which I've used 0 to indicate that we have the capabilities of a VT100 (using code 0 for this is an XTerm convention, since technically DA2 would not have been supported by a VT100). 2. A firmware revision level, which some terminal emulators use to report their actual version number, but I thought it best we just hardcode a value of 10 (the DEC convention for 1.0). 3. Additional hardware options, which tend to be device specific, but I've followed the convention of the later DEC terminals using 1 to indicate the presence of a PC keyboard. The _Tertiary Device Attributes_ response was originally used to provide a unique terminal identification code, and which some terminal emulators use as a way to identify themselves. However, I think that's information we'd probably prefer not to reveal, so I've followed the more common practice of returning all zeros for the ID. In terms of implementation, the only complication was the need to add an additional code path in the `OutputStateMachine` to handle the `>` and `=` intermediates (technically private parameter prefixes) that these sequences require. I've done this as a single method - rather than one for each prefix - since I think that makes the code easier to follow. VALIDATION ---------- I've added output engine tests to make sure the sequences are dispatched correctly, and adapter tests to confirm that they are returning the responses we expect. I've also manually confirmed that they pass the _Test of terminal reports_ in Vttest. Closes #5836
2020-07-11 00:27:47 +02:00
bool SecondaryDeviceAttributes() noexcept override { return false; } // DA2
bool TertiaryDeviceAttributes() noexcept override { return false; } // DA3
Add support for VT52 emulation (#4789) ## Summary of the Pull Request This PR adds support for the core VT52 commands, and implements the `DECANM` private mode sequence, which switches the terminal between ANSI mode and VT52-compatible mode. ## References PR #2017 defined the initial specification for VT52 support. PR #4044 removed the original VT52 cursor ops that conflicted with VT100 sequences. ## PR Checklist * [x] Closes #976 * [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: #2017 ## Detailed Description of the Pull Request / Additional comments Most of the work involves updates to the parsing state machine, which behaves differently in VT52 mode. `CSI`, `OSC`, and `SS3` sequences are not applicable, and there is one special-case escape sequence (_Direct Cursor Address_), which requires an additional state to handle parameters that come _after_ the final character. Once the parsing is handled though, it's mostly just a matter of dispatching the commands to existing methods in the `ITermDispatch` interface. Only one new method was required in the interface to handle the _Identify_ command. The only real new functionality is in the `TerminalInput` class, which needs to generate different escape sequences for certain keys in VT52 mode. This does not yet support _all_ of the VT52 key sequences, because the VT100 support is itself not yet complete. But the basics are in place, and I think the rest is best left for a follow-up issue, and potentially a refactor of the `TerminalInput` class. I should point out that the original spec called for a new _Graphic Mode_ character set, but I've since discovered that the VT terminals that _emulate_ VT52 just use the existing VT100 _Special Graphics_ set, so that is really what we should be doing too. We can always consider adding the VT52 graphic set as a option later, if there is demand for strict VT52 compatibility. ## Validation Steps Performed I've added state machine and adapter tests to confirm that the `DECANM` mode changing sequences are correctly dispatched and forwarded to the `ConGetSet` handler. I've also added state machine tests that confirm the VT52 escape sequences are dispatched correctly when the ANSI mode is reset. For fuzzing support, I've extended the VT command fuzzer to generate the different kinds of VT52 sequences, as well as mode change sequences to switch between the ANSI and VT52 modes. In terms of manual testing, I've confirmed that the _Test of VT52 mode_ in Vttest now works as expected.
2020-06-01 23:20:40 +02:00
bool Vt52DeviceAttributes() noexcept override { return false; } // VT52 Identify
Add support for the DECREQTPARM report (#7939) This PR adds support for the `DECREQTPARM` (Request Terminal Parameters) escape sequence, which was originally used on the VT100 terminal to report the serial communication parameters. Modern terminal emulators simply hardcode the reported values for backward compatibility. The `DECREQTPARM` sequence has one parameter, which was originally used to tell the terminal whether it was permitted to send unsolicited reports or not. However, since we have no reason to send an unsolicited report, we don't need to keep track of that state, but the permission parameter does still determine the value of the first parameter in the response. The response parameters are as follows: | Parameter | Value | Meaning | | ---------------- | ------ | ------------------------ | | response type | 2 or 3 | unsolicited or solicited | | parity | 1 | no parity | | data bits | 1 | 8 bits per character | | transmit speed | 128 | 38400 baud | | receive speed | 128 | 38400 baud | | clock multiplier | 1 | | | flags | 0 | | There is some variation in the baud rate reported by modern terminal emulators, and 9600 baud seems to be a little more common than 38400 baud, but I thought the higher speed was probably more appropriate, especially since that's also the value reported by XTerm. ## Validation Steps Performed I've added a couple of adapter and output engine tests to verify that the sequence is dispatched correctly, and the expected responses are generated. I've also manually tested in Vttest and confirmed that we now pass the `DECREQTPARM` test in the _Test of terminal reports_. Closes #7852
2020-10-16 00:50:02 +02:00
bool RequestTerminalParameters(const DispatchTypes::ReportingPermission /*permission*/) noexcept override { return false; } // DECREQTPARM
Refactor VT control sequence identification (#7304) This PR changes the way VT control sequences are identified and dispatched, to be more efficient and easier to extend. Instead of parsing the intermediate characters into a vector, and then having to identify a sequence using both that vector and the final char, we now use just a single `uint64_t` value as the identifier. The way the identifier is constructed is by taking the private parameter prefix, each of the intermediate characters, and then the final character, and shifting them into a 64-bit integer one byte at a time, in reverse order. For example, the `DECTLTC` control has a private parameter prefix of `?`, one intermediate of `'`, and a final character of `s`. The ASCII values of those characters are `0x3F`, `0x27`, and `0x73` respectively, and reversing them gets you 0x73273F, so that would then be the identifier for the control. The reason for storing them in reverse order, is because sometimes we need to look at the first intermediate to determine the operation, and treat the rest of the sequence as a kind of sub-identifier (the character set designation sequences are one example of this). When in reverse order, this can easily be achieved by masking off the low byte to get the first intermediate, and then shifting the value right by 8 bits to get a new identifier with the rest of the sequence. With 64 bits we have enough space for a private prefix, six intermediates, and the final char, which is way more than we should ever need (the _DEC STD 070_ specification recommends supporting at least three intermediates, but in practice we're unlikely to see more than two). With this new way of identifying controls, it should now be possible for every action code to be unique (for the most part). So I've also used this PR to clean up the action codes a bit, splitting the codes for the escape sequences from the control sequences, and sorting them into alphabetical order (which also does a reasonable job of clustering associated controls). ## Validation Steps Performed I think the existing unit tests should be good enough to confirm that all sequences are still being dispatched correctly. However, I've also manually tested a number of sequences to make sure they were still working as expected, in particular those that used intermediates, since they were the most affected by the dispatch code refactoring. Since these changes also affected the input state machine, I've done some manual testing of the conpty keyboard handling (both with and without the new Win32 input mode enabled) to make sure the keyboard VT sequences were processed correctly. I've also manually tested the various VT mouse modes in Vttest to confirm that they were still working correctly too. Closes #7276
2020-08-18 20:57:52 +02:00
bool DesignateCodingSystem(const VTID /*codingSystem*/) noexcept override { return false; } // DOCS
bool Designate94Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) noexcept override { return false; } // SCS
bool Designate96Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) noexcept override { return false; } // SCS
Improve support for VT character sets (#4496) This PR improves our VT character set support, enabling the [`SCS`] escape sequences to designate into all four G-sets with both 94- and 96-character sets, and supports invoking those G-sets into both the GL and GR areas of the code table, with [locking shifts] and [single shifts]. It also adds [`DOCS`] sequences to switch between UTF-8 and the ISO-2022 coding system (which is what the VT character sets require), and adds support for a lot more characters sets, up to around the level of a VT510. [`SCS`]: https://vt100.net/docs/vt510-rm/SCS.html [locking shifts]: https://vt100.net/docs/vt510-rm/LS.html [single shifts]: https://vt100.net/docs/vt510-rm/SS.html [`DOCS`]: https://en.wikipedia.org/wiki/ISO/IEC_2022#Interaction_with_other_coding_systems ## Detailed Description of the Pull Request / Additional comments To make it easier for us to declare a bunch of character sets, I've made a little `constexpr` class that can build up a mapping table from a base character set (ASCII or Latin1), along with a collection of mappings for the characters the deviate from the base set. Many of the character sets are simple variations of ASCII, so they're easy to define this way. This class then casts directly to a `wstring_view` which is how the translation tables are represented in most of the code. We have an array of four of these tables representing the four G-sets, two instances for the active left and right tables, and one instance for the single shift table. Initially we had just one `DesignateCharset` method, which could select the active character set. We now have two designate methods (for 94- and 96- character sets), and each takes a G-set number specifying the target of the designation, and a pair of characters identifying the character set that will be designated (at the higher VT levels, character sets are often identified by more than one character). There are then two new `LockingShift` methods to invoke these G-sets into either the GL or GR area of the code table, and a `SingleShift` method which invokes a G-set temporarily (for just the next character that is output). I should mention here that I had to make some changes to the state machine to make these single shift sequences work. The problem is that the input state machine treats `SS3` as the start of a control sequence, while the output state machine needs it to be dispatched immediately (it's literally the _Single Shift 3_ escape sequence). To make that work, I've added a `ParseControlSequenceAfterSs3` callback in the `IStateMachineEngine` interface to decide which behavior is appropriate. When it comes to mapping a character, it's simply an array reference into the appropriate `wstring_view` table. If the single shift table is set, that takes preference. Otherwise the GL table is used for characters in the range 0x20 to 0x7F, and the GR table for characters 0xA0 to 0xFF (technically some character sets will only map up to 0x7E and 0xFE, but that's easily controlled by the length of the `wstring_view`). The `DEL` character is a bit of a special case. By default it's meant to be ignored like the `NUL` character (it's essentially a time-fill character). However, it's possible that it could be remapped to a printable character in a 96-character set, so we need to check for that after the translation. This is handled in the `AdaptDispatch::Print` method, so it doesn't interfere with the primary `PrintString` code path. The biggest problem with this whole process, though, is that the GR mappings only really make sense if you have access to the raw output, but by the time the output gets to us, it would already have been translated to Unicode by the active code page. And in the case of UTF-8, the characters we eventually receive may originally have been composed from two or more code points. The way I've dealt with this was to disable the GR translations by default, and then added support for a pair of ISO-2022 `DOCS` sequences, which can switch the code page between UTF-8 and ISO-8859-1. When the code page is ISO-8859-1, we're essentially receiving the raw output bytes, so it's safe to enable the GR translations. This is not strictly correct ISO-2022 behavior, and there are edge cases where it's not going to work, but it's the best solution I could come up with. ## Validation Steps Performed As a result of the `SS3` changes in the state machine engine, I've had to move the existing `SS3` tests from the `OutputEngineTest` to the `InputEngineTest`, otherwise they would now fail (technically they should never have been output tests). I've added no additional unit tests, but I have done a lot of manual testing, and made sure we passed all the character set tests in Vttest (at least for the character sets we currently support). Note that this required a slightly hacked version of the app, since by default it doesn't expose a lot of the test to low-level terminals, and we currently identify as a VT100. Closes #3377 Closes #3487
2020-06-04 21:40:15 +02:00
bool LockingShift(const size_t /*gsetNumber*/) noexcept override { return false; } // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t /*gsetNumber*/) noexcept override { return false; } // LS1R, LS2R, LS3R
bool SingleShift(const size_t /*gsetNumber*/) noexcept override { return false; } // SS2, SS3
bool SoftReset() noexcept override { return false; } // DECSTR
bool HardReset() noexcept override { return false; } // RIS
bool ScreenAlignmentPattern() noexcept override { return false; } // DECALN
bool SetCursorStyle(const DispatchTypes::CursorStyle /*cursorStyle*/) noexcept override { return false; } // DECSCUSR
bool SetCursorColor(const COLORREF /*color*/) noexcept override { return false; } // OSCSetCursorColor, OSCResetCursorColor
bool SetClipboard(std::wstring_view /*content*/) noexcept override { return false; } // OscSetClipboard
// DTTERM_WindowManipulation
bool WindowManipulation(const DispatchTypes::WindowManipulationType /*function*/,
Refactor VT parameter handling (#7799) This PR introduces a pair of classes for managing VT parameters that automatically handle range checking and default fallback values, so the individual operations don't have to do that validation themselves. In addition to simplifying the code, this fixes a few cases where we were mishandling missing or extraneous parameters, and adds support for parameter sequences on commands that couldn't previously handle them. This PR also sets a limit on the number of parameters allowed, to help thwart DoS memory consumption attacks. ## References * The new parameter class also introduces the concept of an omitted/default parameter which is not necessarily zero, which is a prerequisite for addressing issue #4417. ## Detailed Description of the Pull Request / Additional comments There are two new classes provide by this PR: a `VTParameter` class, similar in function to a `std::optional<size_t>`, which holds an individual parameter (which may be an omitted/default value); and a `VTParameters` class, similar in function to `gsl:span<VTParameter>`, which holds a sequence of those parameters. Where `VTParameter` differs from `std::optional` is with the inclusion of two cast operators. There is a `size_t` cast that interprets omitted and zero values as 1 (the expected behaviour for most numeric parameters). And there is a generic cast, for use with the enum parameter types, which interprets omitted values as 0 (the expected behaviour for most selective parameters). The advantage of `VTParameters` class is that it has an `at` method that can never fail - out of range values simply return the a default `VTParameter` instance (this is standard behaviour in VT terminals). It also has a `size` method that will always return a minimum count of 1, since an empty parameter list is typically the equivalent of a single "default" parameter, so this guarantees you'll get at least one value when iterating over the list with `size()`. For cases where we just need to call the same dispatch method for every parameter, there is a helper `for_each` method, which repeatedly calls a given predicate function with each value in the sequence. It also collates the returned success values to determine the overall result of the sequence. As with the `size` method, this will always make at least one call, so it correctly handles empty sequences. With those two classes in place, we could get rid of all the parameter validation and default handling code in the `OutputStateMachineEngine`. We now just use the `VTParameters::at` method to grab a parameter and typically pass it straight to the appropriate dispatch method, letting the cast operators automatically handle the assignment of default values. Occasionally we might need a `value_or` call to specify a non-standard default value, but those cases are fairly rare. In some case the `OutputStateMachineEngine` was also checking whether parameters values were in range, but for the most part this shouldn't have been necessary, since that is something the dispatch classes would already have been doing themselves (in the few cases that they weren't, I've now updated them to do so). I've also updated the `InputStateMachineEngine` in a similar way to the `OutputStateMachineEngine`, getting rid of a few of the parameter extraction methods, and simplifying other parts of the implementation. It's not as clean a replacement as the output engine, but there are still benefits in using the new classes. ## Validation Steps Performed For the most part I haven't had to alter existing tests other than accounting for changes to the API. There were a couple of tests I needed to drop because they were checking for failure cases which shouldn't have been failing (unexpected parameters should never be an error), or testing output engine validation that is no longer handled at that level. I've added a few new tests to cover operations that take sequences of selective parameters (`ED`, `EL`, `TBC`, `SM`, and `RM`). And I've extended the cursor movement tests to make sure those operations can handle extraneous parameters that weren't expected. I've also added a test to verify that the state machine will correctly ignore parameters beyond the maximum 32 parameter count limit. I've also manual confirmed that the various test cases given in issues #2101 are now working as expected. Closes #2101
2020-10-15 18:12:52 +02:00
const VTParameter /*parameter1*/,
const VTParameter /*parameter2*/) noexcept override { return false; }
OSC 8 support for conhost and terminal (#7251) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Conhost can now support OSC8 sequences (as specified [here](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)). Terminal also supports those sequences and additionally hyperlinks can be opened by Ctrl+LeftClicking on them. <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References #204 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [X] Closes #204 * [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] 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: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Added support to: - parse OSC8 sequences and extract URIs from them (conhost and terminal) - add hyperlink uri data to textbuffer/screeninformation, associated with a hyperlink id (conhost and terminal) - attach hyperlink ids to text to allow for uri extraction from the textbuffer/screeninformation (conhost and terminal) - process ctrl+leftclick to open a hyperlink in the clicked region if present <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Open up a PowerShell tab and type ```PowerShell ${ESC}=[char]27 Write-Host "${ESC}]8;;https://github.com/microsoft/terminal${ESC}\This is a link!${ESC}]8;;${ESC}\" ``` Ctrl+LeftClick on the link correctly brings you to the terminal page on github ![hyperlink](https://user-images.githubusercontent.com/26824113/89953536-45a6f580-dbfd-11ea-8e0d-8a3cd25c634a.gif)
2020-09-03 19:52:39 +02:00
bool AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) noexcept override { return false; }
bool EndHyperlink() noexcept override { return false; }
bool DoConEmuAction(const std::wstring_view /*string*/) noexcept override { return false; }
Add support for downloadable soft fonts (#10011) This PR adds conhost support for downloadable soft fonts - also known as dynamically redefinable character sets (DRCS) - using the `DECDLD` escape sequence. These fonts are typically designed to work on a specific terminal model, and each model tends to have a different character cell size. So in order to support as many models as possible, the code attempts to detect the original target size of the font, and then scale the glyphs to fit our current cell size. Once a font has been downloaded to the terminal, it can be designated in the same way you would a standard character set, using an `SCS` escape sequence. The identification string for the set is defined by the `DECDLD` sequence. Internally we map the characters in this set to code points `U+EF20` to `U+EF7F` in the Unicode private use are (PUA). Then in the renderer, any characters in that range are split off into separate runs, which get painted with a special font. The font itself is dynamically generated as an in-memory resource, constructed from the downloaded character bitmaps which have been scaled to the appropriate size. If no soft fonts are in use, then no mapping of the PUA code points will take place, so this shouldn't interfere with anyone using those code points for something else, as along as they aren't also trying to use soft fonts. I also tried to pick a PUA range that hadn't already been snatched up by Nerd Fonts, but if we do receive reports of a conflict, it's easy enough to change. ## Validation Steps Performed I added an adapter test that runs through a bunch of parameter variations for the `DECDLD` sequence, to make sure we're correctly detecting the font sizes for most of the known DEC terminal models. I've also tested manually on a wide range of existing fonts, of varying dimensions, and from multiple sources, and made sure they all worked reasonably well. Closes #9164
2021-08-06 22:41:02 +02:00
StringHandler DownloadDRCS(const size_t /*fontNumber*/,
const VTParameter /*startChar*/,
const DispatchTypes::DrcsEraseControl /*eraseControl*/,
const DispatchTypes::DrcsCellMatrix /*cellMatrix*/,
const DispatchTypes::DrcsFontSet /*fontSet*/,
const DispatchTypes::DrcsFontUsage /*fontUsage*/,
const VTParameter /*cellHeight*/,
const DispatchTypes::DrcsCharsetSize /*charsetSize*/) noexcept override { return nullptr; }
StringHandler RequestSetting() noexcept override { return nullptr; }; // DECRQSS
};