terminal/src/terminal/adapter/adaptDispatch.hpp
James Holderness 7b7dea009c
Consolidate the interfaces for setting VT input modes (#11384)
Instead of having a separate method for setting each mouse and keyboard
mode, this PR consolidates them all into a single method which takes a
mode parameter, and stores the modes in a `til::enumset` rather than
having a separate `bool` for each mode.

This enables us to get rid of a lot of boilerplate code, and makes the
code easier to extend when we want to introduce additional modes in the
future. It'll also makes it easier to read back the state of the various
modes when implementing the `DECRQM` query.

Most of the complication is in the `TerminalInput` class, which had to
be adjusted to work with an `enumset` in place of all the `bool` fields.
For the rest, it was largely a matter of replacing calls to all the old
mode setting methods with the new `SetInputMode` method, and deleting a
bunch of unused code.

One thing worth mentioning is that the `AdaptDispatch` implementation
used to have a `_ShouldPassThroughInputModeChange` method that was
called after every mode change. This code has now been moved up into the
`SetInputMode` implementation in `ConhostInternalGetSet` so it's just
handled in one place. Keeping this out of the dispatch class will also
be beneficial for sharing the implementation with `TerminalDispatch`.

## Validation

The updated interface necessitated some adjustments to the tests in
`AdapterTest` and `MouseInputTest`, but the essential structure of the
tests remains unchanged, and everything still passes.

I've also tested the keyboard and mouse modes in Vttest and confirmed
they still work at least as well as they did before (both conhost and
Windows Terminal), and I tested the alternate scroll mode manually
(conhost only).

Simplifying the `ConGetSet` and `ITerminalApi` is also part of the plan
to de-duplicate the `AdaptDispatch` and `TerminalDispatch`
implementation (#3849).
2021-10-26 21:12:22 +00:00

227 lines
11 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- adaptDispatch.hpp
Abstract:
- This serves as the Windows Console API-specific implementation of the callbacks from our generic Virtual Terminal parser.
Author(s):
- Michael Niksa (MiNiksa) 30-July-2015
--*/
#pragma once
#include "termDispatch.hpp"
#include "DispatchCommon.hpp"
#include "conGetSet.hpp"
#include "adaptDefaults.hpp"
#include "FontBuffer.hpp"
#include "terminalOutput.hpp"
#include "..\..\types\inc\sgrStack.hpp"
namespace Microsoft::Console::VirtualTerminal
{
class AdaptDispatch : public ITermDispatch
{
public:
AdaptDispatch(std::unique_ptr<ConGetSet> pConApi,
std::unique_ptr<AdaptDefaults> pDefaults);
void Execute(const wchar_t wchControl) override
{
_pDefaults->Execute(wchControl);
}
void PrintString(const std::wstring_view string) override;
void Print(const wchar_t wchPrintable) override;
bool CursorUp(const size_t distance) override; // CUU
bool CursorDown(const size_t distance) override; // CUD
bool CursorForward(const size_t distance) override; // CUF
bool CursorBackward(const size_t distance) override; // CUB, BS
bool CursorNextLine(const size_t distance) override; // CNL
bool CursorPrevLine(const size_t distance) override; // CPL
bool CursorHorizontalPositionAbsolute(const size_t column) override; // HPA, CHA
bool VerticalLinePositionAbsolute(const size_t line) override; // VPA
bool HorizontalPositionRelative(const size_t distance) override; // HPR
bool VerticalPositionRelative(const size_t distance) override; // VPR
bool CursorPosition(const size_t line, const size_t column) override; // CUP, HVP
bool CursorSaveState() override; // DECSC
bool CursorRestoreState() override; // DECRC
bool CursorVisibility(const bool isVisible) override; // DECTCEM
bool EraseInDisplay(const DispatchTypes::EraseType eraseType) override; // ED
bool EraseInLine(const DispatchTypes::EraseType eraseType) override; // EL
bool EraseCharacters(const size_t numChars) override; // ECH
bool InsertCharacter(const size_t count) override; // ICH
bool DeleteCharacter(const size_t count) override; // DCH
bool SetGraphicsRendition(const VTParameters options) override; // SGR
bool SetLineRendition(const LineRendition rendition) override; // DECSWL, DECDWL, DECDHL
bool PushGraphicsRendition(const VTParameters options) override; // XTPUSHSGR
bool PopGraphicsRendition() override; // XTPOPSGR
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) override; // DSR, DSR-OS, DSR-CPR
bool DeviceAttributes() override; // DA1
bool SecondaryDeviceAttributes() override; // DA2
bool TertiaryDeviceAttributes() override; // DA3
bool Vt52DeviceAttributes() override; // VT52 Identify
bool RequestTerminalParameters(const DispatchTypes::ReportingPermission permission) override; // DECREQTPARM
bool ScrollUp(const size_t distance) override; // SU
bool ScrollDown(const size_t distance) override; // SD
bool InsertLine(const size_t distance) override; // IL
bool DeleteLine(const size_t distance) override; // DL
bool SetColumns(const size_t columns) override; // DECCOLM
bool SetMode(const DispatchTypes::ModeParams param) override; // DECSET
bool ResetMode(const DispatchTypes::ModeParams param) override; // DECRST
bool SetCursorKeysMode(const bool applicationMode) override; // DECCKM
bool SetKeypadMode(const bool applicationMode) override; // DECKPAM, DECKPNM
bool EnableWin32InputMode(const bool win32InputMode) override; // win32-input-mode
bool EnableCursorBlinking(const bool enable) override; // ATT610
bool SetAnsiMode(const bool ansiMode) override; // DECANM
bool SetScreenMode(const bool reverseMode) override; // DECSCNM
bool SetOriginMode(const bool relativeMode) noexcept override; // DECOM
bool SetAutoWrapMode(const bool wrapAtEOL) override; // DECAWM
bool SetTopBottomScrollingMargins(const size_t topMargin,
const size_t bottomMargin) override; // DECSTBM
bool WarningBell() override; // BEL
bool CarriageReturn() override; // CR
bool LineFeed(const DispatchTypes::LineFeedType lineFeedType) override; // IND, NEL, LF, FF, VT
bool ReverseLineFeed() override; // RI
bool SetWindowTitle(const std::wstring_view title) override; // OSCWindowTitle
bool UseAlternateScreenBuffer() override; // ASBSET
bool UseMainScreenBuffer() override; // ASBRST
bool HorizontalTabSet() override; // HTS
bool ForwardTab(const size_t numTabs) override; // CHT, HT
bool BackwardsTab(const size_t numTabs) override; // CBT
bool TabClear(const DispatchTypes::TabClearType clearType) override; // TBC
bool DesignateCodingSystem(const VTID codingSystem) override; // DOCS
bool Designate94Charset(const size_t gsetNumber, const VTID charset) override; // SCS
bool Designate96Charset(const size_t gsetNumber, const VTID charset) override; // SCS
bool LockingShift(const size_t gsetNumber) override; // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t gsetNumber) override; // LS1R, LS2R, LS3R
bool SingleShift(const size_t gsetNumber) override; // SS2, SS3
bool SoftReset() override; // DECSTR
bool HardReset() override; // RIS
bool ScreenAlignmentPattern() override; // DECALN
bool EnableDECCOLMSupport(const bool enabled) noexcept override; // ?40
bool EnableVT200MouseMode(const bool enabled) override; // ?1000
bool EnableUTF8ExtendedMouseMode(const bool enabled) override; // ?1005
bool EnableSGRExtendedMouseMode(const bool enabled) override; // ?1006
bool EnableButtonEventMouseMode(const bool enabled) override; // ?1002
bool EnableAnyEventMouseMode(const bool enabled) override; // ?1003
bool EnableAlternateScroll(const bool enabled) override; // ?1007
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override; // ?2004
bool SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) override; // DECSCUSR
bool SetCursorColor(const COLORREF cursorColor) override;
bool SetClipboard(const std::wstring_view content) noexcept override; // OSCSetClipboard
bool SetColorTableEntry(const size_t tableIndex,
const DWORD color) override; // OSCColorTable
bool SetDefaultForeground(const DWORD color) override; // OSCDefaultForeground
bool SetDefaultBackground(const DWORD color) override; // OSCDefaultBackground
bool WindowManipulation(const DispatchTypes::WindowManipulationType function,
const VTParameter parameter1,
const VTParameter parameter2) override; // DTTERM_WindowManipulation
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override;
bool EndHyperlink() override;
bool DoConEmuAction(const std::wstring_view string) noexcept override;
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) override; // DECDLD
StringHandler RequestSetting() override; // DECRQSS
private:
enum class ScrollDirection
{
Up,
Down
};
struct CursorState
{
unsigned int Row = 1;
unsigned int Column = 1;
bool IsOriginModeRelative = false;
TextAttribute Attributes = {};
TerminalOutput TermOutput = {};
unsigned int CodePage = 0;
};
struct Offset
{
int Value;
bool IsAbsolute;
// VT origin is at 1,1 so we need to subtract 1 from absolute positions.
static constexpr Offset Absolute(const size_t value) { return { gsl::narrow_cast<int>(value) - 1, true }; };
static constexpr Offset Forward(const size_t value) { return { gsl::narrow_cast<int>(value), false }; };
static constexpr Offset Backward(const size_t value) { return { -gsl::narrow_cast<int>(value), false }; };
static constexpr Offset Unchanged() { return Forward(0); };
};
bool _CursorMovePosition(const Offset rowOffset, const Offset colOffset, const bool clampInMargins) const;
bool _EraseSingleLineHelper(const CONSOLE_SCREEN_BUFFER_INFOEX& csbiex,
const DispatchTypes::EraseType eraseType,
const size_t lineId) const;
bool _EraseScrollback();
bool _EraseAll();
bool _InsertDeleteHelper(const size_t count, const bool isInsert) const;
bool _ScrollMovement(const ScrollDirection dir, const size_t distance) const;
bool _DoSetTopBottomScrollingMargins(const size_t topMargin,
const size_t bottomMargin);
bool _OperatingStatus() const;
bool _CursorPositionReport() const;
bool _WriteResponse(const std::wstring_view reply) const;
bool _ModeParamsHelper(const DispatchTypes::ModeParams param, const bool enable);
bool _DoDECCOLMHelper(const size_t columns);
bool _ClearSingleTabStop();
bool _ClearAllTabStops() noexcept;
void _ResetTabStops() noexcept;
void _InitTabStopsForWidth(const size_t width);
void _ReportSGRSetting() const;
void _ReportDECSTBMSetting() const;
std::vector<bool> _tabStopColumns;
bool _initDefaultTabStops = true;
std::unique_ptr<ConGetSet> _pConApi;
std::unique_ptr<AdaptDefaults> _pDefaults;
TerminalOutput _termOutput;
std::unique_ptr<FontBuffer> _fontBuffer;
std::optional<unsigned int> _initialCodePage;
// We have two instances of the saved cursor state, because we need
// one for the main buffer (at index 0), and another for the alt buffer
// (at index 1). The _usingAltBuffer property keeps tracks of which
// buffer is active, so can be used as an index into this array to
// obtain the saved state that should be currently active.
std::array<CursorState, 2> _savedCursorState;
bool _usingAltBuffer;
SMALL_RECT _scrollMargins;
bool _isOriginModeRelative;
bool _isDECCOLMAllowed;
SgrStack _sgrStack;
size_t _SetRgbColorsHelper(const VTParameters options,
TextAttribute& attr,
const bool isForeground) noexcept;
};
}