Apply audit mode to TerminalInput/Adapter/Parser libraries (#4005)

<!-- 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
- Enables auditing of Virtual Terminal libraries (input, adapter, parser)

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Rolls audit out to more things
* [x] I work here
* [x] Tests should still pass
* [x] Am core contributor
* [x] Closes #3957

<!-- 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
This is turning on the auditing of these projects (as enabled by the heavier lifting in the other refactor) and then cleaning up the remaining warnings.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- [x] Built it
- [x] Ran the tests
This commit is contained in:
Michael Niksa 2020-01-03 06:25:21 -08:00 committed by msftbot[bot]
parent f467422912
commit 322989d017
36 changed files with 1162 additions and 1271 deletions

View File

@ -353,8 +353,8 @@ Global
{2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|x86.Build.0 = Release|Win32
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.ActiveCfg = Release|x64
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.Build.0 = Release|x64
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.ActiveCfg = AuditMode|x64
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.Build.0 = AuditMode|x64
{3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x86.ActiveCfg = Release|Win32
{3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|Any CPU.ActiveCfg = Debug|Win32
{3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|ARM64.ActiveCfg = Debug|ARM64
@ -372,7 +372,8 @@ Global
{3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|x86.Build.0 = Release|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = Release|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = AuditMode|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.Build.0 = AuditMode|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.ActiveCfg = Release|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|Any CPU.ActiveCfg = Debug|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
@ -390,8 +391,8 @@ Global
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x86.Build.0 = Release|Win32
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = Release|x64
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.Build.0 = Release|x64
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = AuditMode|x64
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.Build.0 = AuditMode|x64
{1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.ActiveCfg = Release|Win32
{1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|Any CPU.ActiveCfg = Debug|Win32
{1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64

View File

@ -31,7 +31,7 @@ void TerminalDispatch::PrintString(const std::wstring_view string)
}
bool TerminalDispatch::CursorPosition(const size_t line,
const size_t column)
const size_t column) noexcept
{
const auto columnInBufferSpace = column - 1;
const auto lineInBufferSpace = line - 1;
@ -40,33 +40,33 @@ bool TerminalDispatch::CursorPosition(const size_t line,
return _terminalApi.SetCursorPosition(x, y);
}
bool TerminalDispatch::CursorForward(const size_t distance)
bool TerminalDispatch::CursorForward(const size_t distance) noexcept
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X + gsl::narrow<short>(distance), cursorPos.Y };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
}
bool TerminalDispatch::CursorBackward(const size_t distance)
bool TerminalDispatch::CursorBackward(const size_t distance) noexcept
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X - gsl::narrow<short>(distance), cursorPos.Y };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
}
bool TerminalDispatch::CursorUp(const size_t distance)
bool TerminalDispatch::CursorUp(const size_t distance) noexcept
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X, cursorPos.Y + gsl::narrow<short>(distance) };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
}
bool TerminalDispatch::EraseCharacters(const size_t numChars)
bool TerminalDispatch::EraseCharacters(const size_t numChars) noexcept
{
return _terminalApi.EraseCharacters(numChars);
}
bool TerminalDispatch::SetWindowTitle(std::wstring_view title)
bool TerminalDispatch::SetWindowTitle(std::wstring_view title) noexcept
{
return _terminalApi.SetWindowTitle(title);
}
@ -79,12 +79,12 @@ bool TerminalDispatch::SetWindowTitle(std::wstring_view title)
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::SetColorTableEntry(const size_t tableIndex,
const DWORD color)
const DWORD color) noexcept
{
return _terminalApi.SetColorTableEntry(tableIndex, color);
}
bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noexcept
{
return _terminalApi.SetCursorStyle(cursorStyle);
}
@ -95,7 +95,7 @@ bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorSty
// - color: The new RGB color value to use, in 0x00BBGGRR form
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::SetDefaultForeground(const DWORD color)
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
{
return _terminalApi.SetDefaultForeground(color);
}
@ -106,7 +106,7 @@ bool TerminalDispatch::SetDefaultForeground(const DWORD color)
// - color: The new RGB color value to use, in 0x00BBGGRR form
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::SetDefaultBackground(const DWORD color)
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
{
return _terminalApi.SetDefaultBackground(color);
}
@ -117,7 +117,7 @@ bool TerminalDispatch::SetDefaultBackground(const DWORD color)
// - eraseType: the erase type (from beginning, to end, or all)
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType)
bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType) noexcept
{
return _terminalApi.EraseInLine(eraseType);
}
@ -128,7 +128,7 @@ bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType)
// - count, the number of characters to delete
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::DeleteCharacter(const size_t count)
bool TerminalDispatch::DeleteCharacter(const size_t count) noexcept
{
return _terminalApi.DeleteCharacter(count);
}
@ -139,7 +139,7 @@ bool TerminalDispatch::DeleteCharacter(const size_t count)
// - count, the number of spaces to add
// Return Value:
// True if handled successfully, false otherwise
bool TerminalDispatch::InsertCharacter(const size_t count)
bool TerminalDispatch::InsertCharacter(const size_t count) noexcept
{
return _terminalApi.InsertCharacter(count);
}
@ -150,7 +150,7 @@ bool TerminalDispatch::InsertCharacter(const size_t count)
// - eraseType: the desired erase type
// Return Value:
// True if handled successfully. False otherwise
bool TerminalDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType)
bool TerminalDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) noexcept
{
return _terminalApi.EraseInDisplay(eraseType);
}

View File

@ -13,27 +13,27 @@ public:
virtual void Print(const wchar_t wchPrintable) override;
virtual void PrintString(const std::wstring_view string) override;
bool SetGraphicsRendition(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions> options) override;
bool SetGraphicsRendition(const std::basic_string_view<::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions> options) noexcept override;
virtual bool CursorPosition(const size_t line,
const size_t column) override; // CUP
const size_t column) noexcept override; // CUP
bool CursorForward(const size_t distance) override;
bool CursorBackward(const size_t distance) override;
bool CursorUp(const size_t distance) override;
bool CursorForward(const size_t distance) noexcept override;
bool CursorBackward(const size_t distance) noexcept override;
bool CursorUp(const size_t distance) noexcept override;
bool EraseCharacters(const size_t numChars) override;
bool SetWindowTitle(std::wstring_view title) override;
bool EraseCharacters(const size_t numChars) noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const DWORD color) override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override;
bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
bool SetDefaultForeground(const DWORD color) override;
bool SetDefaultBackground(const DWORD color) override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; // ED
bool DeleteCharacter(const size_t count) override;
bool InsertCharacter(const size_t count) override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override;
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;
private:
::Microsoft::Terminal::Core::ITerminalApi& _terminalApi;

View File

@ -287,7 +287,7 @@ void TerminalDispatch::_SetGraphicsOptionHelper(const DispatchTypes::GraphicsOpt
}
}
bool TerminalDispatch::SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> options)
bool TerminalDispatch::SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> options) noexcept
{
bool success = false;
// Run through the graphics options and apply them

View File

@ -19,6 +19,8 @@ namespace Microsoft::Console
class ITerminalOutputConnection
{
public:
#pragma warning(push)
#pragma warning(disable : 26432) // suppress rule of 5 violation on interface because tampering with this is fraught with peril
virtual ~ITerminalOutputConnection() = 0;
[[nodiscard]] virtual HRESULT WriteTerminalUtf8(const std::string_view str) = 0;
@ -26,4 +28,5 @@ namespace Microsoft::Console
};
inline Microsoft::Console::ITerminalOutputConnection::~ITerminalOutputConnection() {}
#pragma warning(pop)
}

View File

@ -78,6 +78,9 @@
// WRL
#include <wrl.h>
// TIL - Terminal Implementation Library
#include "til.h"
#pragma warning(pop)
// clang-format on

45
src/inc/til.h Normal file
View File

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
// The at function declares that you've already sufficiently checked that your array access
// is in range before retrieving an item inside it at an offset.
// This is to save double/triple/quadruple testing in circumstances where you are already
// pivoting on the length of a set and now want to pull elements out of it by offset
// without checking again.
// gsl::at will do the check again. As will .at(). And using [] will have a warning in audit.
template<class T>
constexpr auto at(T& cont, const size_t i) -> decltype(cont[cont.size()])
{
#pragma warning(suppress : 26482) // Suppress bounds.2 check for indexing with constant expressions
#pragma warning(suppress : 26446) // Suppress bounds.4 check for subscript operator.
return cont[i];
}
}
// These sit outside the namespace because they sit outside for WIL too.
// Inspired from RETURN_IF_WIN32_BOOL_FALSE
// WIL doesn't include a RETURN_BOOL_IF_FALSE, and RETURN_IF_WIN32_BOOL_FALSE
// will actually return the value of GLE.
#define RETURN_BOOL_IF_FALSE(b) \
do \
{ \
const bool __boolRet = wil::verify_bool(b); \
if (!__boolRet) \
{ \
return __boolRet; \
} \
} while (0, 0)
// Due to a bug (DevDiv 441931), Warning 4297 (function marked noexcept throws exception) is detected even when the throwing code is unreachable, such as the end of scope after a return, in function-level catch.
#define CATCH_LOG_RETURN_FALSE() \
catch (...) \
{ \
__pragma(warning(suppress : 4297)); \
LOG_CAUGHT_EXCEPTION(); \
return false; \
}

View File

@ -25,17 +25,17 @@ bool DispatchCommon::s_ResizeWindow(ConGetSet& conApi,
SHORT sRows = 0;
// We should do nothing if 0 is passed in for a size.
bool fSuccess = SUCCEEDED(SizeTToShort(width, &sColumns)) &&
SUCCEEDED(SizeTToShort(height, &sRows)) &&
(width > 0 && height > 0);
bool success = SUCCEEDED(SizeTToShort(width, &sColumns)) &&
SUCCEEDED(SizeTToShort(height, &sRows)) &&
(width > 0 && height > 0);
if (fSuccess)
if (success)
{
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
fSuccess = !!conApi.GetConsoleScreenBufferInfoEx(csbiex);
success = conApi.GetConsoleScreenBufferInfoEx(csbiex);
if (fSuccess)
if (success)
{
const Viewport oldViewport = Viewport::FromInclusive(csbiex.srWindow);
const Viewport newViewport = Viewport::FromDimensions(oldViewport.Origin(),
@ -51,20 +51,20 @@ bool DispatchCommon::s_ResizeWindow(ConGetSet& conApi,
}
// SetConsoleWindowInfo expect inclusive rects
SMALL_RECT sri = newViewport.ToInclusive();
const auto sri = newViewport.ToInclusive();
// SetConsoleScreenBufferInfoEx however expects exclusive rects
SMALL_RECT sre = newViewport.ToExclusive();
const auto sre = newViewport.ToExclusive();
csbiex.srWindow = sre;
fSuccess = conApi.SetConsoleScreenBufferInfoEx(csbiex);
if (fSuccess)
success = conApi.SetConsoleScreenBufferInfoEx(csbiex);
if (success)
{
fSuccess = conApi.SetConsoleWindowInfo(true, sri);
success = conApi.SetConsoleWindowInfo(true, sri);
}
}
}
return fSuccess;
return success;
}
// Routine Description:

View File

@ -23,7 +23,10 @@ namespace Microsoft::Console::VirtualTerminal
class IInteractDispatch
{
public:
#pragma warning(push)
#pragma warning(disable : 26432) // suppress rule of 5 violation on interface because tampering with this is fraught with peril
virtual ~IInteractDispatch() = default;
#pragma warning(pop)
virtual bool WriteInput(std::deque<std::unique_ptr<IInputEvent>>& inputEvents) = 0;

View File

@ -22,7 +22,10 @@ namespace Microsoft::Console::VirtualTerminal
class Microsoft::Console::VirtualTerminal::ITermDispatch
{
public:
#pragma warning(push)
#pragma warning(disable : 26432) // suppress rule of 5 violation on interface because tampering with this is fraught with peril
virtual ~ITermDispatch() = 0;
virtual void Execute(const wchar_t wchControl) = 0;
virtual void Print(const wchar_t wchPrintable) = 0;
virtual void PrintString(const std::wstring_view string) = 0;
@ -97,3 +100,4 @@ public:
const std::basic_string_view<size_t> parameters) = 0;
};
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() {}
#pragma warning(pop)

View File

@ -115,7 +115,7 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio
// the ConGetSet interface, that specifically handles a conpty resize.
if (parameters.size() == 2)
{
success = DispatchCommon::s_ResizeWindow(*_pConApi, parameters[1], parameters[0]);
success = DispatchCommon::s_ResizeWindow(*_pConApi, til::at(parameters, 1), til::at(parameters, 0));
if (success)
{
DispatchCommon::s_SuppressResizeRepaint(*_pConApi);

View File

@ -25,8 +25,6 @@ namespace Microsoft::Console::VirtualTerminal
public:
InteractDispatch(std::unique_ptr<ConGetSet> pConApi);
~InteractDispatch() = default;
bool WriteInput(std::deque<std::unique_ptr<IInputEvent>>& inputEvents) override;
bool WriteCtrlC() override;
bool WriteString(const std::wstring_view string) override;

View File

@ -5,50 +5,39 @@
#include <windows.h>
#include "MouseInput.hpp"
#include "strsafe.h"
#include <stdio.h>
#include <stdlib.h>
using namespace Microsoft::Console::VirtualTerminal;
#define WIL_SUPPORT_BITOPERATION_PASCAL_NAMES
#include <wil\Common.h>
#ifdef BUILD_ONECORE_INTERACTIVITY
#include "..\..\interactivity\inc\VtApiRedirection.hpp"
#endif
// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx
// "If the high-order bit is 1, the key is down; otherwise, it is up."
#define KEY_PRESSED 0x8000
static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
// Alternate scroll sequences
#define CURSOR_UP_SEQUENCE (L"\x1b[A")
#define CURSOR_DOWN_SEQUENCE (L"\x1b[B")
#define CCH_CURSOR_SEQUENCES (3)
static constexpr std::wstring_view CursorUpSequence{ L"\x1b[A" };
static constexpr std::wstring_view CursorDownSequence{ L"\x1b[B" };
MouseInput::MouseInput(const WriteInputEvents pfnWriteEvents) :
MouseInput::MouseInput(const WriteInputEvents pfnWriteEvents) noexcept :
_pfnWriteEvents(pfnWriteEvents),
_coordLastPos{ -1, -1 },
_lastPos{ -1, -1 },
_lastButton{ 0 }
{
}
MouseInput::~MouseInput()
{
}
// Routine Description:
// - Determines if the input windows message code describes a button event
// (left, middle, right button and any of up, down or double click)
// Also returns true for wheel events, which are buttons in *nix terminals
// Parameters:
// - uiButton - the message to decode.
// - button - the message to decode.
// Return value:
// - true iff uiButton is a button message to translate
bool MouseInput::s_IsButtonMsg(const unsigned int uiButton)
// - true iff button is a button message to translate
static constexpr bool _isButtonMsg(const unsigned int button) noexcept
{
bool fIsButton = false;
switch (uiButton)
bool isButton = false;
switch (button)
{
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
@ -61,34 +50,34 @@ bool MouseInput::s_IsButtonMsg(const unsigned int uiButton)
case WM_MBUTTONDBLCLK:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
fIsButton = true;
isButton = true;
break;
}
return fIsButton;
return isButton;
}
// Routine Description:
// - Determines if the input windows message code describes a hover event
// Parameters:
// - uiButtonCode - the message to decode.
// - buttonCode - the message to decode.
// Return value:
// - true iff uiButtonCode is a hover enent to translate
bool MouseInput::s_IsHoverMsg(const unsigned int uiButtonCode)
// - true iff buttonCode is a hover enent to translate
static constexpr bool _isHoverMsg(const unsigned int buttonCode) noexcept
{
return uiButtonCode == WM_MOUSEMOVE;
return buttonCode == WM_MOUSEMOVE;
}
// Routine Description:
// - Determines if the input windows message code describes a button press
// (either down or doubleclick)
// Parameters:
// - uiButton - the message to decode.
// - button - the message to decode.
// Return value:
// - true iff uiButton is a button down event
bool MouseInput::s_IsButtonDown(const unsigned int uiButton)
// - true iff button is a button down event
static constexpr bool _isButtonDown(const unsigned int button) noexcept
{
bool fIsButtonDown = false;
switch (uiButton)
bool isButtonDown = false;
switch (button)
{
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
@ -98,10 +87,10 @@ bool MouseInput::s_IsButtonDown(const unsigned int uiButton)
case WM_MBUTTONDBLCLK:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
fIsButtonDown = true;
isButtonDown = true;
break;
}
return fIsButtonDown;
return isButtonDown;
}
// Routine Description:
@ -127,51 +116,54 @@ bool MouseInput::s_IsButtonDown(const unsigned int uiButton)
// so wheel up? is 64, and wheel down? is 65.
//
// Parameters:
// - uiButton - the message to decode.
// - button - the message to decode.
// - isHover - whether or not this is a hover event
// - modifierKeyState - alt/ctrl/shift key hold state
// - delta - scroll wheel delta
// Return value:
// - the int representing the equivalent X button encoding.
int MouseInput::s_WindowsButtonToXEncoding(const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta)
static constexpr int _windowsButtonToXEncoding(const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta) noexcept
{
int iXValue = 0;
switch (uiButton)
int xvalue = 0;
switch (button)
{
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
iXValue = 0;
xvalue = 0;
break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
iXValue = 3;
xvalue = 3;
break;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
iXValue = 2;
xvalue = 2;
break;
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
iXValue = 1;
xvalue = 1;
break;
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
iXValue = sWheelDelta > 0 ? 0x40 : 0x41;
xvalue = delta > 0 ? 0x40 : 0x41;
}
if (fIsHover)
if (isHover)
{
iXValue += 0x20;
xvalue += 0x20;
}
// Shift will never pass through to us, because shift is used by the host to skip VT mouse and use the default handler.
// TODO: MSFT:8804719 Add an option to disable/remap shift as a bypass for VT mousemode handling
// iXValue += (sModifierKeystate & MK_SHIFT) ? 0x04 : 0x00;
iXValue += (sModifierKeystate & MK_CONTROL) ? 0x08 : 0x00;
// xvalue += (modifierKeyState & MK_SHIFT) ? 0x04 : 0x00;
xvalue += (modifierKeyState & MK_CONTROL) ? 0x08 : 0x00;
// Unfortunately, we don't get meta/alt as a part of mouse events. Only Ctrl and Shift.
// iXValue += (sModifierKeystate & MK_META) ? 0x10 : 0x00;
// xvalue += (modifierKeyState & MK_META) ? 0x10 : 0x00;
return iXValue;
return xvalue;
}
// Routine Description:
@ -181,52 +173,75 @@ int MouseInput::s_WindowsButtonToXEncoding(const unsigned int uiButton,
// 3 is reserved for mouse hovers with _no_ buttons pressed.
// See MSFT:19461988 and https://github.com/Microsoft/console/issues/296
// Parameters:
// - uiButton - the message to decode.
// - button - the message to decode.
// Return value:
// - the int representing the equivalent X button encoding.
int MouseInput::s_WindowsButtonToSGREncoding(const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta)
static constexpr int _windowsButtonToSGREncoding(const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta) noexcept
{
int iXValue = 0;
switch (uiButton)
int xvalue = 0;
switch (button)
{
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
iXValue = 0;
xvalue = 0;
break;
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
iXValue = 2;
xvalue = 2;
break;
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
iXValue = 1;
xvalue = 1;
break;
case WM_MOUSEMOVE:
iXValue = 3;
xvalue = 3;
break;
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
iXValue = sWheelDelta > 0 ? 0x40 : 0x41;
xvalue = delta > 0 ? 0x40 : 0x41;
}
if (fIsHover)
if (isHover)
{
iXValue += 0x20;
xvalue += 0x20;
}
// Shift will never pass through to us, because shift is used by the host to skip VT mouse and use the default handler.
// TODO: MSFT:8804719 Add an option to disable/remap shift as a bypass for VT mousemode handling
// iXValue += (sModifierKeystate & MK_SHIFT) ? 0x04 : 0x00;
iXValue += (sModifierKeystate & MK_CONTROL) ? 0x08 : 0x00;
// xvalue += (modifierKeyState & MK_SHIFT) ? 0x04 : 0x00;
xvalue += (modifierKeyState & MK_CONTROL) ? 0x08 : 0x00;
// Unfortunately, we don't get meta/alt as a part of mouse events. Only Ctrl and Shift.
// iXValue += (sModifierKeystate & MK_META) ? 0x10 : 0x00;
// xvalue += (modifierKeyState & MK_META) ? 0x10 : 0x00;
return iXValue;
return xvalue;
}
// Routine Description:
// - Translates the given coord from windows coordinate space (origin=0,0) to VT space (origin=1,1)
// Parameters:
// - coordWinCoordinate - the coordinate to translate
// Return value:
// - the translated coordinate.
static constexpr COORD _winToVTCoord(const COORD coordWinCoordinate) noexcept
{
return { coordWinCoordinate.X + 1, coordWinCoordinate.Y + 1 };
}
// Routine Description:
// - Encodes the given value as a default (or utf-8) encoding value.
// 32 is added so that the value 0 can be emitted as the printable characher ' '.
// Parameters:
// - sCoordinateValue - the value to encode.
// Return value:
// - the encoded value.
static constexpr short _encodeDefaultCoordinate(const short sCoordinateValue) noexcept
{
return sCoordinateValue + 32;
}
// Routine Description:
@ -234,185 +249,161 @@ int MouseInput::s_WindowsButtonToSGREncoding(const unsigned int uiButton,
// If the event should be transmitted in the selected mouse mode, then we'll try and
// encode the event according to the rules of the selected ExtendedMode, and insert those characters into the input buffer.
// Parameters:
// - coordMousePosition - The windows coordinates (top,left = 0,0) of the mouse event
// - uiButton - the message to decode.
// - sModifierKeystate - the modifier keys pressed with this button
// - sWheelDelta - the amount that the scroll wheel changed (should be 0 unless uiButton is a WM_MOUSE*WHEEL)
// - position - The windows coordinates (top,left = 0,0) of the mouse event
// - button - the message to decode.
// - modifierKeyState - the modifier keys pressed with this button
// - delta - the amount that the scroll wheel changed (should be 0 unless button is a WM_MOUSE*WHEEL)
// Return value:
// - true if the event was handled and we should stop event propagation to the default window handler.
bool MouseInput::HandleMouse(const COORD coordMousePosition,
const unsigned int uiButton,
const short sModifierKeystate,
const short sWheelDelta)
bool MouseInput::HandleMouse(const COORD position,
const unsigned int button,
const short modifierKeyState,
const short delta)
{
bool fSuccess = false;
if (_ShouldSendAlternateScroll(uiButton, sWheelDelta))
bool success = false;
if (_ShouldSendAlternateScroll(button, delta))
{
fSuccess = _SendAlternateScroll(sWheelDelta);
success = _SendAlternateScroll(delta);
}
else
{
fSuccess = (_TrackingMode != TrackingMode::None);
if (fSuccess)
success = (_trackingMode != TrackingMode::None);
if (success)
{
// fIsHover is only true for WM_MOUSEMOVE events
const bool fIsHover = s_IsHoverMsg(uiButton);
const bool fIsButton = s_IsButtonMsg(uiButton);
// isHover is only true for WM_MOUSEMOVE events
const bool isHover = _isHoverMsg(button);
const bool isButton = _isButtonMsg(button);
const bool fSameCoord = (coordMousePosition.X == _coordLastPos.X) &&
(coordMousePosition.Y == _coordLastPos.Y) &&
(_lastButton == uiButton);
const bool sameCoord = (position.X == _lastPos.X) &&
(position.Y == _lastPos.Y) &&
(_lastButton == button);
// If we have a WM_MOUSEMOVE, we need to know if any of the mouse
// buttons are actually pressed. If they are,
// s_GetPressedButton will return the first pressed mouse button.
// If it returns WM_LBUTTONUP, then we can assume that the mouse
// moved without a button being pressed.
const unsigned int uiRealButton = fIsHover ? s_GetPressedButton() : uiButton;
const unsigned int realButton = isHover ? s_GetPressedButton() : button;
// In default mode, only button presses/releases are sent
// In ButtonEvent mode, changing coord hovers WITH A BUTTON PRESSED
// (WM_LBUTTONUP is our sentinel that no button was pressed) are also sent.
// In AnyEvent, all coord change hovers are sent
const bool physicalButtonPressed = uiRealButton != WM_LBUTTONUP;
const bool physicalButtonPressed = realButton != WM_LBUTTONUP;
fSuccess = (fIsButton && _TrackingMode != TrackingMode::None) ||
(fIsHover && _TrackingMode == TrackingMode::ButtonEvent && ((!fSameCoord) && (physicalButtonPressed))) ||
(fIsHover && _TrackingMode == TrackingMode::AnyEvent && !fSameCoord);
if (fSuccess)
success = (isButton && _trackingMode != TrackingMode::None) ||
(isHover && _trackingMode == TrackingMode::ButtonEvent && ((!sameCoord) && (physicalButtonPressed))) ||
(isHover && _trackingMode == TrackingMode::AnyEvent && !sameCoord);
if (success)
{
wchar_t* pwchSequence = nullptr;
size_t cchSequenceLength = 0;
switch (_ExtendedMode)
std::wstring sequence;
switch (_extendedMode)
{
case ExtendedMode::None:
fSuccess = _GenerateDefaultSequence(coordMousePosition,
uiRealButton,
fIsHover,
sModifierKeystate,
sWheelDelta,
&pwchSequence,
&cchSequenceLength);
sequence = _GenerateDefaultSequence(position,
realButton,
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Utf8:
fSuccess = _GenerateUtf8Sequence(coordMousePosition,
uiRealButton,
fIsHover,
sModifierKeystate,
sWheelDelta,
&pwchSequence,
&cchSequenceLength);
sequence = _GenerateUtf8Sequence(position,
realButton,
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Sgr:
// For SGR encoding, if no physical buttons were pressed,
// then we want to handle hovers with WM_MOUSEMOVE.
// However, if we're dragging (WM_MOUSEMOVE with a button pressed),
// then use that pressed button instead.
fSuccess = _GenerateSGRSequence(coordMousePosition,
physicalButtonPressed ? uiRealButton : uiButton,
s_IsButtonDown(uiRealButton), // Use uiRealButton here, to properly get the up/down state
fIsHover,
sModifierKeystate,
sWheelDelta,
&pwchSequence,
&cchSequenceLength);
sequence = _GenerateSGRSequence(position,
physicalButtonPressed ? realButton : button,
_isButtonDown(realButton), // Use realButton here, to properly get the up/down state
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Urxvt:
default:
fSuccess = false;
success = false;
break;
}
if (fSuccess)
success = !sequence.empty();
if (success)
{
_SendInputSequence(pwchSequence, cchSequenceLength);
delete[] pwchSequence;
fSuccess = true;
_SendInputSequence(sequence);
success = true;
}
if (_TrackingMode == TrackingMode::ButtonEvent || _TrackingMode == TrackingMode::AnyEvent)
if (_trackingMode == TrackingMode::ButtonEvent || _trackingMode == TrackingMode::AnyEvent)
{
_coordLastPos.X = coordMousePosition.X;
_coordLastPos.Y = coordMousePosition.Y;
_lastButton = uiButton;
_lastPos.X = position.X;
_lastPos.Y = position.Y;
_lastButton = button;
}
}
}
}
return fSuccess;
return success;
}
// Routine Description:
// - Generates a sequence encoding the mouse event according to the default scheme.
// see http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
// Parameters:
// - coordMousePosition - The windows coordinates (top,left = 0,0) of the mouse event
// - uiButton - the message to decode.
// - fIsHover - true if the sequence is generated in response to a mouse hover
// - sModifierKeystate - the modifier keys pressed with this button
// - sWheelDelta - the amount that the scroll wheel changed (should be 0 unless uiButton is a WM_MOUSE*WHEEL)
// - ppwchSequence - On success, where to put the pointer to the generated sequence
// - pcchLength - On success, where to put the length of the generated sequence
// - position - The windows coordinates (top,left = 0,0) of the mouse event
// - button - the message to decode.
// - isHover - true if the sequence is generated in response to a mouse hover
// - modifierKeyState - the modifier keys pressed with this button
// - delta - the amount that the scroll wheel changed (should be 0 unless button is a WM_MOUSE*WHEEL)
// Return value:
// - true if we were able to successfully generate a sequence.
// On success, caller is responsible for delete[]ing *ppwchSequence.
bool MouseInput::_GenerateDefaultSequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const
// - The generated sequence. Will be empty if we couldn't generate.
std::wstring MouseInput::_GenerateDefaultSequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta)
{
bool fSuccess = false;
// In the default, non-extended encoding scheme, coordinates above 94 shouldn't be supported,
// because (95+32+1)=128, which is not an ASCII character.
// There are more details in _GenerateUtf8Sequence, but basically, we can't put anything above x80 into the input
// stream without bash.exe trying to convert it into utf8, and generating extra bytes in the process.
if (coordMousePosition.X <= MouseInput::s_MaxDefaultCoordinate && coordMousePosition.Y <= MouseInput::s_MaxDefaultCoordinate)
if (position.X <= MouseInput::s_MaxDefaultCoordinate && position.Y <= MouseInput::s_MaxDefaultCoordinate)
{
const COORD coordVTCoords = s_WinToVTCoord(coordMousePosition);
const short sEncodedX = s_EncodeDefaultCoordinate(coordVTCoords.X);
const short sEncodedY = s_EncodeDefaultCoordinate(coordVTCoords.Y);
wchar_t* pwchFormat = new (std::nothrow) wchar_t[7]{ L"\x1b[Mbxy" };
if (pwchFormat != nullptr)
{
pwchFormat[3] = ' ' + (short)s_WindowsButtonToXEncoding(uiButton, fIsHover, sModifierKeystate, sWheelDelta);
pwchFormat[4] = sEncodedX;
pwchFormat[5] = sEncodedY;
const COORD vtCoords = _winToVTCoord(position);
const short encodedX = _encodeDefaultCoordinate(vtCoords.X);
const short encodedY = _encodeDefaultCoordinate(vtCoords.Y);
*ppwchSequence = pwchFormat;
*pcchLength = 7;
fSuccess = true;
}
std::wstring format{ L"\x1b[Mbxy" };
format.at(3) = ' ' + gsl::narrow_cast<short>(_windowsButtonToXEncoding(button, isHover, modifierKeyState, delta));
format.at(4) = encodedX;
format.at(5) = encodedY;
return format;
}
return fSuccess;
return {};
}
// Routine Description:
// - Generates a sequence encoding the mouse event according to the UTF8 Extended scheme.
// see http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Extended-coordinates
// Parameters:
// - coordMousePosition - The windows coordinates (top,left = 0,0) of the mouse event
// - uiButton - the message to decode.
// - fIsHover - true if the sequence is generated in response to a mouse hover
// - sModifierKeystate - the modifier keys pressed with this button
// - sWheelDelta - the amount that the scroll wheel changed (should be 0 unless uiButton is a WM_MOUSE*WHEEL)
// - ppwchSequence - On success, where to put the pointer to the generated sequence
// - pcchLength - On success, where to put the length of the generated sequence
// - position - The windows coordinates (top,left = 0,0) of the mouse event
// - button - the message to decode.
// - isHover - true if the sequence is generated in response to a mouse hover
// - modifierKeyState - the modifier keys pressed with this button
// - delta - the amount that the scroll wheel changed (should be 0 unless button is a WM_MOUSE*WHEEL)
// Return value:
// - true if we were able to successfully generate a sequence.
// On success, caller is responsible for delete[]ing *ppwchSequence.
bool MouseInput::_GenerateUtf8Sequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const
// - The generated sequence. Will be empty if we couldn't generate.
std::wstring MouseInput::_GenerateUtf8Sequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta)
{
bool fSuccess = false;
// So we have some complications here.
// The windows input stream is typically encoded as UTF16.
// Bash.exe knows this, and converts the utf16 input, character by character, into utf8, to send to wsl.
@ -427,90 +418,51 @@ bool MouseInput::_GenerateUtf8Sequence(const COORD coordMousePosition,
// So bash would also need to change, but how could it tell the difference between them? no real good way.
// I'm going to emit a utf16 encoded value for now. Besides, if a windows program really wants it, just use the SGR mode, which is unambiguous.
// TODO: Followup once the UTF-8 input stack is ready, MSFT:8509613
if (coordMousePosition.X <= (SHORT_MAX - 33) && coordMousePosition.Y <= (SHORT_MAX - 33))
if (position.X <= (SHORT_MAX - 33) && position.Y <= (SHORT_MAX - 33))
{
const COORD coordVTCoords = s_WinToVTCoord(coordMousePosition);
const short sEncodedX = s_EncodeDefaultCoordinate(coordVTCoords.X);
const short sEncodedY = s_EncodeDefaultCoordinate(coordVTCoords.Y);
wchar_t* pwchFormat = new (std::nothrow) wchar_t[7]{ L"\x1b[Mbxy" };
if (pwchFormat != nullptr)
{
// The short cast is safe because we know s_WindowsButtonToXEncoding never returns more than xff
pwchFormat[3] = ' ' + (short)s_WindowsButtonToXEncoding(uiButton, fIsHover, sModifierKeystate, sWheelDelta);
pwchFormat[4] = sEncodedX;
pwchFormat[5] = sEncodedY;
*ppwchSequence = pwchFormat;
*pcchLength = 7;
fSuccess = true;
}
const COORD vtCoords = _winToVTCoord(position);
const short encodedX = _encodeDefaultCoordinate(vtCoords.X);
const short encodedY = _encodeDefaultCoordinate(vtCoords.Y);
std::wstring format{ L"\x1b[Mbxy" };
// The short cast is safe because we know s_WindowsButtonToXEncoding never returns more than xff
format.at(3) = ' ' + gsl::narrow_cast<short>(_windowsButtonToXEncoding(button, isHover, modifierKeyState, delta));
format.at(4) = encodedX;
format.at(5) = encodedY;
return format;
}
return fSuccess;
return {};
}
// Routine Description:
// - Generates a sequence encoding the mouse event according to the SGR Extended scheme.
// see http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Extended-coordinates
// Parameters:
// - coordMousePosition - The windows coordinates (top,left = 0,0) of the mouse event
// - uiButton - the message to decode. WM_MOUSERMOVE is used for mouse hovers with no buttons pressed.
// - position - The windows coordinates (top,left = 0,0) of the mouse event
// - button - the message to decode. WM_MOUSERMOVE is used for mouse hovers with no buttons pressed.
// - isDown - true iff a mouse button was pressed.
// - fIsHover - true if the sequence is generated in response to a mouse hover
// - sModifierKeystate - the modifier keys pressed with this button
// - sWheelDelta - the amount that the scroll wheel changed (should be 0 unless uiButton is a WM_MOUSE*WHEEL)
// - isHover - true if the sequence is generated in response to a mouse hover
// - modifierKeyState - the modifier keys pressed with this button
// - delta - the amount that the scroll wheel changed (should be 0 unless button is a WM_MOUSE*WHEEL)
// - ppwchSequence - On success, where to put the pointer to the generated sequence
// - pcchLength - On success, where to put the length of the generated sequence
// Return value:
// - true if we were able to successfully generate a sequence.
// On success, caller is responsible for delete[]ing *ppwchSequence.
bool MouseInput::_GenerateSGRSequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool isDown,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const
std::wstring MouseInput::_GenerateSGRSequence(const COORD position,
const unsigned int button,
const bool isDown,
const bool isHover,
const short modifierKeyState,
const short delta)
{
// Format for SGR events is:
// "\x1b[<%d;%d;%d;%c", xButton, x+1, y+1, fButtonDown? 'M' : 'm'
bool fSuccess = false;
const int iXButton = s_WindowsButtonToSGREncoding(uiButton, fIsHover, sModifierKeystate, sWheelDelta);
const int xbutton = _windowsButtonToSGREncoding(button, isHover, modifierKeyState, delta);
#pragma warning(push)
#pragma warning(disable : 4996)
// Disable 4996 - The _s version of _snprintf doesn't return the cch if the buffer is null, and we need the cch
#pragma prefast(suppress : 28719, "Using the output of _snwprintf to determine cch. _snwprintf_s used below.")
int iNeededChars = _snwprintf(nullptr, 0, L"\x1b[<%d;%d;%d%c", iXButton, coordMousePosition.X + 1, coordMousePosition.Y + 1, isDown ? L'M' : L'm');
auto format = wil::str_printf<std::wstring>(L"\x1b[<%d;%d;%d%c", xbutton, position.X + 1, position.Y + 1, isDown ? L'M' : L'm');
#pragma warning(pop)
iNeededChars += 1; // for null
wchar_t* pwchFormat = new (std::nothrow) wchar_t[iNeededChars];
if (pwchFormat != nullptr)
{
int iTakenChars = _snwprintf_s(pwchFormat,
iNeededChars,
iNeededChars,
L"\x1b[<%d;%d;%d%c",
iXButton,
coordMousePosition.X + 1,
coordMousePosition.Y + 1,
isDown ? L'M' : L'm');
if (iTakenChars == iNeededChars - 1) // again, adjust for null
{
*ppwchSequence = pwchFormat;
*pcchLength = iTakenChars;
fSuccess = true;
}
else
{
delete[] pwchFormat;
}
}
return fSuccess;
return format;
}
// Routine Description:
@ -519,12 +471,12 @@ bool MouseInput::_GenerateSGRSequence(const COORD coordMousePosition,
// typically UTF-16 encoded, it emits a UTF-16 stream.
// Does NOT enable or disable mouse mode by itself. This matches the behavior I found in Ubuntu terminals.
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::SetUtf8ExtendedMode(const bool fEnable)
void MouseInput::SetUtf8ExtendedMode(const bool enable) noexcept
{
_ExtendedMode = fEnable ? ExtendedMode::Utf8 : ExtendedMode::None;
_extendedMode = enable ? ExtendedMode::Utf8 : ExtendedMode::None;
}
// Routine Description:
@ -533,25 +485,25 @@ void MouseInput::SetUtf8ExtendedMode(const bool fEnable)
// eg, x,y=203,504 -> "^[[<B;203;504M". This way, applications don't need to worry about character encoding.
// Does NOT enable or disable mouse mode by itself. This matches the behavior I found in Ubuntu terminals.
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::SetSGRExtendedMode(const bool fEnable)
void MouseInput::SetSGRExtendedMode(const bool enable) noexcept
{
_ExtendedMode = fEnable ? ExtendedMode::Sgr : ExtendedMode::None;
_extendedMode = enable ? ExtendedMode::Sgr : ExtendedMode::None;
}
// Routine Description:
// - Either enables or disables mouse mode handling. Leaves the extended mode alone,
// so if we disable then re-enable mouse mode without toggling an extended mode, the mode will persist.
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::EnableDefaultTracking(const bool fEnable)
void MouseInput::EnableDefaultTracking(const bool enable) noexcept
{
_TrackingMode = fEnable ? TrackingMode::Default : TrackingMode::None;
_coordLastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_trackingMode = enable ? TrackingMode::Default : TrackingMode::None;
_lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_lastButton = 0;
}
@ -561,13 +513,13 @@ void MouseInput::EnableDefaultTracking(const bool fEnable)
// Leaves the extended mode alone, so if we disable then re-enable mouse mode
// without toggling an extended mode, the mode will persist.
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::EnableButtonEventTracking(const bool fEnable)
void MouseInput::EnableButtonEventTracking(const bool enable) noexcept
{
_TrackingMode = fEnable ? TrackingMode::ButtonEvent : TrackingMode::None;
_coordLastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_trackingMode = enable ? TrackingMode::ButtonEvent : TrackingMode::None;
_lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_lastButton = 0;
}
@ -577,13 +529,13 @@ void MouseInput::EnableButtonEventTracking(const bool fEnable)
// Leaves the extended mode alone, so if we disable then re-enable mouse mode
// without toggling an extended mode, the mode will persist.
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::EnableAnyEventTracking(const bool fEnable)
void MouseInput::EnableAnyEventTracking(const bool enable) noexcept
{
_TrackingMode = fEnable ? TrackingMode::AnyEvent : TrackingMode::None;
_coordLastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_trackingMode = enable ? TrackingMode::AnyEvent : TrackingMode::None;
_lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_lastButton = 0;
}
@ -591,23 +543,19 @@ void MouseInput::EnableAnyEventTracking(const bool fEnable)
// - Sends the given sequence into the input callback specified by _pfnWriteEvents.
// Typically, this inserts the characters into the input buffer as KeyDown KEY_EVENTs.
// Parameters:
// - pwszSequence - sequence to send to _pfnWriteEvents
// - cchLength - the length of pwszSequence
// - sequence - sequence to send to _pfnWriteEvents
// Return value:
// <none>
void MouseInput::_SendInputSequence(_In_reads_(cchLength) const wchar_t* const pwszSequence,
const size_t cchLength) const
void MouseInput::_SendInputSequence(const std::wstring_view sequence) const noexcept
{
size_t cch = 0;
// + 1 to max sequence length for null terminator count which is required by StringCchLengthW
if (SUCCEEDED(StringCchLengthW(pwszSequence, cchLength + 1, &cch)) && cch > 0 && cch < DWORD_MAX)
if (!sequence.empty())
{
std::deque<std::unique_ptr<IInputEvent>> events;
try
{
for (size_t i = 0; i < cch; ++i)
for (const auto& wch : sequence)
{
events.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, pwszSequence[i], 0));
events.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, wch, 0));
}
_pfnWriteEvents(events);
@ -619,63 +567,40 @@ void MouseInput::_SendInputSequence(_In_reads_(cchLength) const wchar_t* const p
}
}
// Routine Description:
// - Translates the given coord from windows coordinate space (origin=0,0) to VT space (origin=1,1)
// Parameters:
// - coordWinCoordinate - the coordinate to translate
// Return value:
// - the translated coordinate.
COORD MouseInput::s_WinToVTCoord(const COORD coordWinCoordinate)
{
return { coordWinCoordinate.X + 1, coordWinCoordinate.Y + 1 };
}
// Routine Description:
// - Encodes the given value as a default (or utf-8) encoding value.
// 32 is added so that the value 0 can be emitted as the printable characher ' '.
// Parameters:
// - sCoordinateValue - the value to encode.
// Return value:
// - the encoded value.
short MouseInput::s_EncodeDefaultCoordinate(const short sCoordinateValue)
{
return sCoordinateValue + 32;
}
// Routine Description:
// - Retrieves which mouse button is currently pressed. This is needed because
// MOUSEMOVE events do not also tell us if any mouse buttons are pressed during the move.
// Parameters:
// <none>
// Return value:
// - a uiButton corresponding to any pressed mouse buttons, else WM_LBUTTONUP if none are pressed.
unsigned int MouseInput::s_GetPressedButton()
// - a button corresponding to any pressed mouse buttons, else WM_LBUTTONUP if none are pressed.
unsigned int MouseInput::s_GetPressedButton() noexcept
{
unsigned int uiButton = WM_LBUTTONUP; // Will be treated as a release, or no button pressed.
if (WI_IsFlagSet(GetKeyState(VK_LBUTTON), KEY_PRESSED))
unsigned int button = WM_LBUTTONUP; // Will be treated as a release, or no button pressed.
if (WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed))
{
uiButton = WM_LBUTTONDOWN;
button = WM_LBUTTONDOWN;
}
else if (WI_IsFlagSet(GetKeyState(VK_MBUTTON), KEY_PRESSED))
else if (WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed))
{
uiButton = WM_MBUTTONDOWN;
button = WM_MBUTTONDOWN;
}
else if (WI_IsFlagSet(GetKeyState(VK_RBUTTON), KEY_PRESSED))
else if (WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed))
{
uiButton = WM_RBUTTONDOWN;
button = WM_RBUTTONDOWN;
}
return uiButton;
return button;
}
// Routine Description:
// - Enables alternate scroll mode. This sends Cursor Up/down sequences when in the alternate buffer
// Parameters:
// - fEnable - either enable or disable.
// - enable - either enable or disable.
// Return value:
// <none>
void MouseInput::EnableAlternateScroll(const bool fEnable)
void MouseInput::EnableAlternateScroll(const bool enable) noexcept
{
_fAlternateScroll = fEnable;
_alternateScroll = enable;
}
// Routine Description:
@ -684,9 +609,9 @@ void MouseInput::EnableAlternateScroll(const bool fEnable)
// <none>
// Return value:
// <none>
void MouseInput::UseAlternateScreenBuffer()
void MouseInput::UseAlternateScreenBuffer() noexcept
{
_fInAlternateBuffer = true;
_inAlternateBuffer = true;
}
// Routine Description:
@ -695,37 +620,42 @@ void MouseInput::UseAlternateScreenBuffer()
// <none>
// Return value:
// <none>
void MouseInput::UseMainScreenBuffer()
void MouseInput::UseMainScreenBuffer() noexcept
{
_fInAlternateBuffer = false;
_inAlternateBuffer = false;
}
// Routine Description:
// - Returns true if we should translate the input event (uiButton, sScrollDelta)
// - Returns true if we should translate the input event (button, sScrollDelta)
// into an alternate scroll event instead of the default scroll event,
// dependiong on if alternate scroll mode is enabled and we're in the alternate buffer.
// Parameters:
// - uiButton: The mouse event code of the input event
// - sScrollDelta: The scroll wheel delta of the input event
// - button: The mouse event code of the input event
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the alternate buffer is active and alternate scroll mode is enabled and the event is a mouse wheel event.
bool MouseInput::_ShouldSendAlternateScroll(_In_ unsigned int uiButton, _In_ short sScrollDelta) const
bool MouseInput::_ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept
{
return _fInAlternateBuffer &&
_fAlternateScroll &&
(uiButton == WM_MOUSEWHEEL || uiButton == WM_MOUSEHWHEEL) && sScrollDelta != 0;
return _inAlternateBuffer &&
_alternateScroll &&
(button == WM_MOUSEWHEEL || button == WM_MOUSEHWHEEL) && delta != 0;
}
// Routine Description:
// - Sends a sequence to the input coresponding to cursor up / down depending on the sScrollDelta.
// Parameters:
// - sScrollDelta: The scroll wheel delta of the input event
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the input sequence was sent successfully.
bool MouseInput::_SendAlternateScroll(_In_ short sScrollDelta) const
bool MouseInput::_SendAlternateScroll(const short delta) const noexcept
{
const wchar_t* const pwchSequence = sScrollDelta > 0 ? CURSOR_UP_SEQUENCE : CURSOR_DOWN_SEQUENCE;
_SendInputSequence(pwchSequence, CCH_CURSOR_SEQUENCES);
if (delta > 0)
{
_SendInputSequence(CursorUpSequence);
}
else
{
_SendInputSequence(CursorDownSequence);
}
return true;
}

View File

@ -26,24 +26,23 @@ namespace Microsoft::Console::VirtualTerminal
class MouseInput sealed
{
public:
MouseInput(const WriteInputEvents pfnWriteEvents);
~MouseInput();
MouseInput(const WriteInputEvents pfnWriteEvents) noexcept;
bool HandleMouse(const COORD coordMousePosition,
const unsigned int uiButton,
const short sModifierKeystate,
const short sWheelDelta);
bool HandleMouse(const COORD position,
const unsigned int button,
const short modifierKeyState,
const short delta);
void SetUtf8ExtendedMode(const bool fEnable);
void SetSGRExtendedMode(const bool fEnable);
void SetUtf8ExtendedMode(const bool enable) noexcept;
void SetSGRExtendedMode(const bool enable) noexcept;
void EnableDefaultTracking(const bool fEnable);
void EnableButtonEventTracking(const bool fEnable);
void EnableAnyEventTracking(const bool fEnable);
void EnableDefaultTracking(const bool enable) noexcept;
void EnableButtonEventTracking(const bool enable) noexcept;
void EnableAnyEventTracking(const bool enable) noexcept;
void EnableAlternateScroll(const bool fEnable);
void UseAlternateScreenBuffer();
void UseMainScreenBuffer();
void EnableAlternateScroll(const bool enable) noexcept;
void UseAlternateScreenBuffer() noexcept;
void UseMainScreenBuffer() noexcept;
enum class ExtendedMode : unsigned int
{
@ -66,57 +65,36 @@ namespace Microsoft::Console::VirtualTerminal
WriteInputEvents _pfnWriteEvents;
ExtendedMode _ExtendedMode = ExtendedMode::None;
TrackingMode _TrackingMode = TrackingMode::None;
ExtendedMode _extendedMode = ExtendedMode::None;
TrackingMode _trackingMode = TrackingMode::None;
bool _fAlternateScroll = false;
bool _fInAlternateBuffer = false;
bool _alternateScroll = false;
bool _inAlternateBuffer = false;
COORD _coordLastPos;
COORD _lastPos;
unsigned int _lastButton;
void _SendInputSequence(_In_reads_(cchLength) const wchar_t* const pwszSequence, const size_t cchLength) const;
bool _GenerateDefaultSequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const;
bool _GenerateUtf8Sequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const;
bool _GenerateSGRSequence(const COORD coordMousePosition,
const unsigned int uiButton,
const bool isDown,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta,
_Outptr_result_buffer_(*pcchLength) wchar_t** const ppwchSequence,
_Out_ size_t* const pcchLength) const;
void _SendInputSequence(const std::wstring_view sequence) const noexcept;
static std::wstring _GenerateDefaultSequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta);
static std::wstring _GenerateUtf8Sequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta);
static std::wstring _GenerateSGRSequence(const COORD position,
const unsigned int button,
const bool isDown,
const bool isHover,
const short modifierKeyState,
const short delta);
bool _ShouldSendAlternateScroll(_In_ unsigned int uiButton, _In_ short sScrollDelta) const;
bool _SendAlternateScroll(_In_ short sScrollDelta) const;
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept;
bool _SendAlternateScroll(const short delta) const noexcept;
static int s_WindowsButtonToXEncoding(const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta);
static int s_WindowsButtonToSGREncoding(const unsigned int uiButton,
const bool fIsHover,
const short sModifierKeystate,
const short sWheelDelta);
static bool s_IsButtonDown(const unsigned int uiButton);
static bool s_IsButtonMsg(const unsigned int uiButton);
static bool s_IsHoverMsg(const unsigned int uiButton);
static COORD s_WinToVTCoord(const COORD coordWinCoordinate);
static short s_EncodeDefaultCoordinate(const short sCoordinateValue);
static unsigned int s_GetPressedButton();
static unsigned int s_GetPressedButton() noexcept;
};
}

View File

@ -7,6 +7,7 @@
#include "conGetSet.hpp"
#include "../../types/inc/Viewport.hpp"
#include "../../types/inc/utils.hpp"
#include "../../inc/unicode.hpp"
using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::VirtualTerminal;
@ -17,7 +18,7 @@ using namespace Microsoft::Console::VirtualTerminal;
// - <none>
// Return Value:
// - Always false to signify we didn't handle it.
bool NoOp()
bool NoOp() noexcept
{
return false;
}
@ -159,7 +160,7 @@ bool AdaptDispatch::_CursorMovement(const CursorDirection dir, const size_t dist
break;
}
if (success)
if (success && pModify)
{
// For up and left, we need to subtract the magnitude of the vector to get the new spot. Right/down = add.
// Use safe short subtraction to prevent under/overflow.
@ -345,24 +346,31 @@ bool AdaptDispatch::_CursorMovePosition(const std::optional<size_t> row, const s
}
else
{
rowActual = csbiex.dwCursorPosition.Y - csbiex.srWindow.Top; // remember, in VT speak, this is relative to the viewport. not absolute.
// remember, in VT speak, this is relative to the viewport. not absolute.
SHORT diff = 0;
success = SUCCEEDED(ShortSub(csbiex.dwCursorPosition.Y, csbiex.srWindow.Top, &diff)) && SUCCEEDED(ShortToSizeT(diff, &rowActual));
}
if (column)
if (success)
{
if (column.value() != 0)
if (column)
{
columnActual = column.value() - 1; // In VT, the origin is 1,1. For our array, it's 0,0. So subtract 1.
if (column.value() != 0)
{
columnActual = column.value() - 1; // In VT, the origin is 1,1. For our array, it's 0,0. So subtract 1.
}
else
{
success = false; // The parser should never return 0 (0 maps to 1), so this is a failure condition.
}
}
else
{
success = false; // The parser should never return 0 (0 maps to 1), so this is a failure condition.
// remember, in VT speak, this is relative to the viewport. not absolute.
SHORT diff = 0;
success = SUCCEEDED(ShortSub(csbiex.dwCursorPosition.X, csbiex.srWindow.Left, &diff)) && SUCCEEDED(ShortToSizeT(diff, &columnActual));
}
}
else
{
columnActual = csbiex.dwCursorPosition.X - csbiex.srWindow.Left; // remember, in VT speak, this is relative to the viewport. not absolute.
}
if (success)
{
@ -672,8 +680,8 @@ bool AdaptDispatch::EraseCharacters(const size_t numChars)
{
const COORD startPosition = csbiex.dwCursorPosition;
const size_t remainingSpaces = csbiex.dwSize.X - startPosition.X;
const auto actualRemaining = (remainingSpaces < 0) ? 0 : remainingSpaces;
const SHORT remainingSpaces = csbiex.dwSize.X - startPosition.X;
const size_t actualRemaining = gsl::narrow_cast<size_t>((remainingSpaces < 0) ? 0 : remainingSpaces);
// erase at max the number of characters remaining in the line from the current position.
const auto eraseLength = (numChars <= actualRemaining) ? numChars : actualRemaining;
@ -1212,7 +1220,7 @@ bool AdaptDispatch::DeleteLine(const size_t distance)
// - relativeMode - set to true to use relative addressing, false for absolute addressing.
// Return Value:
// - True if handled successfully. False otherwise.
bool AdaptDispatch::SetOriginMode(const bool relativeMode)
bool AdaptDispatch::SetOriginMode(const bool relativeMode) noexcept
{
_isOriginModeRelative = relativeMode;
return true;
@ -1249,7 +1257,7 @@ bool AdaptDispatch::_DoSetTopBottomScrollingMargins(const size_t topMargin,
success = SUCCEEDED(SizeTToShort(topMargin, &actualTop)) && SUCCEEDED(SizeTToShort(bottomMargin, &actualBottom));
if (success)
{
SHORT screenHeight = csbiex.srWindow.Bottom - csbiex.srWindow.Top;
const SHORT screenHeight = csbiex.srWindow.Bottom - csbiex.srWindow.Top;
// The default top margin is line 1
if (actualTop == 0)
{
@ -1442,7 +1450,7 @@ bool AdaptDispatch::TabClear(const size_t clearType)
// - wchCharset - The character indicating the charset we should switch to.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::DesignateCharset(const wchar_t wchCharset)
bool AdaptDispatch::DesignateCharset(const wchar_t wchCharset) noexcept
{
return _termOutput.DesignateCharset(wchCharset);
}
@ -1504,7 +1512,7 @@ bool AdaptDispatch::SoftReset()
}
if (success)
{
DispatchTypes::GraphicsOptions opt = DispatchTypes::GraphicsOptions::Off;
const auto opt = DispatchTypes::GraphicsOptions::Off;
success = SetGraphicsRendition({ &opt, 1 }); // Normal rendition.
}
if (success)
@ -1586,7 +1594,7 @@ bool AdaptDispatch::ScreenAlignmentPattern()
{
// Fill the screen with the letter E using the default attributes.
auto fillPosition = COORD{ 0, csbiex.srWindow.Top };
auto fillLength = (csbiex.srWindow.Bottom - csbiex.srWindow.Top) * csbiex.dwSize.X;
const auto fillLength = (csbiex.srWindow.Bottom - csbiex.srWindow.Top) * csbiex.dwSize.X;
success = _pConApi->PrivateFillRegion(fillPosition, fillLength, L'E', false);
// Reset the meta/extended attributes (but leave the colors unchanged).
success = success && _pConApi->PrivateSetLegacyAttributes(0, false, false, true);
@ -1691,83 +1699,83 @@ bool AdaptDispatch::_EraseAll()
// Routine Description:
// - Enables or disables support for the DECCOLM escape sequence.
// Arguments:
// - fEnabled - set to true to allow DECCOLM to be used, false to disallow.
// - enabled - set to true to allow DECCOLM to be used, false to disallow.
// Return Value:
// - True if handled successfully. False otherwise.
bool AdaptDispatch::EnableDECCOLMSupport(const bool fEnabled)
bool AdaptDispatch::EnableDECCOLMSupport(const bool enabled) noexcept
{
_isDECCOLMAllowed = fEnabled;
_isDECCOLMAllowed = enabled;
return true;
}
//Routine Description:
// Enable VT200 Mouse Mode - Enables/disables the mouse input handler in default tracking mode.
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableVT200MouseMode(const bool fEnabled)
bool AdaptDispatch::EnableVT200MouseMode(const bool enabled)
{
return _pConApi->PrivateEnableVT200MouseMode(fEnabled);
return _pConApi->PrivateEnableVT200MouseMode(enabled);
}
//Routine Description:
// Enable UTF-8 Extended Encoding - this changes the encoding scheme for sequences
// emitted by the mouse input handler. Does not enable/disable mouse mode on its own.
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool fEnabled)
bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool enabled)
{
return _pConApi->PrivateEnableUTF8ExtendedMouseMode(fEnabled);
return _pConApi->PrivateEnableUTF8ExtendedMouseMode(enabled);
}
//Routine Description:
// Enable SGR Extended Encoding - this changes the encoding scheme for sequences
// emitted by the mouse input handler. Does not enable/disable mouse mode on its own.
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool fEnabled)
bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool enabled)
{
return _pConApi->PrivateEnableSGRExtendedMouseMode(fEnabled);
return _pConApi->PrivateEnableSGRExtendedMouseMode(enabled);
}
//Routine Description:
// Enable Button Event mode - send mouse move events WITH A BUTTON PRESSED to the input.
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableButtonEventMouseMode(const bool fEnabled)
bool AdaptDispatch::EnableButtonEventMouseMode(const bool enabled)
{
return _pConApi->PrivateEnableButtonEventMouseMode(fEnabled);
return _pConApi->PrivateEnableButtonEventMouseMode(enabled);
}
//Routine Description:
// Enable Any Event mode - send all mouse events to the input.
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableAnyEventMouseMode(const bool fEnabled)
bool AdaptDispatch::EnableAnyEventMouseMode(const bool enabled)
{
return _pConApi->PrivateEnableAnyEventMouseMode(fEnabled);
return _pConApi->PrivateEnableAnyEventMouseMode(enabled);
}
//Routine Description:
// Enable Alternate Scroll Mode - When in the Alt Buffer, send CUP and CUD on
// scroll up/down events instead of the usual sequences
//Arguments:
// - fEnabled - true to enable, false to disable.
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableAlternateScroll(const bool fEnabled)
bool AdaptDispatch::EnableAlternateScroll(const bool enabled)
{
return _pConApi->PrivateEnableAlternateScroll(fEnabled);
return _pConApi->PrivateEnableAlternateScroll(enabled);
}
//Routine Description:
@ -1957,7 +1965,7 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy
case DispatchTypes::WindowManipulationType::ResizeWindowInCharacters:
if (parameters.size() == 2)
{
success = DispatchCommon::s_ResizeWindow(*_pConApi, parameters[1], parameters[0]);
success = DispatchCommon::s_ResizeWindow(*_pConApi, til::at(parameters, 1), til::at(parameters, 0));
}
break;
default:

View File

@ -66,7 +66,7 @@ namespace Microsoft::Console::VirtualTerminal
bool SetCursorKeysMode(const bool applicationMode) override; // DECCKM
bool SetKeypadMode(const bool applicationMode) override; // DECKPAM, DECKPNM
bool EnableCursorBlinking(const bool enable) override; // ATT610
bool SetOriginMode(const bool relativeMode) override; // DECOM
bool SetOriginMode(const bool relativeMode) noexcept override; // DECOM
bool SetTopBottomScrollingMargins(const size_t topMargin,
const size_t bottomMargin) override; // DECSTBM
bool ReverseLineFeed() override; // RI
@ -77,11 +77,11 @@ namespace Microsoft::Console::VirtualTerminal
bool ForwardTab(const size_t numTabs) override; // CHT
bool BackwardsTab(const size_t numTabs) override; // CBT
bool TabClear(const size_t clearType) override; // TBC
bool DesignateCharset(const wchar_t wchCharset) override; // DesignateCharset
bool DesignateCharset(const wchar_t wchCharset) noexcept override; // DesignateCharset
bool SoftReset() override; // DECSTR
bool HardReset() override; // RIS
bool ScreenAlignmentPattern() override; // DECALN
bool EnableDECCOLMSupport(const bool enabled) override; // ?40
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
@ -133,8 +133,8 @@ namespace Microsoft::Console::VirtualTerminal
bool _EraseAll();
bool _InsertDeleteHelper(const size_t count, const bool isInsert) const;
bool _ScrollMovement(const ScrollDirection dir, const size_t distance) const;
static void s_DisableAllColors(WORD& attr, const bool isForeground);
static void s_ApplyColors(WORD& attr, const WORD applyThis, const bool isForeground);
static void s_DisableAllColors(WORD& attr, const bool isForeground) noexcept;
static void s_ApplyColors(WORD& attr, const WORD applyThis, const bool isForeground) noexcept;
bool _DoSetTopBottomScrollingMargins(const size_t topMargin,
const size_t bottomMargin);
@ -175,10 +175,5 @@ namespace Microsoft::Console::VirtualTerminal
bool _SetBoldColorHelper(const DispatchTypes::GraphicsOptions option);
bool _SetDefaultColorHelper(const DispatchTypes::GraphicsOptions option);
bool _SetExtendedTextAttributeHelper(const DispatchTypes::GraphicsOptions option);
static bool s_IsRgbColorOption(const DispatchTypes::GraphicsOptions opt);
static bool s_IsBoldColorOption(const DispatchTypes::GraphicsOptions opt) noexcept;
static bool s_IsDefaultColorOption(const DispatchTypes::GraphicsOptions opt) noexcept;
static bool s_IsExtendedTextAttribute(const DispatchTypes::GraphicsOptions opt) noexcept;
};
}

View File

@ -20,7 +20,7 @@ using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
// - isForeground - True if we're modifying the FOREGROUND colors. False if we're doing BACKGROUND.
// Return Value:
// - <none>
void AdaptDispatch::s_DisableAllColors(WORD& attr, const bool isForeground)
void AdaptDispatch::s_DisableAllColors(WORD& attr, const bool isForeground) noexcept
{
if (isForeground)
{
@ -42,8 +42,9 @@ void AdaptDispatch::s_DisableAllColors(WORD& attr, const bool isForeground)
// upon.
// Return Value:
// - <none>
void AdaptDispatch::s_ApplyColors(WORD& attr, const WORD applyThis, const bool isForeground)
void AdaptDispatch::s_ApplyColors(WORD& attr, const WORD applyThis, const bool isForeground) noexcept
{
#pragma warning(suppress : 26496) // SA is wrong. This variable is assigned more than once.
// Copy the new attribute to apply
WORD wNewColors = applyThis;
@ -267,7 +268,7 @@ void AdaptDispatch::_SetGraphicsOptionHelper(const DispatchTypes::GraphicsOption
// These include things such as Underlined, Italics, Blinking, etc.
// Return Value:
// - true if the opt is the indicator for an extended text attribute, false otherwise.
bool AdaptDispatch::s_IsExtendedTextAttribute(const DispatchTypes::GraphicsOptions opt) noexcept
static constexpr bool _isExtendedTextAttribute(const DispatchTypes::GraphicsOptions opt) noexcept
{
// TODO:GH#2916 add support for DoublyUnderlined, Faint(RGBColorOrFaint).
// These two are currently partially implemented as other things:
@ -291,7 +292,7 @@ bool AdaptDispatch::s_IsExtendedTextAttribute(const DispatchTypes::GraphicsOptio
// These are followed by up to 4 more values which compose the entire option.
// Return Value:
// - true if the opt is the indicator for an extended color sequence, false otherwise.
bool AdaptDispatch::s_IsRgbColorOption(const DispatchTypes::GraphicsOptions opt)
static constexpr bool _isRgbColorOption(const DispatchTypes::GraphicsOptions opt) noexcept
{
return opt == DispatchTypes::GraphicsOptions::ForegroundExtended ||
opt == DispatchTypes::GraphicsOptions::BackgroundExtended;
@ -302,7 +303,7 @@ bool AdaptDispatch::s_IsRgbColorOption(const DispatchTypes::GraphicsOptions opt)
// These are followed by up to 4 more values which compose the entire option.
// Return Value:
// - true if the opt is the indicator for an extended color sequence, false otherwise.
bool AdaptDispatch::s_IsBoldColorOption(const DispatchTypes::GraphicsOptions opt) noexcept
static constexpr bool _isBoldColorOption(const DispatchTypes::GraphicsOptions opt) noexcept
{
return opt == DispatchTypes::GraphicsOptions::BoldBright ||
opt == DispatchTypes::GraphicsOptions::UnBold;
@ -313,7 +314,7 @@ bool AdaptDispatch::s_IsBoldColorOption(const DispatchTypes::GraphicsOptions opt
//the default attributes.
// Return Value:
// - true if the opt sets either/or attribute to the defaults, false otherwise.
bool AdaptDispatch::s_IsDefaultColorOption(const DispatchTypes::GraphicsOptions opt) noexcept
static constexpr bool _isDefaultColorOption(const DispatchTypes::GraphicsOptions opt) noexcept
{
return opt == DispatchTypes::GraphicsOptions::Off ||
opt == DispatchTypes::GraphicsOptions::ForegroundDefault ||
@ -344,11 +345,11 @@ bool AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchTyp
{
bool success = false;
optionsConsumed = 1;
if (options.size() >= 2 && s_IsRgbColorOption(options.at(0)))
if (options.size() >= 2 && _isRgbColorOption(til::at(options, 0)))
{
optionsConsumed = 2;
DispatchTypes::GraphicsOptions extendedOpt = options.at(0);
DispatchTypes::GraphicsOptions typeOpt = options.at(1);
const auto extendedOpt = til::at(options, 0);
const auto typeOpt = til::at(options, 1);
if (extendedOpt == DispatchTypes::GraphicsOptions::ForegroundExtended)
{
@ -363,9 +364,9 @@ bool AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchTyp
{
optionsConsumed = 5;
// ensure that each value fits in a byte
unsigned int red = std::min(static_cast<unsigned int>(options.at(2)), 255u);
unsigned int green = std::min(static_cast<unsigned int>(options.at(3)), 255u);
unsigned int blue = std::min(static_cast<unsigned int>(options.at(4)), 255u);
unsigned int red = std::min(static_cast<unsigned int>(til::at(options, 2)), 255u);
unsigned int green = std::min(static_cast<unsigned int>(til::at(options, 3)), 255u);
unsigned int blue = std::min(static_cast<unsigned int>(til::at(options, 4)), 255u);
rgbColor = RGB(red, green, blue);
@ -374,9 +375,9 @@ bool AdaptDispatch::_SetRgbColorsHelper(const std::basic_string_view<DispatchTyp
else if (typeOpt == DispatchTypes::GraphicsOptions::BlinkOrXterm256Index && options.size() >= 3)
{
optionsConsumed = 3;
if (options.at(2) <= 255) // ensure that the provided index is on the table
if (til::at(options, 2) <= 255) // ensure that the provided index is on the table
{
unsigned int tableIndex = options.at(2);
const auto tableIndex = til::at(options, 2);
success = _pConApi->SetConsoleXtermTextAttribute(tableIndex, isForeground);
}
@ -487,22 +488,22 @@ bool AdaptDispatch::SetGraphicsRendition(const std::basic_string_view<DispatchTy
// Run through the graphics options and apply them
for (size_t i = 0; i < options.size(); i++)
{
DispatchTypes::GraphicsOptions opt = options.at(i);
if (s_IsDefaultColorOption(opt))
const auto opt = til::at(options, i);
if (_isDefaultColorOption(opt))
{
success = _SetDefaultColorHelper(opt);
}
else if (s_IsBoldColorOption(opt))
else if (_isBoldColorOption(opt))
{
success = _SetBoldColorHelper(opt);
}
else if (s_IsExtendedTextAttribute(opt))
else if (_isExtendedTextAttribute(opt))
{
success = _SetExtendedTextAttributeHelper(opt);
}
else if (s_IsRgbColorOption(opt))
else if (_isRgbColorOption(opt))
{
COLORREF rgbColor;
COLORREF rgbColor{ 0 };
bool isForeground = true;
size_t optionsConsumed = 0;

View File

@ -6,7 +6,7 @@
<RootNamespace>adapter</RootNamespace>
<ProjectName>TerminalAdapter</ProjectName>
<TargetName>ConTermAdapt</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
@ -48,4 +48,4 @@
</ItemGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
</Project>
</Project>

View File

@ -21,9 +21,6 @@
<ClCompile Include="..\telemetry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\terminalInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\terminalOutput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -36,6 +33,12 @@
<ClCompile Include="..\precomp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\DispatchCommon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\InteractDispatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\MouseInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -56,9 +59,6 @@
<ClInclude Include="..\telemetry.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\terminalInput.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\terminalOutput.hpp">
<Filter>Header Files</Filter>
</ClInclude>
@ -68,5 +68,26 @@
<ClInclude Include="..\MouseInput.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\DispatchCommon.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\IInteractDispatch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\DispatchTypes.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\InteractDispatch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ITermDispatch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\termDispatch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
</Project>

View File

@ -24,72 +24,72 @@ public:
void Print(const wchar_t wchPrintable) override = 0;
void PrintString(const std::wstring_view string) override = 0;
bool CursorUp(const size_t /*distance*/) override { return false; } // CUU
bool CursorDown(const size_t /*distance*/) override { return false; } // CUD
bool CursorForward(const size_t /*distance*/) override { return false; } // CUF
bool CursorBackward(const size_t /*distance*/) override { return false; } // CUB
bool CursorNextLine(const size_t /*distance*/) override { return false; } // CNL
bool CursorPrevLine(const size_t /*distance*/) override { return false; } // CPL
bool CursorHorizontalPositionAbsolute(const size_t /*column*/) override { return false; } // CHA
bool VerticalLinePositionAbsolute(const size_t /*line*/) override { return false; } // VPA
bool CursorPosition(const size_t /*line*/, const size_t /*column*/) override { return false; } // CUP
bool CursorSaveState() override { return false; } // DECSC
bool CursorRestoreState() override { return false; } // DECRC
bool CursorVisibility(const bool /*isVisible*/) override { return false; } // DECTCEM
bool InsertCharacter(const size_t /*count*/) override { return false; } // ICH
bool DeleteCharacter(const size_t /*count*/) override { return false; } // DCH
bool ScrollUp(const size_t /*distance*/) override { return false; } // SU
bool ScrollDown(const size_t /*distance*/) override { return false; } // SD
bool InsertLine(const size_t /*distance*/) override { return false; } // IL
bool DeleteLine(const size_t /*distance*/) override { return false; } // DL
bool SetColumns(const size_t /*columns*/) override { return false; } // DECSCPP, DECCOLM
bool SetCursorKeysMode(const bool /*applicationMode*/) override { return false; } // DECCKM
bool SetKeypadMode(const bool /*applicationMode*/) override { return false; } // DECKPAM, DECKPNM
bool EnableCursorBlinking(const bool /*enable*/) override { return false; } // ATT610
bool SetOriginMode(const bool /*relativeMode*/) override { return false; }; // DECOM
bool SetTopBottomScrollingMargins(const size_t /*topMargin*/, const size_t /*bottomMargin*/) override { return false; } // DECSTBM
bool ReverseLineFeed() override { return false; } // RI
bool SetWindowTitle(std::wstring_view /*title*/) override { return false; } // OscWindowTitle
bool UseAlternateScreenBuffer() override { return false; } // ASBSET
bool UseMainScreenBuffer() override { return false; } // ASBRST
bool HorizontalTabSet() override { return false; } // HTS
bool ForwardTab(const size_t /*numTabs*/) override { return false; } // CHT
bool BackwardsTab(const size_t /*numTabs*/) override { return false; } // CBT
bool TabClear(const size_t /*clearType*/) override { return false; } // TBC
bool EnableDECCOLMSupport(const bool /*enabled*/) override { return false; } // ?40
bool EnableVT200MouseMode(const bool /*enabled*/) override { return false; } // ?1000
bool EnableUTF8ExtendedMouseMode(const bool /*enabled*/) override { return false; } // ?1005
bool EnableSGRExtendedMouseMode(const bool /*enabled*/) override { return false; } // ?1006
bool EnableButtonEventMouseMode(const bool /*enabled*/) override { return false; } // ?1002
bool EnableAnyEventMouseMode(const bool /*enabled*/) override { return false; } // ?1003
bool EnableAlternateScroll(const bool /*enabled*/) override { return false; } // ?1007
bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*color*/) override { return false; } // OSCColorTable
bool SetDefaultForeground(const DWORD /*color*/) override { return false; } // OSCDefaultForeground
bool SetDefaultBackground(const DWORD /*color*/) override { return false; } // OSCDefaultBackground
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
bool CursorBackward(const size_t /*distance*/) noexcept override { return false; } // CUB
bool CursorNextLine(const size_t /*distance*/) noexcept override { return false; } // CNL
bool CursorPrevLine(const size_t /*distance*/) noexcept override { return false; } // CPL
bool CursorHorizontalPositionAbsolute(const size_t /*column*/) noexcept override { return false; } // CHA
bool VerticalLinePositionAbsolute(const size_t /*line*/) noexcept override { return false; } // VPA
bool CursorPosition(const size_t /*line*/, const size_t /*column*/) noexcept override { return false; } // CUP
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
bool SetColumns(const size_t /*columns*/) noexcept override { return false; } // DECSCPP, DECCOLM
bool SetCursorKeysMode(const bool /*applicationMode*/) noexcept override { return false; } // DECCKM
bool SetKeypadMode(const bool /*applicationMode*/) noexcept override { return false; } // DECKPAM, DECKPNM
bool EnableCursorBlinking(const bool /*enable*/) noexcept override { return false; } // ATT610
bool SetOriginMode(const bool /*relativeMode*/) noexcept override { return false; }; // DECOM
bool SetTopBottomScrollingMargins(const size_t /*topMargin*/, const size_t /*bottomMargin*/) noexcept override { return false; } // DECSTBM
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
bool ForwardTab(const size_t /*numTabs*/) noexcept override { return false; } // CHT
bool BackwardsTab(const size_t /*numTabs*/) noexcept override { return false; } // CBT
bool TabClear(const size_t /*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 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*/) override { return false; } // ED
bool EraseInLine(const DispatchTypes::EraseType /* eraseType*/) override { return false; } // EL
bool EraseCharacters(const size_t /*numChars*/) override { return false; } // ECH
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
bool SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> /*options*/) override { return false; } // SGR
bool SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> /*options*/) noexcept override { return false; } // SGR
bool SetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> /*params*/) override { return false; } // DECSET
bool SetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> /*params*/) noexcept override { return false; } // DECSET
bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> /*params*/) override { return false; } // DECRST
bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> /*params*/) noexcept override { return false; } // DECRST
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) override { return false; } // DSR
bool DeviceAttributes() override { return false; } // DA
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) noexcept override { return false; } // DSR
bool DeviceAttributes() noexcept override { return false; } // DA
bool DesignateCharset(const wchar_t /*wchCharset*/) override { return false; } // DesignateCharset
bool DesignateCharset(const wchar_t /*wchCharset*/) noexcept override { return false; } // DesignateCharset
bool SoftReset() override { return false; } // DECSTR
bool HardReset() override { return false; } // RIS
bool ScreenAlignmentPattern() override { return false; } // DECALN
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*/) override { return false; } // DECSCUSR
bool SetCursorColor(const COLORREF /*color*/) override { return false; } // OSCSetCursorColor, OSCResetCursorColor
bool SetCursorStyle(const DispatchTypes::CursorStyle /*cursorStyle*/) noexcept override { return false; } // DECSCUSR
bool SetCursorColor(const COLORREF /*color*/) noexcept override { return false; } // OSCSetCursorColor, OSCResetCursorColor
// DTTERM_WindowManipulation
bool WindowManipulation(const DispatchTypes::WindowManipulationType /*function*/,
const std::basic_string_view<size_t> /*params*/) override { return false; }
const std::basic_string_view<size_t> /*params*/) noexcept override { return false; }
};

View File

@ -8,18 +8,10 @@
using namespace Microsoft::Console::VirtualTerminal;
TerminalOutput::TerminalOutput()
{
}
TerminalOutput::~TerminalOutput()
{
}
// We include a full table so all we have to do is the lookup.
// The tables only ever change the values x20 - x7f, hence why the table starts at \x20
// From http://vt100.net/docs/vt220-rm/table2-4.html
const wchar_t TerminalOutput::s_rgDECSpecialGraphicsTranslations[s_uiNumDisplayCharacters]{
static constexpr std::array<wchar_t, 96> s_decSpecialGraphicsTranslations{
L'\x20',
L'\x21',
L'\x22',
@ -118,13 +110,13 @@ const wchar_t TerminalOutput::s_rgDECSpecialGraphicsTranslations[s_uiNumDisplayC
L'\x7f' // L'\x7f', -> DEL
};
bool TerminalOutput::DesignateCharset(const wchar_t wchNewCharset)
bool TerminalOutput::DesignateCharset(const wchar_t newCharset) noexcept
{
bool result = false;
if (wchNewCharset == DispatchTypes::VTCharacterSets::DEC_LineDrawing ||
wchNewCharset == DispatchTypes::VTCharacterSets::USASCII)
if (newCharset == DispatchTypes::VTCharacterSets::DEC_LineDrawing ||
newCharset == DispatchTypes::VTCharacterSets::USASCII)
{
_wchCurrentCharset = wchNewCharset;
_currentCharset = newCharset;
result = true;
}
return result;
@ -136,37 +128,35 @@ bool TerminalOutput::DesignateCharset(const wchar_t wchNewCharset)
// - <none>
// Return Value:
// - True if the current charset is not USASCII
bool TerminalOutput::NeedToTranslate() const
bool TerminalOutput::NeedToTranslate() const noexcept
{
return _wchCurrentCharset != DispatchTypes::VTCharacterSets::USASCII;
return _currentCharset != DispatchTypes::VTCharacterSets::USASCII;
}
const wchar_t* TerminalOutput::_GetTranslationTable() const
const std::wstring_view TerminalOutput::_GetTranslationTable() const noexcept
{
const wchar_t* pwchTranslation = nullptr;
switch (_wchCurrentCharset)
switch (_currentCharset)
{
case DispatchTypes::VTCharacterSets::DEC_LineDrawing:
pwchTranslation = TerminalOutput::s_rgDECSpecialGraphicsTranslations;
break;
return { s_decSpecialGraphicsTranslations.data(), s_decSpecialGraphicsTranslations.size() };
}
return pwchTranslation;
return {};
}
wchar_t TerminalOutput::TranslateKey(const wchar_t wch) const
wchar_t TerminalOutput::TranslateKey(const wchar_t wch) const noexcept
{
wchar_t wchFound = wch;
if (_wchCurrentCharset == DispatchTypes::VTCharacterSets::USASCII ||
if (_currentCharset == DispatchTypes::VTCharacterSets::USASCII ||
wch < '\x5f' || wch > '\x7f') // filter out the region we know is unchanged
{
; // do nothing, these are the same as default.
}
else
{
const wchar_t* pwchTranslationTable = _GetTranslationTable();
if (pwchTranslationTable != nullptr)
const auto translationTable = _GetTranslationTable();
if (!translationTable.empty())
{
wchFound = (pwchTranslationTable[wch - '\x20']);
wchFound = translationTable.at(wch - '\x20');
}
}
return wchFound;

View File

@ -23,20 +23,15 @@ namespace Microsoft::Console::VirtualTerminal
class TerminalOutput sealed
{
public:
TerminalOutput();
~TerminalOutput();
TerminalOutput() = default;
wchar_t TranslateKey(const wchar_t wch) const;
bool DesignateCharset(const wchar_t wchNewCharset);
bool NeedToTranslate() const;
wchar_t TranslateKey(const wchar_t wch) const noexcept;
bool DesignateCharset(const wchar_t wchNewCharset) noexcept;
bool NeedToTranslate() const noexcept;
private:
wchar_t _wchCurrentCharset = DispatchTypes::VTCharacterSets::USASCII;
wchar_t _currentCharset = DispatchTypes::VTCharacterSets::USASCII;
// The tables only ever change the values x20 - x7f (96 display characters)
static const unsigned int s_uiNumDisplayCharacters = 96;
static const wchar_t s_rgDECSpecialGraphicsTranslations[s_uiNumDisplayCharacters];
const wchar_t* _GetTranslationTable() const;
const std::wstring_view _GetTranslationTable() const noexcept;
};
}

View File

@ -27,50 +27,68 @@ TerminalInput::TerminalInput(_In_ std::function<void(std::deque<std::unique_ptr<
_pfnWriteEvents = pfn;
}
struct TermKeyMap
{
const WORD vkey;
const std::wstring_view sequence;
const DWORD modifiers;
constexpr TermKeyMap(WORD vkey, std::wstring_view sequence) noexcept :
TermKeyMap(vkey, 0, sequence)
{
}
constexpr TermKeyMap(const WORD vkey, const DWORD modifiers, std::wstring_view sequence) noexcept :
vkey(vkey),
sequence(sequence),
modifiers(modifiers)
{
}
};
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
// For the source for these tables.
// Also refer to the values in terminfo for kcub1, kcud1, kcuf1, kcuu1, kend, khome.
// the 'xterm' setting lists the application mode versions of these sequences.
const TerminalInput::_TermKeyMap TerminalInput::s_rgCursorKeysNormalMapping[]{
{ VK_UP, L"\x1b[A" },
{ VK_DOWN, L"\x1b[B" },
{ VK_RIGHT, L"\x1b[C" },
{ VK_LEFT, L"\x1b[D" },
{ VK_HOME, L"\x1b[H" },
{ VK_END, L"\x1b[F" },
static constexpr std::array<TermKeyMap, 6> s_cursorKeysNormalMapping = {
TermKeyMap{ VK_UP, L"\x1b[A" },
TermKeyMap{ VK_DOWN, L"\x1b[B" },
TermKeyMap{ VK_RIGHT, L"\x1b[C" },
TermKeyMap{ VK_LEFT, L"\x1b[D" },
TermKeyMap{ VK_HOME, L"\x1b[H" },
TermKeyMap{ VK_END, L"\x1b[F" },
};
const TerminalInput::_TermKeyMap TerminalInput::s_rgCursorKeysApplicationMapping[]{
{ VK_UP, L"\x1bOA" },
{ VK_DOWN, L"\x1bOB" },
{ VK_RIGHT, L"\x1bOC" },
{ VK_LEFT, L"\x1bOD" },
{ VK_HOME, L"\x1bOH" },
{ VK_END, L"\x1bOF" },
static constexpr std::array<TermKeyMap, 6> s_cursorKeysApplicationMapping{
TermKeyMap{ VK_UP, L"\x1bOA" },
TermKeyMap{ VK_DOWN, L"\x1bOB" },
TermKeyMap{ VK_RIGHT, L"\x1bOC" },
TermKeyMap{ VK_LEFT, L"\x1bOD" },
TermKeyMap{ VK_HOME, L"\x1bOH" },
TermKeyMap{ VK_END, L"\x1bOF" },
};
const TerminalInput::_TermKeyMap TerminalInput::s_rgKeypadNumericMapping[]{
// HEY YOU. UPDATE THE MAX LENGTH DEF WHEN YOU MAKE CHANGES HERE.
{ VK_TAB, L"\x09" },
{ VK_BACK, L"\x7f" },
{ VK_PAUSE, L"\x1a" },
{ VK_ESCAPE, L"\x1b" },
{ VK_INSERT, L"\x1b[2~" },
{ VK_DELETE, L"\x1b[3~" },
{ VK_PRIOR, L"\x1b[5~" },
{ VK_NEXT, L"\x1b[6~" },
{ VK_F1, L"\x1bOP" }, // also \x1b[11~, PuTTY uses \x1b\x1b[A
{ VK_F2, L"\x1bOQ" }, // also \x1b[12~, PuTTY uses \x1b\x1b[B
{ VK_F3, L"\x1bOR" }, // also \x1b[13~, PuTTY uses \x1b\x1b[C
{ VK_F4, L"\x1bOS" }, // also \x1b[14~, PuTTY uses \x1b\x1b[D
{ VK_F5, L"\x1b[15~" },
{ VK_F6, L"\x1b[17~" },
{ VK_F7, L"\x1b[18~" },
{ VK_F8, L"\x1b[19~" },
{ VK_F9, L"\x1b[20~" },
{ VK_F10, L"\x1b[21~" },
{ VK_F11, L"\x1b[23~" },
{ VK_F12, L"\x1b[24~" },
static constexpr std::array<TermKeyMap, 20> s_keypadNumericMapping{
TermKeyMap{ VK_TAB, L"\x09" },
TermKeyMap{ VK_BACK, L"\x7f" },
TermKeyMap{ VK_PAUSE, L"\x1a" },
TermKeyMap{ VK_ESCAPE, L"\x1b" },
TermKeyMap{ VK_INSERT, L"\x1b[2~" },
TermKeyMap{ VK_DELETE, L"\x1b[3~" },
TermKeyMap{ VK_PRIOR, L"\x1b[5~" },
TermKeyMap{ VK_NEXT, L"\x1b[6~" },
TermKeyMap{ VK_F1, L"\x1bOP" }, // also \x1b[11~, PuTTY uses \x1b\x1b[A
TermKeyMap{ VK_F2, L"\x1bOQ" }, // also \x1b[12~, PuTTY uses \x1b\x1b[B
TermKeyMap{ VK_F3, L"\x1bOR" }, // also \x1b[13~, PuTTY uses \x1b\x1b[C
TermKeyMap{ VK_F4, L"\x1bOS" }, // also \x1b[14~, PuTTY uses \x1b\x1b[D
TermKeyMap{ VK_F5, L"\x1b[15~" },
TermKeyMap{ VK_F6, L"\x1b[17~" },
TermKeyMap{ VK_F7, L"\x1b[18~" },
TermKeyMap{ VK_F8, L"\x1b[19~" },
TermKeyMap{ VK_F9, L"\x1b[20~" },
TermKeyMap{ VK_F10, L"\x1b[21~" },
TermKeyMap{ VK_F11, L"\x1b[23~" },
TermKeyMap{ VK_F12, L"\x1b[24~" },
};
//Application mode - Some terminals support both a "Numeric" input mode, and an "Application" mode
@ -82,28 +100,27 @@ const TerminalInput::_TermKeyMap TerminalInput::s_rgKeypadNumericMapping[]{
//It seems to me as though this was used for early numpad implementations, where presently numlock would enable
// "numeric" mode, outputting the numbers on the keys, while "application" mode does things like pgup/down, arrow keys, etc.
//These keys aren't translated at all in numeric mode, so I figured I'd leave them out of the numeric table.
const TerminalInput::_TermKeyMap TerminalInput::s_rgKeypadApplicationMapping[]{
// HEY YOU. UPDATE THE MAX LENGTH DEF WHEN YOU MAKE CHANGES HERE.
{ VK_TAB, L"\x09" },
{ VK_BACK, L"\x7f" },
{ VK_PAUSE, L"\x1a" },
{ VK_ESCAPE, L"\x1b" },
{ VK_INSERT, L"\x1b[2~" },
{ VK_DELETE, L"\x1b[3~" },
{ VK_PRIOR, L"\x1b[5~" },
{ VK_NEXT, L"\x1b[6~" },
{ VK_F1, L"\x1bOP" }, // also \x1b[11~, PuTTY uses \x1b\x1b[A
{ VK_F2, L"\x1bOQ" }, // also \x1b[12~, PuTTY uses \x1b\x1b[B
{ VK_F3, L"\x1bOR" }, // also \x1b[13~, PuTTY uses \x1b\x1b[C
{ VK_F4, L"\x1bOS" }, // also \x1b[14~, PuTTY uses \x1b\x1b[D
{ VK_F5, L"\x1b[15~" },
{ VK_F6, L"\x1b[17~" },
{ VK_F7, L"\x1b[18~" },
{ VK_F8, L"\x1b[19~" },
{ VK_F9, L"\x1b[20~" },
{ VK_F10, L"\x1b[21~" },
{ VK_F11, L"\x1b[23~" },
{ VK_F12, L"\x1b[24~" },
static constexpr std::array<TermKeyMap, 20> s_keypadApplicationMapping{
TermKeyMap{ VK_TAB, L"\x09" },
TermKeyMap{ VK_BACK, L"\x7f" },
TermKeyMap{ VK_PAUSE, L"\x1a" },
TermKeyMap{ VK_ESCAPE, L"\x1b" },
TermKeyMap{ VK_INSERT, L"\x1b[2~" },
TermKeyMap{ VK_DELETE, L"\x1b[3~" },
TermKeyMap{ VK_PRIOR, L"\x1b[5~" },
TermKeyMap{ VK_NEXT, L"\x1b[6~" },
TermKeyMap{ VK_F1, L"\x1bOP" }, // also \x1b[11~, PuTTY uses \x1b\x1b[A
TermKeyMap{ VK_F2, L"\x1bOQ" }, // also \x1b[12~, PuTTY uses \x1b\x1b[B
TermKeyMap{ VK_F3, L"\x1bOR" }, // also \x1b[13~, PuTTY uses \x1b\x1b[C
TermKeyMap{ VK_F4, L"\x1bOS" }, // also \x1b[14~, PuTTY uses \x1b\x1b[D
TermKeyMap{ VK_F5, L"\x1b[15~" },
TermKeyMap{ VK_F6, L"\x1b[17~" },
TermKeyMap{ VK_F7, L"\x1b[18~" },
TermKeyMap{ VK_F8, L"\x1b[19~" },
TermKeyMap{ VK_F9, L"\x1b[20~" },
TermKeyMap{ VK_F10, L"\x1b[21~" },
TermKeyMap{ VK_F11, L"\x1b[23~" },
TermKeyMap{ VK_F12, L"\x1b[24~" },
// The numpad has a variety of mappings, none of which seem standard or really configurable by the OS.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
// to see just how convoluted this all is.
@ -111,55 +128,54 @@ const TerminalInput::_TermKeyMap TerminalInput::s_rgKeypadApplicationMapping[]{
// (see http://vim.wikia.com/wiki/PuTTY_numeric_keypad_mappings#Comments)
// I think the best solution is to just not do any for the time being.
// Putty also provides configuration for choosing which of the 5 mappings it has through the settings, which is more work than we can manage now.
// { VK_MULTIPLY, L"\x1bOj" }, // PuTTY: \x1bOR (I believe putty is treating the top row of the numpad as PF1-PF4)
// { VK_ADD, L"\x1bOk" }, // PuTTY: \x1bOl, \x1bOm (with shift)
// { VK_SEPARATOR, L"\x1bOl" }, // ? I'm not sure which key this is...
// { VK_SUBTRACT, L"\x1bOm" }, // \x1bOS
// { VK_DECIMAL, L"\x1bOn" }, // \x1bOn
// { VK_DIVIDE, L"\x1bOo" }, // \x1bOQ
// { VK_NUMPAD0, L"\x1bOp" },
// { VK_NUMPAD1, L"\x1bOq" },
// { VK_NUMPAD2, L"\x1bOr" },
// { VK_NUMPAD3, L"\x1bOs" },
// { VK_NUMPAD4, L"\x1bOt" },
// { VK_NUMPAD5, L"\x1bOu" }, // \x1b0E
// { VK_NUMPAD5, L"\x1bOE" }, // PuTTY \x1b[G
// { VK_NUMPAD6, L"\x1bOv" },
// { VK_NUMPAD7, L"\x1bOw" },
// { VK_NUMPAD8, L"\x1bOx" },
// { VK_NUMPAD9, L"\x1bOy" },
// { '=', L"\x1bOX" }, // I've also seen these codes mentioned in some documentation,
// { VK_SPACE, L"\x1bO " }, // but I wasn't really sure if they should be included or not...
// { VK_TAB, L"\x1bOI" }, // So I left them here as a reference just in case.
// TermKeyMap{ VK_MULTIPLY, L"\x1bOj" }, // PuTTY: \x1bOR (I believe putty is treating the top row of the numpad as PF1-PF4)
// TermKeyMap{ VK_ADD, L"\x1bOk" }, // PuTTY: \x1bOl, \x1bOm (with shift)
// TermKeyMap{ VK_SEPARATOR, L"\x1bOl" }, // ? I'm not sure which key this is...
// TermKeyMap{ VK_SUBTRACT, L"\x1bOm" }, // \x1bOS
// TermKeyMap{ VK_DECIMAL, L"\x1bOn" }, // \x1bOn
// TermKeyMap{ VK_DIVIDE, L"\x1bOo" }, // \x1bOQ
// TermKeyMap{ VK_NUMPAD0, L"\x1bOp" },
// TermKeyMap{ VK_NUMPAD1, L"\x1bOq" },
// TermKeyMap{ VK_NUMPAD2, L"\x1bOr" },
// TermKeyMap{ VK_NUMPAD3, L"\x1bOs" },
// TermKeyMap{ VK_NUMPAD4, L"\x1bOt" },
// TermKeyMap{ VK_NUMPAD5, L"\x1bOu" }, // \x1b0E
// TermKeyMap{ VK_NUMPAD5, L"\x1bOE" }, // PuTTY \x1b[G
// TermKeyMap{ VK_NUMPAD6, L"\x1bOv" },
// TermKeyMap{ VK_NUMPAD7, L"\x1bOw" },
// TermKeyMap{ VK_NUMPAD8, L"\x1bOx" },
// TermKeyMap{ VK_NUMPAD9, L"\x1bOy" },
// TermKeyMap{ '=', L"\x1bOX" }, // I've also seen these codes mentioned in some documentation,
// TermKeyMap{ VK_SPACE, L"\x1bO " }, // but I wasn't really sure if they should be included or not...
// TermKeyMap{ VK_TAB, L"\x1bOI" }, // So I left them here as a reference just in case.
};
// Sequences to send when a modifier is pressed with any of these keys
// Basically, the 'm' will be replaced with a character indicating which
// modifier keys are pressed.
const TerminalInput::_TermKeyMap TerminalInput::s_rgModifierKeyMapping[]{
// HEY YOU. UPDATE THE MAX LENGTH DEF WHEN YOU MAKE CHANGES HERE.
{ VK_UP, L"\x1b[1;mA" },
{ VK_DOWN, L"\x1b[1;mB" },
{ VK_RIGHT, L"\x1b[1;mC" },
{ VK_LEFT, L"\x1b[1;mD" },
{ VK_HOME, L"\x1b[1;mH" },
{ VK_END, L"\x1b[1;mF" },
{ VK_F1, L"\x1b[1;mP" },
{ VK_F2, L"\x1b[1;mQ" },
{ VK_F3, L"\x1b[1;mR" },
{ VK_F4, L"\x1b[1;mS" },
{ VK_INSERT, L"\x1b[2;m~" },
{ VK_DELETE, L"\x1b[3;m~" },
{ VK_PRIOR, L"\x1b[5;m~" },
{ VK_NEXT, L"\x1b[6;m~" },
{ VK_F5, L"\x1b[15;m~" },
{ VK_F6, L"\x1b[17;m~" },
{ VK_F7, L"\x1b[18;m~" },
{ VK_F8, L"\x1b[19;m~" },
{ VK_F9, L"\x1b[20;m~" },
{ VK_F10, L"\x1b[21;m~" },
{ VK_F11, L"\x1b[23;m~" },
{ VK_F12, L"\x1b[24;m~" },
static constexpr std::array<TermKeyMap, 22> s_modifierKeyMapping{
TermKeyMap{ VK_UP, L"\x1b[1;mA" },
TermKeyMap{ VK_DOWN, L"\x1b[1;mB" },
TermKeyMap{ VK_RIGHT, L"\x1b[1;mC" },
TermKeyMap{ VK_LEFT, L"\x1b[1;mD" },
TermKeyMap{ VK_HOME, L"\x1b[1;mH" },
TermKeyMap{ VK_END, L"\x1b[1;mF" },
TermKeyMap{ VK_F1, L"\x1b[1;mP" },
TermKeyMap{ VK_F2, L"\x1b[1;mQ" },
TermKeyMap{ VK_F3, L"\x1b[1;mR" },
TermKeyMap{ VK_F4, L"\x1b[1;mS" },
TermKeyMap{ VK_INSERT, L"\x1b[2;m~" },
TermKeyMap{ VK_DELETE, L"\x1b[3;m~" },
TermKeyMap{ VK_PRIOR, L"\x1b[5;m~" },
TermKeyMap{ VK_NEXT, L"\x1b[6;m~" },
TermKeyMap{ VK_F5, L"\x1b[15;m~" },
TermKeyMap{ VK_F6, L"\x1b[17;m~" },
TermKeyMap{ VK_F7, L"\x1b[18;m~" },
TermKeyMap{ VK_F8, L"\x1b[19;m~" },
TermKeyMap{ VK_F9, L"\x1b[20;m~" },
TermKeyMap{ VK_F10, L"\x1b[21;m~" },
TermKeyMap{ VK_F11, L"\x1b[23;m~" },
TermKeyMap{ VK_F12, L"\x1b[24;m~" },
// Ubuntu's inputrc also defines \x1b[5C, \x1b\x1bC (and D) as 'forward/backward-word' mappings
// I believe '\x1b\x1bC' is listed because the C1 ESC (x9B) gets encoded as
// \xC2\x9B, but then translated to \x1b\x1b if the C1 codepoint isn't supported by the current encoding
@ -169,95 +185,127 @@ const TerminalInput::_TermKeyMap TerminalInput::s_rgModifierKeyMapping[]{
// These sequences are not later updated to encode the modifier state in the
// sequence itself, they are just weird exceptional cases to the general
// rules above.
const TerminalInput::_TermKeyMap TerminalInput::s_rgSimpleModifedKeyMapping[]{
// HEY YOU. UPDATE THE MAX LENGTH DEF WHEN YOU MAKE CHANGES HERE.
{ VK_BACK, CTRL_PRESSED, L"\x8" },
{ VK_BACK, ALT_PRESSED, L"\x1b\x7f" },
{ VK_BACK, CTRL_PRESSED | ALT_PRESSED, L"\x1b\x8" },
{ VK_TAB, CTRL_PRESSED, L"\t" },
{ VK_TAB, SHIFT_PRESSED, L"\x1b[Z" },
{ VK_DIVIDE, CTRL_PRESSED, L"\x1F" },
static constexpr std::array<TermKeyMap, 6> s_simpleModifedKeyMapping{
TermKeyMap{ VK_BACK, CTRL_PRESSED, L"\x8" },
TermKeyMap{ VK_BACK, ALT_PRESSED, L"\x1b\x7f" },
TermKeyMap{ VK_BACK, CTRL_PRESSED | ALT_PRESSED, L"\x1b\x8" },
TermKeyMap{ VK_TAB, CTRL_PRESSED, L"\t" },
TermKeyMap{ VK_TAB, SHIFT_PRESSED, L"\x1b[Z" },
TermKeyMap{ VK_DIVIDE, CTRL_PRESSED, L"\x1F" },
// These two are not implemented here, because they are system keys.
// { VK_TAB, ALT_PRESSED, L""}, This is the Windows system shortcut for switching windows.
// { VK_ESCAPE, ALT_PRESSED, L""}, This is another Windows system shortcut for switching windows.
// TermKeyMap{ VK_TAB, ALT_PRESSED, L""}, This is the Windows system shortcut for switching windows.
// TermKeyMap{ VK_ESCAPE, ALT_PRESSED, L""}, This is another Windows system shortcut for switching windows.
};
const wchar_t* const CTRL_SLASH_SEQUENCE = L"\x1f";
// Do NOT include the null terminator in the count.
const size_t TerminalInput::_TermKeyMap::s_cchMaxSequenceLength = 7; // UPDATE THIS DEF WHEN THE LONGEST MAPPED STRING CHANGES
const size_t TerminalInput::s_cCursorKeysNormalMapping = ARRAYSIZE(s_rgCursorKeysNormalMapping);
const size_t TerminalInput::s_cCursorKeysApplicationMapping = ARRAYSIZE(s_rgCursorKeysApplicationMapping);
const size_t TerminalInput::s_cKeypadNumericMapping = ARRAYSIZE(s_rgKeypadNumericMapping);
const size_t TerminalInput::s_cKeypadApplicationMapping = ARRAYSIZE(s_rgKeypadApplicationMapping);
const size_t TerminalInput::s_cModifierKeyMapping = ARRAYSIZE(s_rgModifierKeyMapping);
const size_t TerminalInput::s_cSimpleModifedKeyMapping = ARRAYSIZE(s_rgSimpleModifedKeyMapping);
void TerminalInput::ChangeKeypadMode(const bool fApplicationMode)
void TerminalInput::ChangeKeypadMode(const bool applicationMode) noexcept
{
_fKeypadApplicationMode = fApplicationMode;
_keypadApplicationMode = applicationMode;
}
void TerminalInput::ChangeCursorKeysMode(const bool fApplicationMode)
void TerminalInput::ChangeCursorKeysMode(const bool applicationMode) noexcept
{
_fCursorApplicationMode = fApplicationMode;
_cursorApplicationMode = applicationMode;
}
const size_t TerminalInput::GetKeyMappingLength(const KeyEvent& keyEvent) const
static const std::basic_string_view<TermKeyMap> _getKeyMapping(const KeyEvent& keyEvent,
const bool cursorApplicationMode,
const bool keypadApplicationMode) noexcept
{
if (keyEvent.IsCursorKey())
{
return (_fCursorApplicationMode) ? s_cCursorKeysApplicationMapping : s_cCursorKeysNormalMapping;
if (cursorApplicationMode)
{
return { s_cursorKeysApplicationMapping.data(), s_cursorKeysApplicationMapping.size() };
}
else
{
return { s_cursorKeysNormalMapping.data(), s_cursorKeysNormalMapping.size() };
}
}
return (_fKeypadApplicationMode) ? s_cKeypadApplicationMapping : s_cKeypadNumericMapping;
}
const TerminalInput::_TermKeyMap* TerminalInput::GetKeyMapping(const KeyEvent& keyEvent) const
{
if (keyEvent.IsCursorKey())
else
{
return (_fCursorApplicationMode) ? s_rgCursorKeysApplicationMapping : s_rgCursorKeysNormalMapping;
if (keypadApplicationMode)
{
return { s_keypadApplicationMapping.data(), s_keypadApplicationMapping.size() };
}
else
{
return { s_keypadNumericMapping.data(), s_keypadNumericMapping.size() };
}
}
return (_fKeypadApplicationMode) ? s_rgKeypadApplicationMapping : s_rgKeypadNumericMapping;
}
// Routine Description:
// - Searches the s_ModifierKeyMapping for a entry corresponding to this key event.
// - Searches the keyMapping for a entry corresponding to this key event, and returns it.
// Arguments:
// - keyEvent - Key event to translate
// - keyMapping - Array of key mappings to search
// Return Value:
// - Has value if there was a match to a key translation.
static std::optional<const TermKeyMap> _searchKeyMapping(const KeyEvent& keyEvent,
std::basic_string_view<TermKeyMap> keyMapping) noexcept
{
for (auto& map : keyMapping)
{
if (map.vkey == keyEvent.GetVirtualKeyCode())
{
// If the mapping has no modifiers set, then it doesn't really care
// what the modifiers are on the key. The caller will likely do
// something with them.
// However, if there are modifiers set, then we only want to match
// if the key's modifiers are the same as the modifiers in the
// mapping.
bool modifiersMatch = WI_AreAllFlagsClear(map.modifiers, MOD_PRESSED);
if (!modifiersMatch)
{
// The modifier mapping expects certain modifier keys to be
// pressed. Check those as well.
modifiersMatch =
(WI_IsFlagSet(map.modifiers, SHIFT_PRESSED) == keyEvent.IsShiftPressed()) &&
(WI_IsAnyFlagSet(map.modifiers, ALT_PRESSED) == keyEvent.IsAltPressed()) &&
(WI_IsAnyFlagSet(map.modifiers, CTRL_PRESSED) == keyEvent.IsCtrlPressed());
}
if (modifiersMatch)
{
return map;
}
}
}
return std::nullopt;
}
typedef std::function<void(const std::wstring_view)> InputSender;
// Routine Description:
// - Searches the s_modifierKeyMapping for a entry corresponding to this key event.
// Changes the second to last byte to correspond to the currently pressed modifier keys
// before sending to the input.
// Arguments:
// - keyEvent - Key event to translate
// - sender - Function to use to dispatch translated event
// Return Value:
// - True if there was a match to a key translation, and we successfully modified and sent it to the input
bool TerminalInput::_SearchWithModifier(const KeyEvent& keyEvent) const
static bool _searchWithModifier(const KeyEvent& keyEvent, InputSender sender)
{
const TerminalInput::_TermKeyMap* pMatchingMapping;
bool fSuccess = _SearchKeyMapping(keyEvent,
s_rgModifierKeyMapping,
s_cModifierKeyMapping,
&pMatchingMapping);
if (fSuccess)
bool success = false;
const auto match = _searchKeyMapping(keyEvent,
{ s_modifierKeyMapping.data(), s_modifierKeyMapping.size() });
if (match)
{
size_t cch = 0;
if (SUCCEEDED(StringCchLengthW(pMatchingMapping->pwszSequence, _TermKeyMap::s_cchMaxSequenceLength + 1, &cch)) &&
cch > 0)
const auto v = match.value();
if (!v.sequence.empty())
{
wchar_t* rwchModifiedSequence = new (std::nothrow) wchar_t[cch + 1];
if (rwchModifiedSequence != nullptr)
{
memcpy(rwchModifiedSequence, pMatchingMapping->pwszSequence, cch * sizeof(wchar_t));
const bool fShift = keyEvent.IsShiftPressed();
const bool fAlt = keyEvent.IsAltPressed();
const bool fCtrl = keyEvent.IsCtrlPressed();
rwchModifiedSequence[cch - 2] = L'1' + (fShift ? 1 : 0) + (fAlt ? 2 : 0) + (fCtrl ? 4 : 0);
rwchModifiedSequence[cch] = 0;
_SendInputSequence(rwchModifiedSequence);
fSuccess = true;
delete[] rwchModifiedSequence;
}
std::wstring modified{ v.sequence }; // Make a copy so we can modify it.
const bool shift = keyEvent.IsShiftPressed();
const bool alt = keyEvent.IsAltPressed();
const bool ctrl = keyEvent.IsCtrlPressed();
modified.at(modified.size() - 2) = L'1' + (shift ? 1 : 0) + (alt ? 2 : 0) + (ctrl ? 4 : 0);
sender(modified);
success = true;
}
}
else
@ -265,15 +313,13 @@ bool TerminalInput::_SearchWithModifier(const KeyEvent& keyEvent) const
// We didn't find the key in the map of modified keys that need editing,
// maybe it's in the other map of modified keys with sequences that
// don't need editing before sending.
fSuccess = _SearchKeyMapping(keyEvent,
s_rgSimpleModifedKeyMapping,
s_cSimpleModifedKeyMapping,
&pMatchingMapping);
if (fSuccess)
const auto match2 = _searchKeyMapping(keyEvent,
{ s_simpleModifedKeyMapping.data(), s_simpleModifedKeyMapping.size() });
if (match2)
{
// This mapping doesn't need to be changed at all.
_SendInputSequence(pMatchingMapping->pwszSequence);
fSuccess = true;
sender(match2.value().sequence);
success = true;
}
else
{
@ -284,62 +330,13 @@ bool TerminalInput::_SearchWithModifier(const KeyEvent& keyEvent) const
if (keyEvent.GetVirtualKeyCode() == slashVkey && keyEvent.IsCtrlPressed())
{
// This mapping doesn't need to be changed at all.
_SendInputSequence(CTRL_SLASH_SEQUENCE);
fSuccess = true;
sender(CTRL_SLASH_SEQUENCE);
success = true;
}
}
}
return fSuccess;
}
// Routine Description:
// - Searches the keyMapping for a entry corresponding to this key event, and returns it.
// Arguments:
// - keyEvent - Key event to translate
// - keyMapping - Array of key mappings to search
// - cKeyMapping - number of entries in keyMapping
// - pMatchingMapping - Where to put the pointer to the found match
// Return Value:
// - True if there was a match to a key translation
bool TerminalInput::_SearchKeyMapping(const KeyEvent& keyEvent,
_In_reads_(cKeyMapping) const TerminalInput::_TermKeyMap* keyMapping,
const size_t cKeyMapping,
_Out_ const TerminalInput::_TermKeyMap** pMatchingMapping) const
{
bool fKeyTranslated = false;
for (size_t i = 0; i < cKeyMapping; i++)
{
const _TermKeyMap* const pMap = &(keyMapping[i]);
if (pMap->wVirtualKey == keyEvent.GetVirtualKeyCode())
{
// If the mapping has no modifiers set, then it doesn't really care
// what the modifiers are on the key. The caller will likely do
// something with them.
// However, if there are modifiers set, then we only want to match
// if the key's modifiers are the same as the modifiers in the
// mapping.
bool modifiersMatch = WI_AreAllFlagsClear(pMap->dwModifiers, MOD_PRESSED);
if (!modifiersMatch)
{
// The modifier mapping expects certain modifier keys to be
// pressed. Check those as well.
modifiersMatch =
(WI_IsFlagSet(pMap->dwModifiers, SHIFT_PRESSED) == keyEvent.IsShiftPressed()) &&
(WI_IsAnyFlagSet(pMap->dwModifiers, ALT_PRESSED) == keyEvent.IsAltPressed()) &&
(WI_IsAnyFlagSet(pMap->dwModifiers, CTRL_PRESSED) == keyEvent.IsCtrlPressed());
}
if (modifiersMatch)
{
fKeyTranslated = true;
*pMatchingMapping = pMap;
break;
}
}
}
return fKeyTranslated;
return success;
}
// Routine Description:
@ -347,30 +344,31 @@ bool TerminalInput::_SearchKeyMapping(const KeyEvent& keyEvent,
// Arguments:
// - keyEvent - Key event to translate
// - keyMapping - Array of key mappings to search
// - cKeyMapping - number of entries in keyMapping
// - sender - Function to use to dispatch translated event
// Return Value:
// - True if there was a match to a key translation, and we successfully sent it to the input
bool TerminalInput::_TranslateDefaultMapping(const KeyEvent& keyEvent,
_In_reads_(cKeyMapping) const TerminalInput::_TermKeyMap* keyMapping,
const size_t cKeyMapping) const
static bool _translateDefaultMapping(const KeyEvent& keyEvent,
const std::basic_string_view<TermKeyMap> keyMapping,
InputSender sender)
{
const TerminalInput::_TermKeyMap* pMatchingMapping;
const bool fSuccess = _SearchKeyMapping(keyEvent, keyMapping, cKeyMapping, &pMatchingMapping);
if (fSuccess)
const auto match = _searchKeyMapping(keyEvent, keyMapping);
if (match)
{
_SendInputSequence(pMatchingMapping->pwszSequence);
sender(match->sequence);
}
return fSuccess;
return match.has_value();
}
bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
{
// By default, we fail to handle the key
bool fKeyHandled = false;
bool keyHandled = false;
// On key presses, prepare to translate to VT compatible sequences
if (pInEvent->EventType() == InputEventType::KeyEvent)
{
const auto senderFunc = [this](const std::wstring_view seq) { _SendInputSequence(seq); };
auto keyEvent = *static_cast<const KeyEvent* const>(pInEvent);
// Only need to handle key down. See raw key handler (see RawReadWaitRoutine in stream.cpp)
@ -406,7 +404,7 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
// For Alt+Ctrl+Key messages, the UnicodeChar is NOT the Ctrl+key char, it's null.
// So we need to get the char from the vKey.
// EXCEPT for Alt+Ctrl+Space. Then the UnicodeChar is space, not NUL.
auto wchPressedChar = static_cast<wchar_t>(MapVirtualKeyW(keyEvent.GetVirtualKeyCode(), MAPVK_VK_TO_CHAR));
auto wchPressedChar = gsl::narrow_cast<wchar_t>(MapVirtualKeyW(keyEvent.GetVirtualKeyCode(), MAPVK_VK_TO_CHAR));
// This is a trick - C-Spc is supposed to send NUL. So quick change space -> @ (0x40)
wchPressedChar = (wchPressedChar == UNICODE_SPACE) ? 0x40 : wchPressedChar;
if (wchPressedChar >= 0x40 && wchPressedChar < 0x7F)
@ -414,23 +412,23 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
//shift the char to the ctrl range
wchPressedChar -= 0x40;
_SendEscapedInputSequence(wchPressedChar);
fKeyHandled = true;
keyHandled = true;
}
}
// If a modifier key was pressed, then we need to try and send the modified sequence.
if (!fKeyHandled && keyEvent.IsModifierPressed())
if (!keyHandled && keyEvent.IsModifierPressed())
{
// Translate the key using the modifier table
fKeyHandled = _SearchWithModifier(keyEvent);
keyHandled = _searchWithModifier(keyEvent, senderFunc);
}
// ALT is a sequence of ESC + KEY.
if (!fKeyHandled && keyEvent.GetCharData() != 0 && keyEvent.IsAltPressed())
if (!keyHandled && keyEvent.GetCharData() != 0 && keyEvent.IsAltPressed())
{
_SendEscapedInputSequence(keyEvent.GetCharData());
fKeyHandled = true;
keyHandled = true;
}
if (!fKeyHandled && keyEvent.IsCtrlPressed())
if (!keyHandled && keyEvent.IsCtrlPressed())
{
if ((keyEvent.GetCharData() == UNICODE_SPACE) || // Ctrl+Space
// when Ctrl+@ comes through, the unicodechar
@ -439,11 +437,11 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
(keyEvent.GetCharData() == UNICODE_NULL && keyEvent.GetVirtualKeyCode() == LOBYTE(VkKeyScanW(0))))
{
_SendNullInputSequence(keyEvent.GetActiveModifierKeys());
fKeyHandled = true;
keyHandled = true;
}
}
if (!fKeyHandled)
if (!keyHandled)
{
// For perf optimization, filter out any typically printable Virtual Keys (e.g. A-Z)
// This is in lieu of an O(1) sparse table or other such less-maintanable methods.
@ -451,7 +449,7 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
if ((keyEvent.GetVirtualKeyCode() < '0' || keyEvent.GetVirtualKeyCode() > 'Z') &&
keyEvent.GetVirtualKeyCode() != VK_CANCEL)
{
fKeyHandled = _TranslateDefaultMapping(keyEvent, GetKeyMapping(keyEvent), GetKeyMappingLength(keyEvent));
keyHandled = _translateDefaultMapping(keyEvent, _getKeyMapping(keyEvent, _cursorApplicationMode, _keypadApplicationMode), senderFunc);
}
else
{
@ -459,13 +457,13 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) const
rgwchSequence[0] = keyEvent.GetCharData();
rgwchSequence[1] = UNICODE_NULL;
_SendInputSequence(rgwchSequence);
fKeyHandled = true;
keyHandled = true;
}
}
}
}
return fKeyHandled;
return keyHandled;
}
bool TerminalInput::HandleChar(const wchar_t ch)
@ -480,9 +478,8 @@ bool TerminalInput::HandleChar(const wchar_t ch)
{
// we already were storing a leading surrogate but we got another one. Go ahead and send the
// saved surrogate piece and save the new one
wchar_t buffer[32];
swprintf_s(buffer, L"%I32u", _leadingSurrogate.value());
_SendInputSequence(buffer);
const auto formatted = wil::str_printf<std::wstring>(L"%I32u", _leadingSurrogate.value());
_SendInputSequence(formatted);
}
// save the leading portion of a surrogate pair so that they can be sent at the same time
_leadingSurrogate.emplace(ch);
@ -499,9 +496,7 @@ bool TerminalInput::HandleChar(const wchar_t ch)
}
else
{
wchar_t buffer[2] = { ch, 0 };
std::wstring_view buffer_view(buffer, 1);
_SendInputSequence(buffer_view);
_SendInputSequence({ &ch, 1 });
}
return true;
@ -529,7 +524,7 @@ void TerminalInput::_SendEscapedInputSequence(const wchar_t wch) const
}
}
void TerminalInput::_SendNullInputSequence(const DWORD dwControlKeyState) const
void TerminalInput::_SendNullInputSequence(const DWORD controlKeyState) const
{
try
{
@ -539,7 +534,7 @@ void TerminalInput::_SendNullInputSequence(const DWORD dwControlKeyState) const
LOBYTE(VkKeyScanW(0)),
0ui16,
L'\x0',
dwControlKeyState));
controlKeyState));
_pfnWriteEvents(inputEvents);
}
catch (...)
@ -548,17 +543,16 @@ void TerminalInput::_SendNullInputSequence(const DWORD dwControlKeyState) const
}
}
void TerminalInput::_SendInputSequence(_In_ const std::wstring_view sequence) const
void TerminalInput::_SendInputSequence(const std::wstring_view sequence) const
{
const auto length = sequence.length();
if (length <= _TermKeyMap::s_cchMaxSequenceLength && length > 0)
if (!sequence.empty())
{
try
{
std::deque<std::unique_ptr<IInputEvent>> inputEvents;
for (size_t i = 0; i < length; i++)
for (const auto& wch : sequence)
{
inputEvents.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, sequence[i], 0));
inputEvents.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, wch, 0));
}
_pfnWriteEvents(inputEvents);
}

View File

@ -35,8 +35,8 @@ namespace Microsoft::Console::VirtualTerminal
bool HandleKey(const IInputEvent* const pInEvent) const;
bool HandleChar(const wchar_t ch);
void ChangeKeypadMode(const bool fApplicationMode);
void ChangeCursorKeysMode(const bool fApplicationMode);
void ChangeKeypadMode(const bool applicationMode) noexcept;
void ChangeCursorKeysMode(const bool applicationMode) noexcept;
private:
std::function<void(std::deque<std::unique_ptr<IInputEvent>>&)> _pfnWriteEvents;
@ -44,70 +44,11 @@ namespace Microsoft::Console::VirtualTerminal
// storage location for the leading surrogate of a utf-16 surrogate pair
std::optional<wchar_t> _leadingSurrogate;
bool _fKeypadApplicationMode = false;
bool _fCursorApplicationMode = false;
bool _keypadApplicationMode = false;
bool _cursorApplicationMode = false;
void _SendNullInputSequence(const DWORD dwControlKeyState) const;
void _SendInputSequence(_In_ const std::wstring_view sequence) const;
void _SendInputSequence(const std::wstring_view sequence) const;
void _SendEscapedInputSequence(const wchar_t wch) const;
struct _TermKeyMap
{
WORD const wVirtualKey;
PCWSTR const pwszSequence;
DWORD const dwModifiers;
static const size_t s_cchMaxSequenceLength;
_TermKeyMap(const WORD wVirtualKey, _In_ PCWSTR const pwszSequence) noexcept :
wVirtualKey(wVirtualKey),
pwszSequence(pwszSequence),
dwModifiers(0){};
_TermKeyMap(const WORD wVirtualKey, const DWORD dwModifiers, _In_ PCWSTR const pwszSequence) noexcept :
wVirtualKey(wVirtualKey),
pwszSequence(pwszSequence),
dwModifiers(dwModifiers){};
// C++11 syntax for prohibiting assignment
// We can't assign, everything here is const.
// We also shouldn't need to, this is only for a specific table.
_TermKeyMap(const _TermKeyMap&) = delete;
_TermKeyMap& operator=(const _TermKeyMap&) = delete;
_TermKeyMap(_TermKeyMap&&) = delete;
_TermKeyMap& operator=(_TermKeyMap&&) = delete;
_TermKeyMap() = delete;
~_TermKeyMap() = default;
};
static const _TermKeyMap s_rgCursorKeysNormalMapping[];
static const _TermKeyMap s_rgCursorKeysApplicationMapping[];
static const _TermKeyMap s_rgKeypadNumericMapping[];
static const _TermKeyMap s_rgKeypadApplicationMapping[];
static const _TermKeyMap s_rgModifierKeyMapping[];
static const _TermKeyMap s_rgSimpleModifedKeyMapping[];
static const size_t s_cCursorKeysNormalMapping;
static const size_t s_cCursorKeysApplicationMapping;
static const size_t s_cKeypadNumericMapping;
static const size_t s_cKeypadApplicationMapping;
static const size_t s_cModifierKeyMapping;
static const size_t s_cSimpleModifedKeyMapping;
bool _SearchKeyMapping(const KeyEvent& keyEvent,
_In_reads_(cKeyMapping) const TerminalInput::_TermKeyMap* keyMapping,
const size_t cKeyMapping,
_Out_ const TerminalInput::_TermKeyMap** pMatchingMapping) const;
bool _TranslateDefaultMapping(const KeyEvent& keyEvent,
_In_reads_(cKeyMapping) const TerminalInput::_TermKeyMap* keyMapping,
const size_t cKeyMapping) const;
bool _SearchWithModifier(const KeyEvent& keyEvent) const;
const size_t GetKeyMappingLength(const KeyEvent& keyEvent) const;
const _TermKeyMap* GetKeyMapping(const KeyEvent& keyEvent) const;
};
}

View File

@ -204,7 +204,7 @@ bool InputStateMachineEngine::_DoControlCharacter(const wchar_t wch, const bool
{
// This is a C0 Control Character.
// This should be translated as Ctrl+(wch+x40)
wchar_t actualChar = wch;
const wchar_t actualChar = wch;
bool writeCtrl = true;
short vkey = 0;
@ -393,7 +393,7 @@ bool InputStateMachineEngine::ActionCsiDispatch(const wchar_t wch,
const auto remainingArgs = parameters.size() > 1 ? parameters.substr(1) : std::basic_string_view<size_t>{};
bool success = false;
switch ((CsiActionCodes)wch)
switch (static_cast<CsiActionCodes>(wch))
{
case CsiActionCodes::Generic:
modifierState = _GetGenericKeysModifierState(parameters);
@ -437,7 +437,7 @@ bool InputStateMachineEngine::ActionCsiDispatch(const wchar_t wch,
if (success)
{
switch ((CsiActionCodes)wch)
switch (static_cast<CsiActionCodes>(wch))
{
// case CsiActionCodes::DSR_DeviceStatusReportResponse:
case CsiActionCodes::CSI_F3:
@ -493,14 +493,14 @@ bool InputStateMachineEngine::ActionSs3Dispatch(const wchar_t wch,
{
// Ss3 sequence keys aren't modified.
// When F1-F4 *are* modified, they're sent as CSI sequences, not SS3's.
DWORD dwModifierState = 0;
const DWORD modifierState = 0;
short vkey = 0;
bool success = _GetSs3KeysVkey(wch, vkey);
if (success)
{
success = _WriteSingleKey(vkey, dwModifierState);
success = _WriteSingleKey(vkey, modifierState);
}
return success;
@ -513,7 +513,7 @@ bool InputStateMachineEngine::ActionSs3Dispatch(const wchar_t wch,
// - <none>
// Return Value:
// - true iff we successfully dispatched the sequence.
bool InputStateMachineEngine::ActionClear()
bool InputStateMachineEngine::ActionClear() noexcept
{
return true;
}
@ -525,7 +525,7 @@ bool InputStateMachineEngine::ActionClear()
// - <none>
// Return Value:
// - true iff we successfully dispatched the sequence.
bool InputStateMachineEngine::ActionIgnore()
bool InputStateMachineEngine::ActionIgnore() noexcept
{
return true;
}
@ -541,7 +541,7 @@ bool InputStateMachineEngine::ActionIgnore()
// - true if we handled the dsipatch.
bool InputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
const size_t /*parameter*/,
const std::wstring_view /*string*/)
const std::wstring_view /*string*/) noexcept
{
return false;
}
@ -575,7 +575,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
const bool ctrl = WI_IsFlagSet(modifierState, LEFT_CTRL_PRESSED);
const bool alt = WI_IsFlagSet(modifierState, LEFT_ALT_PRESSED);
INPUT_RECORD next;
INPUT_RECORD next{ 0 };
DWORD currentModifiers = 0;
@ -587,7 +587,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_SHIFT;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -599,7 +599,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_MENU;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_MENU, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_MENU, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -611,7 +611,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_CONTROL;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -626,7 +626,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_CONTROL;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -638,7 +638,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_MENU;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_MENU, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_MENU, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -650,7 +650,7 @@ void InputStateMachineEngine::_GenerateWrappedSequence(const wchar_t wch,
next.Event.KeyEvent.dwControlKeyState = currentModifiers;
next.Event.KeyEvent.wRepeatCount = 1;
next.Event.KeyEvent.wVirtualKeyCode = VK_SHIFT;
next.Event.KeyEvent.wVirtualScanCode = static_cast<WORD>(MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC));
next.Event.KeyEvent.uChar.UnicodeChar = 0x0;
input.push_back(next);
}
@ -681,7 +681,7 @@ void InputStateMachineEngine::_GetSingleKeypress(const wchar_t wch,
rec.Event.KeyEvent.dwControlKeyState = modifierState;
rec.Event.KeyEvent.wRepeatCount = 1;
rec.Event.KeyEvent.wVirtualKeyCode = vkey;
rec.Event.KeyEvent.wVirtualScanCode = (WORD)MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
rec.Event.KeyEvent.wVirtualScanCode = gsl::narrow_cast<WORD>(MapVirtualKey(vkey, MAPVK_VK_TO_VSC));
rec.Event.KeyEvent.uChar.UnicodeChar = wch;
input.push_back(rec);
@ -715,12 +715,12 @@ bool InputStateMachineEngine::_WriteSingleKey(const wchar_t wch, const short vke
// Will automatically get the wchar_t associated with that vkey.
// Arguments:
// - vkey - the VKEY of the key to write to the input callback.
// - dwModifierState - the modifier state to write with the key.
// - modifierState - the modifier state to write with the key.
// Return Value:
// - true iff we successfully wrote the keypress to the input callback.
bool InputStateMachineEngine::_WriteSingleKey(const short vkey, const DWORD dwModifierState)
{
wchar_t wch = (wchar_t)MapVirtualKey(vkey, MAPVK_VK_TO_CHAR);
const wchar_t wch = gsl::narrow_cast<wchar_t>(MapVirtualKey(vkey, MAPVK_VK_TO_CHAR));
return _WriteSingleKey(wch, vkey, dwModifierState);
}
@ -732,7 +732,7 @@ bool InputStateMachineEngine::_WriteSingleKey(const short vkey, const DWORD dwMo
// - cParams - the number of elements in rgusParams
// Return Value:
// - the INPUT_RECORD comaptible modifier state.
DWORD InputStateMachineEngine::_GetCursorKeysModifierState(const std::basic_string_view<size_t> parameters)
DWORD InputStateMachineEngine::_GetCursorKeysModifierState(const std::basic_string_view<size_t> parameters) noexcept
{
// Both Cursor keys and generic keys keep their modifiers in the same index.
return _GetGenericKeysModifierState(parameters);
@ -746,7 +746,7 @@ DWORD InputStateMachineEngine::_GetCursorKeysModifierState(const std::basic_stri
// - cParams - the number of elements in rgusParams
// Return Value:
// - the INPUT_RECORD compatible modifier state.
DWORD InputStateMachineEngine::_GetGenericKeysModifierState(const std::basic_string_view<size_t> parameters)
DWORD InputStateMachineEngine::_GetGenericKeysModifierState(const std::basic_string_view<size_t> parameters) noexcept
{
DWORD modifiers = 0;
if (_IsModified(parameters.size()) && parameters.size() >= 2)
@ -762,7 +762,7 @@ DWORD InputStateMachineEngine::_GetGenericKeysModifierState(const std::basic_str
// - paramCount - the nummber of parameters we've collected in this sequence
// Return Value:
// - true iff the sequence is a modified sequence.
bool InputStateMachineEngine::_IsModified(const size_t paramCount)
bool InputStateMachineEngine::_IsModified(const size_t paramCount) noexcept
{
// modified input either looks like
// \x1b[1;mA or \x1b[17;m~
@ -776,7 +776,7 @@ bool InputStateMachineEngine::_IsModified(const size_t paramCount)
// - modifierParam - the VT modifier value to convert
// Return Value:
// - The equivalent INPUT_RECORD modifier value.
DWORD InputStateMachineEngine::_GetModifier(const size_t modifierParam)
DWORD InputStateMachineEngine::_GetModifier(const size_t modifierParam) noexcept
{
// VT Modifiers are 1+(modifier flags)
const auto vtParam = modifierParam - 1;
@ -805,7 +805,7 @@ bool InputStateMachineEngine::_GetGenericVkey(const std::basic_string_view<size_
return false;
}
const auto identifier = (GenericKeyIdentifiers)parameters[0];
const auto identifier = (GenericKeyIdentifiers)til::at(parameters, 0);
const auto mapping = std::find(s_genericMap.cbegin(), s_genericMap.cend(), identifier);
if (mapping != s_genericMap.end())
@ -869,14 +869,14 @@ bool InputStateMachineEngine::_GetSs3KeysVkey(const wchar_t wch, short& vkey) co
// <none>
bool InputStateMachineEngine::_GenerateKeyFromChar(const wchar_t wch,
short& vkey,
DWORD& modifierState)
DWORD& modifierState) noexcept
{
// Low order byte is key, high order is modifiers
short keyscan = VkKeyScanW(wch);
const short keyscan = VkKeyScanW(wch);
short key = LOBYTE(keyscan);
short keyscanModifiers = HIBYTE(keyscan);
const short keyscanModifiers = HIBYTE(keyscan);
if (key == -1 && keyscanModifiers == -1)
{
@ -902,7 +902,7 @@ bool InputStateMachineEngine::_GenerateKeyFromChar(const wchar_t wch,
// ProcessString, and dispatch only at the end of the sequence.
// Return Value:
// - True iff we should manually dispatch on the last character of a string.
bool InputStateMachineEngine::FlushAtEndOfString() const
bool InputStateMachineEngine::FlushAtEndOfString() const noexcept
{
return true;
}
@ -917,7 +917,7 @@ bool InputStateMachineEngine::FlushAtEndOfString() const
// Return Value:
// - True iff we should return to the Ground state when the state machine
// encounters a Control (C0) character in the Escape state.
bool InputStateMachineEngine::DispatchControlCharsFromEscape() const
bool InputStateMachineEngine::DispatchControlCharsFromEscape() const noexcept
{
return true;
}
@ -930,7 +930,7 @@ bool InputStateMachineEngine::DispatchControlCharsFromEscape() const
// Return Value:
// - True iff we should dispatch in the Escape state when we encounter a
// Intermediate character.
bool InputStateMachineEngine::DispatchIntermediatesFromEscape() const
bool InputStateMachineEngine::DispatchIntermediatesFromEscape() const noexcept
{
return true;
}
@ -946,14 +946,14 @@ bool InputStateMachineEngine::DispatchIntermediatesFromEscape() const
// Return Value:
// - True iff we successfully pulled the function type from the parameters
bool InputStateMachineEngine::_GetWindowManipulationType(const std::basic_string_view<size_t> parameters,
unsigned int& function) const
unsigned int& function) const noexcept
{
bool success = false;
function = DispatchTypes::WindowManipulationType::Invalid;
if (!parameters.empty())
{
switch (parameters[0])
switch (til::at(parameters, 0))
{
case DispatchTypes::WindowManipulationType::RefreshWindow:
function = DispatchTypes::WindowManipulationType::RefreshWindow;
@ -981,7 +981,7 @@ bool InputStateMachineEngine::_GetWindowManipulationType(const std::basic_string
// - True if we successfully pulled the cursor coordinates from the parameters we've stored. False otherwise.
bool InputStateMachineEngine::_GetXYPosition(const std::basic_string_view<size_t> parameters,
size_t& line,
size_t& column) const
size_t& column) const noexcept
{
bool success = true;
line = DefaultLine;
@ -994,13 +994,13 @@ bool InputStateMachineEngine::_GetXYPosition(const std::basic_string_view<size_t
else if (parameters.size() == 1)
{
// If there's only one param, leave the default for the column, and retrieve the specified row.
line = parameters[0];
line = til::at(parameters, 0);
}
else if (parameters.size() == 2)
{
// If there are exactly two parameters, use them.
line = parameters[0];
column = parameters[1];
line = til::at(parameters, 0);
column = til::at(parameters, 1);
}
else
{

View File

@ -46,31 +46,31 @@ namespace Microsoft::Console::VirtualTerminal
const std::basic_string_view<wchar_t> intermediates,
const std::basic_string_view<size_t> parameters) override;
bool ActionClear() override;
bool ActionClear() noexcept override;
bool ActionIgnore() override;
bool ActionIgnore() noexcept override;
bool ActionOscDispatch(const wchar_t wch,
const size_t parameter,
const std::wstring_view string) override;
const std::wstring_view string) noexcept override;
bool ActionSs3Dispatch(const wchar_t wch,
const std::basic_string_view<size_t> parameters) override;
bool FlushAtEndOfString() const override;
bool DispatchControlCharsFromEscape() const override;
bool DispatchIntermediatesFromEscape() const override;
bool FlushAtEndOfString() const noexcept override;
bool DispatchControlCharsFromEscape() const noexcept override;
bool DispatchIntermediatesFromEscape() const noexcept override;
private:
const std::unique_ptr<IInteractDispatch> _pDispatch;
bool _lookingForDSR;
DWORD _GetCursorKeysModifierState(const std::basic_string_view<size_t> parameters);
DWORD _GetGenericKeysModifierState(const std::basic_string_view<size_t> parameters);
bool _GenerateKeyFromChar(const wchar_t wch, short& vkey, DWORD& modifierState);
DWORD _GetCursorKeysModifierState(const std::basic_string_view<size_t> parameters) noexcept;
DWORD _GetGenericKeysModifierState(const std::basic_string_view<size_t> parameters) noexcept;
bool _GenerateKeyFromChar(const wchar_t wch, short& vkey, DWORD& modifierState) noexcept;
bool _IsModified(const size_t paramCount);
DWORD _GetModifier(const size_t parameter);
bool _IsModified(const size_t paramCount) noexcept;
DWORD _GetModifier(const size_t parameter) noexcept;
bool _GetGenericVkey(const std::basic_string_view<size_t> parameters,
short& vkey) const;
@ -91,13 +91,13 @@ namespace Microsoft::Console::VirtualTerminal
std::vector<INPUT_RECORD>& input);
bool _GetWindowManipulationType(const std::basic_string_view<size_t> parameters,
unsigned int& function) const;
unsigned int& function) const noexcept;
static constexpr size_t DefaultLine = 1;
static constexpr size_t DefaultColumn = 1;
bool _GetXYPosition(const std::basic_string_view<size_t> parameters,
size_t& line,
size_t& column) const;
size_t& column) const noexcept;
bool _DoControlCharacter(const wchar_t wch, const bool writeAlt);
};

View File

@ -17,10 +17,7 @@ OutputStateMachineEngine::OutputStateMachineEngine(std::unique_ptr<ITermDispatch
_pTtyConnection(nullptr),
_lastPrintedChar(AsciiChars::NUL)
{
}
OutputStateMachineEngine::~OutputStateMachineEngine()
{
THROW_IF_NULL_ALLOC(_dispatch.get());
}
const ITermDispatch& OutputStateMachineEngine::Dispatch() const noexcept
@ -207,7 +204,7 @@ bool OutputStateMachineEngine::ActionEscDispatch(const wchar_t wch,
}
else if (intermediates.size() == 1)
{
const auto value = intermediates[0];
const auto value = til::at(intermediates, 0);
DesignateCharsetTypes designateType = DefaultDesignateCharsetType;
success = _GetDesignateType(value, designateType);
if (success)
@ -282,7 +279,7 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const wchar_t wch,
unsigned int function = 0;
DispatchTypes::EraseType eraseType = DispatchTypes::EraseType::ToEnd;
std::vector<DispatchTypes::GraphicsOptions> graphicsOptions;
DispatchTypes::AnsiStatusType deviceStatusType = (DispatchTypes::AnsiStatusType)-1; // there is no default status type.
DispatchTypes::AnsiStatusType deviceStatusType = static_cast<DispatchTypes::AnsiStatusType>(0); // there is no default status type.
size_t repeatCount = 0;
// This is all the args after the first arg, and the count of args not including the first one.
const auto remainingParams = parameters.size() > 1 ? parameters.substr(1) : std::basic_string_view<size_t>{};
@ -500,7 +497,7 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const wchar_t wch,
}
else if (intermediates.size() == 1)
{
const auto value = intermediates[0];
const auto value = til::at(intermediates, 0);
switch (value)
{
case L'?':
@ -653,7 +650,7 @@ bool OutputStateMachineEngine::_IntermediateSpaceDispatch(const wchar_t wchActio
// - <none>
// Return Value:
// - <none>
bool OutputStateMachineEngine::ActionClear()
bool OutputStateMachineEngine::ActionClear() noexcept
{
// do nothing.
return true;
@ -666,7 +663,7 @@ bool OutputStateMachineEngine::ActionClear()
// - <none>
// Return Value:
// - <none>
bool OutputStateMachineEngine::ActionIgnore()
bool OutputStateMachineEngine::ActionIgnore() noexcept
{
// do nothing.
return true;
@ -774,7 +771,7 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
// Return Value:
// - true iff we successfully dispatched the sequence.
bool OutputStateMachineEngine::ActionSs3Dispatch(const wchar_t /*wch*/,
const std::basic_string_view<size_t> /*parameters*/)
const std::basic_string_view<size_t> /*parameters*/) noexcept
{
// The output engine doesn't handle any SS3 sequences.
_ClearLastChar();
@ -825,7 +822,7 @@ bool OutputStateMachineEngine::_GetGraphicsOptions(const std::basic_string_view<
// Return Value:
// - True if we successfully pulled an erase type from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetEraseOperation(const std::basic_string_view<size_t> parameters,
DispatchTypes::EraseType& eraseType) const
DispatchTypes::EraseType& eraseType) const noexcept
{
bool success = false; // If we have too many parameters or don't know what to do with the given value, return false.
eraseType = DefaultEraseType; // if we fail, just put the default type in.
@ -839,7 +836,7 @@ bool OutputStateMachineEngine::_GetEraseOperation(const std::basic_string_view<s
else if (parameters.size() == 1)
{
// If there's one parameter, attempt to match it to the values we accept.
const auto param = static_cast<DispatchTypes::EraseType>(parameters[0]);
const auto param = static_cast<DispatchTypes::EraseType>(til::at(parameters, 0));
switch (param)
{
@ -864,7 +861,7 @@ bool OutputStateMachineEngine::_GetEraseOperation(const std::basic_string_view<s
// Return Value:
// - True if we successfully pulled the cursor distance from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetCursorDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const
size_t& distance) const noexcept
{
bool success = false;
distance = DefaultCursorDistance;
@ -877,7 +874,7 @@ bool OutputStateMachineEngine::_GetCursorDistance(const std::basic_string_view<s
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
distance = parameters[0];
distance = til::at(parameters, 0);
success = true;
}
@ -898,7 +895,7 @@ bool OutputStateMachineEngine::_GetCursorDistance(const std::basic_string_view<s
// Return Value:
// - True if we successfully pulled the scroll distance from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetScrollDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const
size_t& distance) const noexcept
{
bool success = false;
distance = DefaultScrollDistance;
@ -911,7 +908,7 @@ bool OutputStateMachineEngine::_GetScrollDistance(const std::basic_string_view<s
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
distance = parameters[0];
distance = til::at(parameters, 0);
success = true;
}
@ -932,7 +929,7 @@ bool OutputStateMachineEngine::_GetScrollDistance(const std::basic_string_view<s
// Return Value:
// - True if we successfully pulled the width from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetConsoleWidth(const std::basic_string_view<size_t> parameters,
size_t& consoleWidth) const
size_t& consoleWidth) const noexcept
{
bool success = false;
consoleWidth = DefaultConsoleWidth;
@ -945,7 +942,7 @@ bool OutputStateMachineEngine::_GetConsoleWidth(const std::basic_string_view<siz
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
consoleWidth = parameters[0];
consoleWidth = til::at(parameters, 0);
success = true;
}
@ -968,7 +965,7 @@ bool OutputStateMachineEngine::_GetConsoleWidth(const std::basic_string_view<siz
// - True if we successfully pulled the cursor coordinates from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetXYPosition(const std::basic_string_view<size_t> parameters,
size_t& line,
size_t& column) const
size_t& column) const noexcept
{
bool success = false;
line = DefaultLine;
@ -982,14 +979,14 @@ bool OutputStateMachineEngine::_GetXYPosition(const std::basic_string_view<size_
else if (parameters.size() == 1)
{
// If there's only one param, leave the default for the column, and retrieve the specified row.
line = parameters[0];
line = til::at(parameters, 0);
success = true;
}
else if (parameters.size() == 2)
{
// If there are exactly two parameters, use them.
line = parameters[0];
column = parameters[1];
line = til::at(parameters, 0);
column = til::at(parameters, 1);
success = true;
}
@ -1017,7 +1014,7 @@ bool OutputStateMachineEngine::_GetXYPosition(const std::basic_string_view<size_
// - True if we successfully pulled the margin settings from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetTopBottomMargins(const std::basic_string_view<size_t> parameters,
size_t& topMargin,
size_t& bottomMargin) const
size_t& bottomMargin) const noexcept
{
// Notes: (input -> state machine out)
// having only a top param is legal ([3;r -> 3,0)
@ -1036,14 +1033,14 @@ bool OutputStateMachineEngine::_GetTopBottomMargins(const std::basic_string_view
}
else if (parameters.size() == 1)
{
topMargin = parameters[0];
topMargin = til::at(parameters, 0);
success = true;
}
else if (parameters.size() == 2)
{
// If there are exactly two parameters, use them.
topMargin = parameters[0];
bottomMargin = parameters[1];
topMargin = til::at(parameters, 0);
bottomMargin = til::at(parameters, 1);
success = true;
}
@ -1061,15 +1058,15 @@ bool OutputStateMachineEngine::_GetTopBottomMargins(const std::basic_string_view
// Return Value:
// - True if we successfully found a device operation in the parameters stored. False otherwise.
bool OutputStateMachineEngine::_GetDeviceStatusOperation(const std::basic_string_view<size_t> parameters,
DispatchTypes::AnsiStatusType& statusType) const
DispatchTypes::AnsiStatusType& statusType) const noexcept
{
bool success = false;
statusType = (DispatchTypes::AnsiStatusType)0;
statusType = static_cast<DispatchTypes::AnsiStatusType>(0);
if (parameters.size() == 1)
{
// If there's one parameter, attempt to match it to the values we accept.
const auto param = parameters[0];
const auto param = til::at(parameters, 0);
switch (param)
{
@ -1112,7 +1109,7 @@ bool OutputStateMachineEngine::_GetPrivateModeParams(const std::basic_string_vie
// - parameters - The parameters to parse
// Return Value:
// - True if there were no parameters. False otherwise.
bool OutputStateMachineEngine::_VerifyHasNoParameters(const std::basic_string_view<size_t> parameters) const
bool OutputStateMachineEngine::_VerifyHasNoParameters(const std::basic_string_view<size_t> parameters) const noexcept
{
return parameters.empty();
}
@ -1124,7 +1121,7 @@ bool OutputStateMachineEngine::_VerifyHasNoParameters(const std::basic_string_vi
// - parameters - The parameters to parse
// Return Value:
// - True if the DA params were valid. False otherwise.
bool OutputStateMachineEngine::_VerifyDeviceAttributesParams(const std::basic_string_view<size_t> parameters) const
bool OutputStateMachineEngine::_VerifyDeviceAttributesParams(const std::basic_string_view<size_t> parameters) const noexcept
{
bool success = false;
@ -1134,7 +1131,7 @@ bool OutputStateMachineEngine::_VerifyDeviceAttributesParams(const std::basic_st
}
else if (parameters.size() == 1)
{
if (parameters[0] == 0)
if (til::at(parameters, 0) == 0)
{
success = true;
}
@ -1166,7 +1163,7 @@ bool OutputStateMachineEngine::_GetOscTitle(const std::wstring_view string,
// Return Value:
// - True if we successfully pulled the tab distance from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetTabDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const
size_t& distance) const noexcept
{
bool success = false;
distance = DefaultTabDistance;
@ -1179,7 +1176,7 @@ bool OutputStateMachineEngine::_GetTabDistance(const std::basic_string_view<size
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
distance = parameters[0];
distance = til::at(parameters, 0);
success = true;
}
@ -1200,7 +1197,7 @@ bool OutputStateMachineEngine::_GetTabDistance(const std::basic_string_view<size
// Return Value:
// - True if we successfully pulled the tab clear type from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetTabClearType(const std::basic_string_view<size_t> parameters,
size_t& clearType) const
size_t& clearType) const noexcept
{
bool success = false;
clearType = DefaultTabClearType;
@ -1213,7 +1210,7 @@ bool OutputStateMachineEngine::_GetTabClearType(const std::basic_string_view<siz
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
clearType = parameters[0];
clearType = til::at(parameters, 0);
success = true;
}
return success;
@ -1227,7 +1224,7 @@ bool OutputStateMachineEngine::_GetTabClearType(const std::basic_string_view<siz
// Return Value:
// - True if we successfully pulled the designate type from the intermediate we've stored. False otherwise.
bool OutputStateMachineEngine::_GetDesignateType(const wchar_t intermediate,
DesignateCharsetTypes& designateType) const
DesignateCharsetTypes& designateType) const noexcept
{
bool success = false;
designateType = DefaultDesignateCharsetType;
@ -1265,7 +1262,7 @@ bool OutputStateMachineEngine::_GetDesignateType(const wchar_t intermediate,
// ProcessString, and dispatch only at the end of the sequence.
// Return Value:
// - True iff we should manually dispatch on the last character of a string.
bool OutputStateMachineEngine::FlushAtEndOfString() const
bool OutputStateMachineEngine::FlushAtEndOfString() const noexcept
{
return false;
}
@ -1280,7 +1277,7 @@ bool OutputStateMachineEngine::FlushAtEndOfString() const
// Return Value:
// - True iff we should return to the Ground state when the state machine
// encounters a Control (C0) character in the Escape state.
bool OutputStateMachineEngine::DispatchControlCharsFromEscape() const
bool OutputStateMachineEngine::DispatchControlCharsFromEscape() const noexcept
{
return false;
}
@ -1292,7 +1289,7 @@ bool OutputStateMachineEngine::DispatchControlCharsFromEscape() const
// Return Value:
// - True iff we should dispatch in the Escape state when we encounter a
// Intermediate character.
bool OutputStateMachineEngine::DispatchIntermediatesFromEscape() const
bool OutputStateMachineEngine::DispatchIntermediatesFromEscape() const noexcept
{
return false;
}
@ -1305,7 +1302,7 @@ bool OutputStateMachineEngine::DispatchIntermediatesFromEscape() const
// Return Value:
// - true iff the character is a hex character.
bool OutputStateMachineEngine::s_HexToUint(const wchar_t wch,
unsigned int& value)
unsigned int& value) noexcept
{
value = 0;
bool success = false;
@ -1333,7 +1330,7 @@ bool OutputStateMachineEngine::s_HexToUint(const wchar_t wch,
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool OutputStateMachineEngine::s_IsNumber(const wchar_t wch)
static constexpr bool _isNumber(const wchar_t wch) noexcept
{
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
}
@ -1344,7 +1341,7 @@ bool OutputStateMachineEngine::s_IsNumber(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool OutputStateMachineEngine::s_IsHexNumber(const wchar_t wch)
static constexpr bool _isHexNumber(const wchar_t wch) noexcept
{
return (wch >= L'0' && wch <= L'9') || // 0x30 - 0x39
(wch >= L'A' && wch <= L'F') ||
@ -1363,11 +1360,11 @@ bool OutputStateMachineEngine::s_IsHexNumber(const wchar_t wch)
// Return Value:
// - True if a color was successfully parsed
bool OutputStateMachineEngine::s_ParseColorSpec(const std::wstring_view string,
DWORD& rgb)
DWORD& rgb) noexcept
{
bool foundRGB = false;
bool foundValidColorSpec = false;
unsigned int rguiColorValues[3] = { 0 };
std::array<unsigned int, 3> colorValues = { 0 };
bool success = false;
// We can have anywhere between [11,15] characters
// 9 "rgb:h/h/h"
@ -1398,18 +1395,18 @@ bool OutputStateMachineEngine::s_ParseColorSpec(const std::wstring_view string,
for (size_t component = 0; component < 3; component++)
{
bool foundColor = false;
unsigned int* const pValue = &(rguiColorValues[component]);
auto& value = colorValues.at(component);
for (size_t i = 0; i < 3; i++)
{
const wchar_t wch = *curr++;
if (s_IsHexNumber(wch))
if (_isHexNumber(wch))
{
*pValue *= 16;
value *= 16;
unsigned int intVal = 0;
if (s_HexToUint(wch, intVal))
{
*pValue += intVal;
value += intVal;
}
else
{
@ -1449,9 +1446,9 @@ bool OutputStateMachineEngine::s_ParseColorSpec(const std::wstring_view string,
// Only if we find a valid colorspec can we pass it out successfully.
if (foundValidColorSpec)
{
DWORD color = RGB(LOBYTE(rguiColorValues[0]),
LOBYTE(rguiColorValues[1]),
LOBYTE(rguiColorValues[2]));
DWORD color = RGB(LOBYTE(colorValues.at(0)),
LOBYTE(colorValues.at(1)),
LOBYTE(colorValues.at(2)));
rgb = color;
success = true;
@ -1473,7 +1470,7 @@ bool OutputStateMachineEngine::s_ParseColorSpec(const std::wstring_view string,
// - True if a table index and color was parsed successfully. False otherwise.
bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view string,
size_t& tableIndex,
DWORD& rgb) const
DWORD& rgb) const noexcept
{
tableIndex = 0;
rgb = 0;
@ -1497,7 +1494,7 @@ bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view stri
for (size_t i = 0; i < 4; i++)
{
const wchar_t wch = string.at(current);
if (s_IsNumber(wch))
if (_isNumber(wch))
{
_TableIndex *= 10;
_TableIndex += wch - L'0';
@ -1546,7 +1543,7 @@ bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view stri
// Return Value:
// - True if a table index and color was parsed successfully. False otherwise.
bool OutputStateMachineEngine::_GetOscSetColor(const std::wstring_view string,
DWORD& rgb) const
DWORD& rgb) const noexcept
{
rgb = 0;
@ -1574,14 +1571,14 @@ bool OutputStateMachineEngine::_GetOscSetColor(const std::wstring_view string,
// Return Value:
// - True iff we successfully pulled the function type from the parameters
bool OutputStateMachineEngine::_GetWindowManipulationType(const std::basic_string_view<size_t> parameters,
unsigned int& function) const
unsigned int& function) const noexcept
{
bool success = false;
function = DefaultWindowManipulationType;
if (parameters.size() > 0)
{
switch (parameters[0])
switch (til::at(parameters, 0))
{
case DispatchTypes::WindowManipulationType::RefreshWindow:
function = DispatchTypes::WindowManipulationType::RefreshWindow;
@ -1608,7 +1605,7 @@ bool OutputStateMachineEngine::_GetWindowManipulationType(const std::basic_strin
// Return Value:
// - True if we successfully pulled the cursor style from the parameters we've stored. False otherwise.
bool OutputStateMachineEngine::_GetCursorStyle(const std::basic_string_view<size_t> parameters,
DispatchTypes::CursorStyle& cursorStyle) const
DispatchTypes::CursorStyle& cursorStyle) const noexcept
{
bool success = false;
cursorStyle = DefaultCursorStyle;
@ -1621,7 +1618,7 @@ bool OutputStateMachineEngine::_GetCursorStyle(const std::basic_string_view<size
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
cursorStyle = (DispatchTypes::CursorStyle)parameters[0];
cursorStyle = (DispatchTypes::CursorStyle)til::at(parameters, 0);
success = true;
}
@ -1670,7 +1667,7 @@ bool OutputStateMachineEngine::_GetRepeatCount(std::basic_string_view<size_t> pa
else if (parameters.size() == 1)
{
// If there's one parameter, use it.
repeatCount = parameters[0];
repeatCount = til::at(parameters, 0);
success = true;
}

View File

@ -23,7 +23,6 @@ namespace Microsoft::Console::VirtualTerminal
{
public:
OutputStateMachineEngine(std::unique_ptr<ITermDispatch> pDispatch);
~OutputStateMachineEngine();
bool ActionExecute(const wchar_t wch) override;
bool ActionExecuteFromEscape(const wchar_t wch) override;
@ -41,20 +40,20 @@ namespace Microsoft::Console::VirtualTerminal
const std::basic_string_view<wchar_t> intermediates,
const std::basic_string_view<size_t> parameters) override;
bool ActionClear() override;
bool ActionClear() noexcept override;
bool ActionIgnore() override;
bool ActionIgnore() noexcept override;
bool ActionOscDispatch(const wchar_t wch,
const size_t parameter,
const std::wstring_view string) override;
bool ActionSs3Dispatch(const wchar_t wch,
const std::basic_string_view<size_t> parameters) override;
const std::basic_string_view<size_t> parameters) noexcept override;
bool FlushAtEndOfString() const override;
bool DispatchControlCharsFromEscape() const override;
bool DispatchIntermediatesFromEscape() const override;
bool FlushAtEndOfString() const noexcept override;
bool DispatchControlCharsFromEscape() const noexcept override;
bool DispatchIntermediatesFromEscape() const noexcept override;
void SetTerminalConnection(Microsoft::Console::ITerminalOutputConnection* const pTtyConnection,
std::function<bool()> pfnFlushToTerminal);
@ -152,32 +151,32 @@ namespace Microsoft::Console::VirtualTerminal
static constexpr DispatchTypes::EraseType DefaultEraseType = DispatchTypes::EraseType::ToEnd;
bool _GetEraseOperation(const std::basic_string_view<size_t> parameters,
DispatchTypes::EraseType& eraseType) const;
DispatchTypes::EraseType& eraseType) const noexcept;
static constexpr size_t DefaultCursorDistance = 1;
bool _GetCursorDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const;
size_t& distance) const noexcept;
static constexpr size_t DefaultScrollDistance = 1;
bool _GetScrollDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const;
size_t& distance) const noexcept;
static constexpr size_t DefaultConsoleWidth = 80;
bool _GetConsoleWidth(const std::basic_string_view<size_t> parameters,
size_t& consoleWidth) const;
size_t& consoleWidth) const noexcept;
static constexpr size_t DefaultLine = 1;
static constexpr size_t DefaultColumn = 1;
bool _GetXYPosition(const std::basic_string_view<size_t> parameters,
size_t& line,
size_t& column) const;
size_t& column) const noexcept;
bool _GetDeviceStatusOperation(const std::basic_string_view<size_t> parameters,
DispatchTypes::AnsiStatusType& statusType) const;
DispatchTypes::AnsiStatusType& statusType) const noexcept;
bool _VerifyHasNoParameters(const std::basic_string_view<size_t> parameters) const;
bool _VerifyHasNoParameters(const std::basic_string_view<size_t> parameters) const noexcept;
bool _VerifyDeviceAttributesParams(const std::basic_string_view<size_t> parameters) const;
bool _VerifyDeviceAttributesParams(const std::basic_string_view<size_t> parameters) const noexcept;
bool _GetPrivateModeParams(const std::basic_string_view<size_t> parameters,
std::vector<DispatchTypes::PrivateModeParams>& privateModes) const;
@ -186,44 +185,42 @@ namespace Microsoft::Console::VirtualTerminal
static constexpr size_t DefaultBottomMargin = 0;
bool _GetTopBottomMargins(const std::basic_string_view<size_t> parameters,
size_t& topMargin,
size_t& bottomMargin) const;
size_t& bottomMargin) const noexcept;
bool _GetOscTitle(const std::wstring_view string,
std::wstring& title) const;
static constexpr size_t DefaultTabDistance = 1;
bool _GetTabDistance(const std::basic_string_view<size_t> parameters,
size_t& distance) const;
size_t& distance) const noexcept;
static constexpr size_t DefaultTabClearType = 0;
bool _GetTabClearType(const std::basic_string_view<size_t> parameters,
size_t& clearType) const;
size_t& clearType) const noexcept;
static constexpr DesignateCharsetTypes DefaultDesignateCharsetType = DesignateCharsetTypes::G0;
bool _GetDesignateType(const wchar_t intermediate,
DesignateCharsetTypes& designateType) const;
DesignateCharsetTypes& designateType) const noexcept;
static constexpr DispatchTypes::WindowManipulationType DefaultWindowManipulationType = DispatchTypes::WindowManipulationType::Invalid;
bool _GetWindowManipulationType(const std::basic_string_view<size_t> parameters,
unsigned int& function) const;
unsigned int& function) const noexcept;
static bool s_HexToUint(const wchar_t wch,
unsigned int& value);
static bool s_IsNumber(const wchar_t wch);
static bool s_IsHexNumber(const wchar_t wch);
unsigned int& value) noexcept;
bool _GetOscSetColorTable(const std::wstring_view string,
size_t& tableIndex,
DWORD& rgb) const;
DWORD& rgb) const noexcept;
static bool s_ParseColorSpec(const std::wstring_view string,
DWORD& rgb);
DWORD& rgb) noexcept;
bool _GetOscSetColor(const std::wstring_view string,
DWORD& rgb) const;
DWORD& rgb) const noexcept;
static constexpr DispatchTypes::CursorStyle DefaultCursorStyle = DispatchTypes::CursorStyle::BlinkingBlockDefault;
bool _GetCursorStyle(const std::basic_string_view<size_t> parameters,
DispatchTypes::CursorStyle& cursorStyle) const;
DispatchTypes::CursorStyle& cursorStyle) const noexcept;
static constexpr size_t DefaultRepeatCount = 1;
bool _GetRepeatCount(const std::basic_string_view<size_t> parameters,

View File

@ -33,15 +33,14 @@ IStateMachineEngine& StateMachine::Engine() noexcept
}
// Routine Description:
// - Determines if a character indicates an action that should be taken in the ground state -
// These are C0 characters and the C1 [single-character] CSI.
// - Determines if a character is a valid number character, 0-9.
// Arguments:
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsActionableFromGround(const wchar_t wch)
static constexpr bool _isNumber(const wchar_t wch) noexcept
{
return (wch <= AsciiChars::US) || s_IsC1Csi(wch) || s_IsDelete(wch);
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
}
// Routine Description:
@ -52,7 +51,7 @@ bool StateMachine::s_IsActionableFromGround(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsC0Code(const wchar_t wch)
static constexpr bool _isC0Code(const wchar_t wch) noexcept
{
return (wch >= AsciiChars::NUL && wch <= AsciiChars::ETB) ||
wch == AsciiChars::EM ||
@ -78,7 +77,7 @@ bool StateMachine::s_IsC0Code(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsC1Csi(const wchar_t wch)
static constexpr bool _isC1Csi(const wchar_t wch) noexcept
{
return wch == L'\x9b';
}
@ -92,7 +91,7 @@ bool StateMachine::s_IsC1Csi(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsIntermediate(const wchar_t wch)
static constexpr bool _isIntermediate(const wchar_t wch) noexcept
{
return wch >= L' ' && wch <= L'/'; // 0x20 - 0x2F
}
@ -103,7 +102,7 @@ bool StateMachine::s_IsIntermediate(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsDelete(const wchar_t wch)
static constexpr bool _isDelete(const wchar_t wch) noexcept
{
return wch == AsciiChars::DEL;
}
@ -115,7 +114,7 @@ bool StateMachine::s_IsDelete(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsEscape(const wchar_t wch)
static constexpr bool _isEscape(const wchar_t wch) noexcept
{
return wch == AsciiChars::ESC;
}
@ -127,7 +126,7 @@ bool StateMachine::s_IsEscape(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsCsiIndicator(const wchar_t wch)
static constexpr bool _isCsiIndicator(const wchar_t wch) noexcept
{
return wch == L'['; // 0x5B
}
@ -140,7 +139,7 @@ bool StateMachine::s_IsCsiIndicator(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsCsiDelimiter(const wchar_t wch)
static constexpr bool _isCsiDelimiter(const wchar_t wch) noexcept
{
return wch == L';'; // 0x3B
}
@ -152,7 +151,7 @@ bool StateMachine::s_IsCsiDelimiter(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsCsiParamValue(const wchar_t wch)
static constexpr bool _isCsiParamValue(const wchar_t wch) noexcept
{
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
}
@ -164,7 +163,7 @@ bool StateMachine::s_IsCsiParamValue(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsCsiPrivateMarker(const wchar_t wch)
static constexpr bool _isCsiPrivateMarker(const wchar_t wch) noexcept
{
return wch == L'<' || wch == L'=' || wch == L'>' || wch == L'?'; // 0x3C - 0x3F
}
@ -175,7 +174,7 @@ bool StateMachine::s_IsCsiPrivateMarker(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsCsiInvalid(const wchar_t wch)
static constexpr bool _isCsiInvalid(const wchar_t wch) noexcept
{
return wch == L':'; // 0x3A
}
@ -189,7 +188,7 @@ bool StateMachine::s_IsCsiInvalid(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsSs3Indicator(const wchar_t wch)
static constexpr bool _isSs3Indicator(const wchar_t wch) noexcept
{
return wch == L'O'; // 0x4F
}
@ -201,7 +200,7 @@ bool StateMachine::s_IsSs3Indicator(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscIndicator(const wchar_t wch)
static constexpr bool _isOscIndicator(const wchar_t wch) noexcept
{
return wch == L']'; // 0x5D
}
@ -214,7 +213,7 @@ bool StateMachine::s_IsOscIndicator(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscDelimiter(const wchar_t wch)
static constexpr bool _isOscDelimiter(const wchar_t wch) noexcept
{
return wch == L';'; // 0x3B
}
@ -227,9 +226,9 @@ bool StateMachine::s_IsOscDelimiter(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscParamValue(const wchar_t wch)
static constexpr bool _isOscParamValue(const wchar_t wch) noexcept
{
return s_IsNumber(wch); // 0x30 - 0x39
return _isNumber(wch); // 0x30 - 0x39
}
// Routine Description:
@ -238,7 +237,7 @@ bool StateMachine::s_IsOscParamValue(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscTerminationInitiator(const wchar_t wch)
static constexpr bool _isOscTerminationInitiator(const wchar_t wch) noexcept
{
return wch == AsciiChars::ESC;
}
@ -249,7 +248,7 @@ bool StateMachine::s_IsOscTerminationInitiator(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscInvalid(const wchar_t wch)
static constexpr bool _isOscInvalid(const wchar_t wch) noexcept
{
return wch <= L'\x17' ||
wch == L'\x19' ||
@ -263,20 +262,21 @@ bool StateMachine::s_IsOscInvalid(const wchar_t wch)
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsOscTerminator(const wchar_t wch)
static constexpr bool _isOscTerminator(const wchar_t wch) noexcept
{
return wch == L'\x7' || wch == L'\x9C'; // Bell character or C1 terminator
}
// Routine Description:
// - Determines if a character is a valid number character, 0-9.
// - Determines if a character indicates an action that should be taken in the ground state -
// These are C0 characters and the C1 [single-character] CSI.
// Arguments:
// - wch - Character to check.
// Return Value:
// - True if it is. False if it isn't.
bool StateMachine::s_IsNumber(const wchar_t wch)
static constexpr bool _isActionableFromGround(const wchar_t wch) noexcept
{
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
return (wch <= AsciiChars::US) || _isC1Csi(wch) || _isDelete(wch);
}
// Routine Description:
@ -328,7 +328,7 @@ void StateMachine::_ActionEscDispatch(const wchar_t wch)
{
_trace.TraceOnAction(L"EscDispatch");
bool success = _engine->ActionEscDispatch(wch, { _intermediates.data(), _intermediates.size() });
const bool success = _engine->ActionEscDispatch(wch, { _intermediates.data(), _intermediates.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
@ -351,9 +351,9 @@ void StateMachine::_ActionCsiDispatch(const wchar_t wch)
{
_trace.TraceOnAction(L"CsiDispatch");
bool success = _engine->ActionCsiDispatch(wch,
{ _intermediates.data(), _intermediates.size() },
{ _parameters.data(), _parameters.size() });
const bool success = _engine->ActionCsiDispatch(wch,
{ _intermediates.data(), _intermediates.size() },
{ _parameters.data(), _parameters.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
@ -438,7 +438,7 @@ void StateMachine::_ActionClear()
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionIgnore()
void StateMachine::_ActionIgnore() noexcept
{
// do nothing.
_trace.TraceOnAction(L"Ignore");
@ -481,7 +481,7 @@ void StateMachine::_ActionOscDispatch(const wchar_t wch)
{
_trace.TraceOnAction(L"OscDispatch");
bool success = _engine->ActionOscDispatch(wch, _oscParameter, _oscString);
const bool success = _engine->ActionOscDispatch(wch, _oscParameter, _oscString);
// Trace the result.
_trace.DispatchSequenceTrace(success);
@ -504,7 +504,7 @@ void StateMachine::_ActionSs3Dispatch(const wchar_t wch)
{
_trace.TraceOnAction(L"Ss3Dispatch");
bool success = _engine->ActionSs3Dispatch(wch, { _parameters.data(), _parameters.size() });
const bool success = _engine->ActionSs3Dispatch(wch, { _parameters.data(), _parameters.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
@ -525,7 +525,7 @@ void StateMachine::_ActionSs3Dispatch(const wchar_t wch)
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterGround()
void StateMachine::_EnterGround() noexcept
{
_state = VTStates::Ground;
_trace.TraceStateChange(L"Ground");
@ -555,7 +555,7 @@ void StateMachine::_EnterEscape()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterEscapeIntermediate()
void StateMachine::_EnterEscapeIntermediate() noexcept
{
_state = VTStates::EscapeIntermediate;
_trace.TraceStateChange(L"EscapeIntermediate");
@ -584,7 +584,7 @@ void StateMachine::_EnterCsiEntry()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterCsiParam()
void StateMachine::_EnterCsiParam() noexcept
{
_state = VTStates::CsiParam;
_trace.TraceStateChange(L"CsiParam");
@ -599,7 +599,7 @@ void StateMachine::_EnterCsiParam()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterCsiIgnore()
void StateMachine::_EnterCsiIgnore() noexcept
{
_state = VTStates::CsiIgnore;
_trace.TraceStateChange(L"CsiIgnore");
@ -614,7 +614,7 @@ void StateMachine::_EnterCsiIgnore()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterCsiIntermediate()
void StateMachine::_EnterCsiIntermediate() noexcept
{
_state = VTStates::CsiIntermediate;
_trace.TraceStateChange(L"CsiIntermediate");
@ -628,7 +628,7 @@ void StateMachine::_EnterCsiIntermediate()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterOscParam()
void StateMachine::_EnterOscParam() noexcept
{
_state = VTStates::OscParam;
_trace.TraceStateChange(L"OscParam");
@ -642,7 +642,7 @@ void StateMachine::_EnterOscParam()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterOscString()
void StateMachine::_EnterOscString() noexcept
{
_state = VTStates::OscString;
_trace.TraceStateChange(L"OscString");
@ -657,7 +657,7 @@ void StateMachine::_EnterOscString()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterOscTermination()
void StateMachine::_EnterOscTermination() noexcept
{
_state = VTStates::OscTermination;
_trace.TraceStateChange(L"OscTermination");
@ -686,7 +686,7 @@ void StateMachine::_EnterSs3Entry()
// - <none>
// Return Value:
// - <none>
void StateMachine::_EnterSs3Param()
void StateMachine::_EnterSs3Param() noexcept
{
_state = VTStates::Ss3Param;
_trace.TraceStateChange(L"Ss3Param");
@ -705,11 +705,11 @@ void StateMachine::_EnterSs3Param()
void StateMachine::_EventGround(const wchar_t wch)
{
_trace.TraceOnEvent(L"Ground");
if (s_IsC0Code(wch) || s_IsDelete(wch))
if (_isC0Code(wch) || _isDelete(wch))
{
_ActionExecute(wch);
}
else if (s_IsC1Csi(wch))
else if (_isC1Csi(wch))
{
_EnterCsiEntry();
}
@ -734,7 +734,7 @@ void StateMachine::_EventGround(const wchar_t wch)
void StateMachine::_EventEscape(const wchar_t wch)
{
_trace.TraceOnEvent(L"Escape");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
if (_engine->DispatchControlCharsFromEscape())
{
@ -746,11 +746,11 @@ void StateMachine::_EventEscape(const wchar_t wch)
_ActionExecute(wch);
}
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
if (_engine->DispatchIntermediatesFromEscape())
{
@ -763,15 +763,15 @@ void StateMachine::_EventEscape(const wchar_t wch)
_EnterEscapeIntermediate();
}
}
else if (s_IsCsiIndicator(wch))
else if (_isCsiIndicator(wch))
{
_EnterCsiEntry();
}
else if (s_IsOscIndicator(wch))
else if (_isOscIndicator(wch))
{
_EnterOscParam();
}
else if (s_IsSs3Indicator(wch))
else if (_isSs3Indicator(wch))
{
_EnterSs3Entry();
}
@ -796,15 +796,15 @@ void StateMachine::_EventEscape(const wchar_t wch)
void StateMachine::_EventEscapeIntermediate(const wchar_t wch)
{
_trace.TraceOnEvent(L"EscapeIntermediate");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
_ActionCollect(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
@ -832,29 +832,29 @@ void StateMachine::_EventEscapeIntermediate(const wchar_t wch)
void StateMachine::_EventCsiEntry(const wchar_t wch)
{
_trace.TraceOnEvent(L"CsiEntry");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
_ActionCollect(wch);
_EnterCsiIntermediate();
}
else if (s_IsCsiInvalid(wch))
else if (_isCsiInvalid(wch))
{
_EnterCsiIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiDelimiter(wch))
else if (_isCsiParamValue(wch) || _isCsiDelimiter(wch))
{
_ActionParam(wch);
_EnterCsiParam();
}
else if (s_IsCsiPrivateMarker(wch))
else if (_isCsiPrivateMarker(wch))
{
_ActionCollect(wch);
_EnterCsiParam();
@ -881,19 +881,19 @@ void StateMachine::_EventCsiEntry(const wchar_t wch)
void StateMachine::_EventCsiIntermediate(const wchar_t wch)
{
_trace.TraceOnEvent(L"CsiIntermediate");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
_ActionCollect(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiInvalid(wch) || s_IsCsiDelimiter(wch) || s_IsCsiPrivateMarker(wch))
else if (_isCsiParamValue(wch) || _isCsiInvalid(wch) || _isCsiDelimiter(wch) || _isCsiPrivateMarker(wch))
{
_EnterCsiIgnore();
}
@ -919,19 +919,19 @@ void StateMachine::_EventCsiIntermediate(const wchar_t wch)
void StateMachine::_EventCsiIgnore(const wchar_t wch)
{
_trace.TraceOnEvent(L"CsiIgnore");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
_ActionIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiInvalid(wch) || s_IsCsiDelimiter(wch) || s_IsCsiPrivateMarker(wch))
else if (_isCsiParamValue(wch) || _isCsiInvalid(wch) || _isCsiDelimiter(wch) || _isCsiPrivateMarker(wch))
{
_ActionIgnore();
}
@ -957,24 +957,24 @@ void StateMachine::_EventCsiIgnore(const wchar_t wch)
void StateMachine::_EventCsiParam(const wchar_t wch)
{
_trace.TraceOnEvent(L"CsiParam");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiDelimiter(wch))
else if (_isCsiParamValue(wch) || _isCsiDelimiter(wch))
{
_ActionParam(wch);
}
else if (s_IsIntermediate(wch))
else if (_isIntermediate(wch))
{
_ActionCollect(wch);
_EnterCsiIntermediate();
}
else if (s_IsCsiInvalid(wch) || s_IsCsiPrivateMarker(wch))
else if (_isCsiInvalid(wch) || _isCsiPrivateMarker(wch))
{
_EnterCsiIgnore();
}
@ -998,15 +998,15 @@ void StateMachine::_EventCsiParam(const wchar_t wch)
void StateMachine::_EventOscParam(const wchar_t wch)
{
_trace.TraceOnEvent(L"OscParam");
if (s_IsOscTerminator(wch))
if (_isOscTerminator(wch))
{
_EnterGround();
}
else if (s_IsOscParamValue(wch))
else if (_isOscParamValue(wch))
{
_ActionOscParam(wch);
}
else if (s_IsOscDelimiter(wch))
else if (_isOscDelimiter(wch))
{
_EnterOscString();
}
@ -1031,16 +1031,16 @@ void StateMachine::_EventOscParam(const wchar_t wch)
void StateMachine::_EventOscString(const wchar_t wch)
{
_trace.TraceOnEvent(L"OscString");
if (s_IsOscTerminator(wch))
if (_isOscTerminator(wch))
{
_ActionOscDispatch(wch);
_EnterGround();
}
else if (s_IsOscTerminationInitiator(wch))
else if (_isOscTerminationInitiator(wch))
{
_EnterOscTermination();
}
else if (s_IsOscInvalid(wch))
else if (_isOscInvalid(wch))
{
_ActionIgnore();
}
@ -1085,21 +1085,21 @@ void StateMachine::_EventOscTermination(const wchar_t wch)
void StateMachine::_EventSs3Entry(const wchar_t wch)
{
_trace.TraceOnEvent(L"Ss3Entry");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsCsiInvalid(wch))
else if (_isCsiInvalid(wch))
{
// It's safe for us to go into the CSI ignore here, because both SS3 and
// CSI sequences ignore characters the same way.
_EnterCsiIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiDelimiter(wch))
else if (_isCsiParamValue(wch) || _isCsiDelimiter(wch))
{
_ActionParam(wch);
_EnterSs3Param();
@ -1126,19 +1126,19 @@ void StateMachine::_EventSs3Entry(const wchar_t wch)
void StateMachine::_EventSs3Param(const wchar_t wch)
{
_trace.TraceOnEvent(L"Ss3Param");
if (s_IsC0Code(wch))
if (_isC0Code(wch))
{
_ActionExecute(wch);
}
else if (s_IsDelete(wch))
else if (_isDelete(wch))
{
_ActionIgnore();
}
else if (s_IsCsiParamValue(wch) || s_IsCsiDelimiter(wch))
else if (_isCsiParamValue(wch) || _isCsiDelimiter(wch))
{
_ActionParam(wch);
}
else if (s_IsCsiInvalid(wch) || s_IsCsiPrivateMarker(wch))
else if (_isCsiInvalid(wch) || _isCsiPrivateMarker(wch))
{
_EnterCsiIgnore();
}
@ -1166,7 +1166,7 @@ void StateMachine::ProcessCharacter(const wchar_t wch)
_ActionExecute(wch);
_EnterGround();
}
else if (s_IsEscape(wch) && _state != VTStates::OscString)
else if (_isEscape(wch) && _state != VTStates::OscString)
{
// Don't go to escape from the OSC string state - ESC can be used to
// terminate OSC strings.
@ -1259,7 +1259,7 @@ void StateMachine::ProcessString(const std::wstring_view string)
}
else
{
if (s_IsActionableFromGround(string.at(current))) // If the current char is the start of an escape sequence, or should be executed in ground state...
if (_isActionableFromGround(string.at(current))) // If the current char is the start of an escape sequence, or should be executed in ground state...
{
_engine->ActionPrintString(_run); // ... print all the chars leading up to it as part of the run...
_trace.DispatchPrintRunTrace(_run);
@ -1356,7 +1356,7 @@ void StateMachine::ProcessString(const std::wstring_view string)
// - <none>
// Return Value:
// - <none>
void StateMachine::ResetState()
void StateMachine::ResetState() noexcept
{
_EnterGround();
}

View File

@ -34,7 +34,7 @@ namespace Microsoft::Console::VirtualTerminal
void ProcessCharacter(const wchar_t wch);
void ProcessString(const std::wstring_view string);
void ResetState();
void ResetState() noexcept;
bool FlushToTerminal();
@ -42,26 +42,6 @@ namespace Microsoft::Console::VirtualTerminal
IStateMachineEngine& Engine() noexcept;
private:
static bool s_IsActionableFromGround(const wchar_t wch);
static bool s_IsC0Code(const wchar_t wch);
static bool s_IsC1Csi(const wchar_t wch);
static bool s_IsIntermediate(const wchar_t wch);
static bool s_IsDelete(const wchar_t wch);
static bool s_IsEscape(const wchar_t wch);
static bool s_IsCsiIndicator(const wchar_t wch);
static bool s_IsCsiDelimiter(const wchar_t wch);
static bool s_IsCsiParamValue(const wchar_t wch);
static bool s_IsCsiPrivateMarker(const wchar_t wch);
static bool s_IsCsiInvalid(const wchar_t wch);
static bool s_IsOscIndicator(const wchar_t wch);
static bool s_IsOscDelimiter(const wchar_t wch);
static bool s_IsOscParamValue(const wchar_t wch);
static bool s_IsOscInvalid(const wchar_t wch);
static bool s_IsOscTerminator(const wchar_t wch);
static bool s_IsOscTerminationInitiator(const wchar_t wch);
static bool s_IsNumber(const wchar_t wch);
static bool s_IsSs3Indicator(const wchar_t wch);
void _ActionExecute(const wchar_t wch);
void _ActionExecuteFromEscape(const wchar_t wch);
void _ActionPrint(const wchar_t wch);
@ -75,20 +55,20 @@ namespace Microsoft::Console::VirtualTerminal
void _ActionSs3Dispatch(const wchar_t wch);
void _ActionClear();
void _ActionIgnore();
void _ActionIgnore() noexcept;
void _EnterGround();
void _EnterGround() noexcept;
void _EnterEscape();
void _EnterEscapeIntermediate();
void _EnterEscapeIntermediate() noexcept;
void _EnterCsiEntry();
void _EnterCsiParam();
void _EnterCsiIgnore();
void _EnterCsiIntermediate();
void _EnterOscParam();
void _EnterOscString();
void _EnterOscTermination();
void _EnterCsiParam() noexcept;
void _EnterCsiIgnore() noexcept;
void _EnterCsiIntermediate() noexcept;
void _EnterOscParam() noexcept;
void _EnterOscString() noexcept;
void _EnterOscTermination() noexcept;
void _EnterSs3Entry();
void _EnterSs3Param();
void _EnterSs3Param() noexcept;
void _EventGround(const wchar_t wch);
void _EventEscape(const wchar_t wch);

View File

@ -5,6 +5,13 @@
#include "telemetry.hpp"
#pragma warning(push)
#pragma warning(disable : 26494) // _Tlgdata uninitialized from TraceLoggingWrite
#pragma warning(disable : 26477) // Use nullptr instead of NULL or 0 from TraceLoggingWrite
#pragma warning(disable : 26485) // _Tlgdata, no array to pointer decay from TraceLoggingWrite
#pragma warning(disable : 26446) // Prefer gsl::at over unchecked subscript from TraceLoggingLevel
#pragma warning(disable : 26482) // Only index to arrays with constant expressions from TraceLoggingLevel
TRACELOGGING_DEFINE_PROVIDER(g_hConsoleVirtTermParserEventTraceProvider,
"Microsoft.Windows.Console.VirtualTerminal.Parser",
// {c9ba2a84-d3ca-5e19-2bd6-776a0910cb9d}
@ -15,7 +22,7 @@ using namespace Microsoft::Console::VirtualTerminal;
#pragma warning(push)
// Disable 4351 so we can initialize the arrays to 0 without a warning.
#pragma warning(disable : 4351)
TermTelemetry::TermTelemetry() :
TermTelemetry::TermTelemetry() noexcept :
_uiTimesUsedCurrent(0),
_uiTimesFailedCurrent(0),
_uiTimesFailedOutsideRangeCurrent(0),
@ -34,8 +41,12 @@ TermTelemetry::TermTelemetry() :
TermTelemetry::~TermTelemetry()
{
WriteFinalTraceLog();
TraceLoggingUnregister(g_hConsoleVirtTermParserEventTraceProvider);
try
{
WriteFinalTraceLog();
TraceLoggingUnregister(g_hConsoleVirtTermParserEventTraceProvider);
}
CATCH_LOG()
}
// Routine Description:
@ -45,7 +56,7 @@ TermTelemetry::~TermTelemetry()
// - code - VT100 code.
// Return Value:
// - <none>
void TermTelemetry::Log(const Codes code)
void TermTelemetry::Log(const Codes code) noexcept
{
// Initially we wanted to pass over a string (ex. "CUU") and use a dictionary data type to hold the counts.
// However we would have to search through the dictionary every time we called this method, so we decided
@ -63,7 +74,7 @@ void TermTelemetry::Log(const Codes code)
// - code - VT100 code.
// Return Value:
// - <none>
void TermTelemetry::LogFailed(const wchar_t wch)
void TermTelemetry::LogFailed(const wchar_t wch) noexcept
{
if (wch > CHAR_MAX)
{
@ -85,11 +96,11 @@ void TermTelemetry::LogFailed(const wchar_t wch)
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesUsedCurrent()
unsigned int TermTelemetry::GetAndResetTimesUsedCurrent() noexcept
{
unsigned int uiTemp = _uiTimesUsedCurrent;
const auto temp = _uiTimesUsedCurrent;
_uiTimesUsedCurrent = 0;
return uiTemp;
return temp;
}
// Routine Description:
@ -99,11 +110,11 @@ unsigned int TermTelemetry::GetAndResetTimesUsedCurrent()
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesFailedCurrent()
unsigned int TermTelemetry::GetAndResetTimesFailedCurrent() noexcept
{
unsigned int uiTemp = _uiTimesFailedCurrent;
const auto temp = _uiTimesFailedCurrent;
_uiTimesFailedCurrent = 0;
return uiTemp;
return temp;
}
// Routine Description:
@ -113,11 +124,11 @@ unsigned int TermTelemetry::GetAndResetTimesFailedCurrent()
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesFailedOutsideRangeCurrent()
unsigned int TermTelemetry::GetAndResetTimesFailedOutsideRangeCurrent() noexcept
{
unsigned int uiTemp = _uiTimesFailedOutsideRangeCurrent;
const auto temp = _uiTimesFailedOutsideRangeCurrent;
_uiTimesFailedOutsideRangeCurrent = 0;
return uiTemp;
return temp;
}
// Routine Description:
@ -128,7 +139,7 @@ unsigned int TermTelemetry::GetAndResetTimesFailedOutsideRangeCurrent()
// - writeLog - true if we should write the log.
// Return Value:
// - <none>
void TermTelemetry::SetShouldWriteFinalLog(const bool writeLog)
void TermTelemetry::SetShouldWriteFinalLog(const bool writeLog) noexcept
{
_fShouldWriteFinalLog = writeLog;
}
@ -140,7 +151,7 @@ void TermTelemetry::SetShouldWriteFinalLog(const bool writeLog)
// - activityId - Pointer to Guid to set our activity Id to.
// Return Value:
// - <none>
void TermTelemetry::SetActivityId(const GUID* activityId)
void TermTelemetry::SetActivityId(const GUID* activityId) noexcept
{
_activityId = *activityId;
}
@ -252,3 +263,5 @@ void TermTelemetry::WriteFinalTraceLog() const
}
}
}
#pragma warning(pop)

View File

@ -24,7 +24,7 @@ namespace Microsoft::Console::VirtualTerminal
{
public:
// Implement this as a singleton class.
static TermTelemetry& Instance()
static TermTelemetry& Instance() noexcept
{
static TermTelemetry s_Instance;
return s_Instance;
@ -88,20 +88,22 @@ namespace Microsoft::Console::VirtualTerminal
// Only use this last enum as a count of the number of codes.
NUMBER_OF_CODES
};
void Log(const Codes code);
void LogFailed(const wchar_t wch);
void SetShouldWriteFinalLog(const bool writeLog);
void SetActivityId(const GUID* activityId);
unsigned int GetAndResetTimesUsedCurrent();
unsigned int GetAndResetTimesFailedCurrent();
unsigned int GetAndResetTimesFailedOutsideRangeCurrent();
void Log(const Codes code) noexcept;
void LogFailed(const wchar_t wch) noexcept;
void SetShouldWriteFinalLog(const bool writeLog) noexcept;
void SetActivityId(const GUID* activityId) noexcept;
unsigned int GetAndResetTimesUsedCurrent() noexcept;
unsigned int GetAndResetTimesFailedCurrent() noexcept;
unsigned int GetAndResetTimesFailedOutsideRangeCurrent() noexcept;
private:
// Used to prevent multiple instances
TermTelemetry();
TermTelemetry() noexcept;
~TermTelemetry();
TermTelemetry(TermTelemetry const&);
void operator=(TermTelemetry const&);
TermTelemetry(TermTelemetry const&) = delete;
TermTelemetry(TermTelemetry&&) = delete;
TermTelemetry& operator=(const TermTelemetry&) = delete;
TermTelemetry& operator=(TermTelemetry&&) = delete;
void WriteFinalTraceLog() const;

View File

@ -6,16 +6,19 @@
using namespace Microsoft::Console::VirtualTerminal;
ParserTracing::ParserTracing()
#pragma warning(push)
#pragma warning(disable : 26494) // _Tlgdata uninitialized from TraceLoggingWrite
#pragma warning(disable : 26477) // Use nullptr instead of NULL or 0 from TraceLoggingWrite
#pragma warning(disable : 26485) // _Tlgdata, no array to pointer decay from TraceLoggingWrite
#pragma warning(disable : 26446) // Prefer gsl::at over unchecked subscript from TraceLoggingLevel
#pragma warning(disable : 26482) // Only index to arrays with constant expressions from TraceLoggingLevel
ParserTracing::ParserTracing() noexcept
{
ClearSequenceTrace();
}
ParserTracing::~ParserTracing()
{
}
void ParserTracing::TraceStateChange(const std::wstring_view name) const
void ParserTracing::TraceStateChange(const std::wstring_view name) const noexcept
{
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_EnterState",
@ -23,7 +26,7 @@ void ParserTracing::TraceStateChange(const std::wstring_view name) const
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
void ParserTracing::TraceOnAction(const std::wstring_view name) const
void ParserTracing::TraceOnAction(const std::wstring_view name) const noexcept
{
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_Action",
@ -33,7 +36,7 @@ void ParserTracing::TraceOnAction(const std::wstring_view name) const
void ParserTracing::TraceOnExecute(const wchar_t wch) const
{
INT16 sch = (INT16)wch;
const auto sch = gsl::narrow_cast<INT16>(wch);
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_Execute",
TraceLoggingWChar(wch),
@ -43,7 +46,7 @@ void ParserTracing::TraceOnExecute(const wchar_t wch) const
void ParserTracing::TraceOnExecuteFromEscape(const wchar_t wch) const
{
INT16 sch = (INT16)wch;
const auto sch = gsl::narrow_cast<INT16>(wch);
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_ExecuteFromEscape",
TraceLoggingWChar(wch),
@ -51,7 +54,7 @@ void ParserTracing::TraceOnExecuteFromEscape(const wchar_t wch) const
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
void ParserTracing::TraceOnEvent(const std::wstring_view name) const
void ParserTracing::TraceOnEvent(const std::wstring_view name) const noexcept
{
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_Event",
@ -62,7 +65,7 @@ void ParserTracing::TraceOnEvent(const std::wstring_view name) const
void ParserTracing::TraceCharInput(const wchar_t wch)
{
AddSequenceTrace(wch);
INT16 sch = (INT16)wch;
const auto sch = gsl::narrow_cast<INT16>(wch);
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_NewChar",
@ -76,7 +79,7 @@ void ParserTracing::AddSequenceTrace(const wchar_t wch)
_sequenceTrace.push_back(wch);
}
void ParserTracing::DispatchSequenceTrace(const bool fSuccess)
void ParserTracing::DispatchSequenceTrace(const bool fSuccess) noexcept
{
if (fSuccess)
{
@ -96,7 +99,7 @@ void ParserTracing::DispatchSequenceTrace(const bool fSuccess)
ClearSequenceTrace();
}
void ParserTracing::ClearSequenceTrace()
void ParserTracing::ClearSequenceTrace() noexcept
{
_sequenceTrace.clear();
}
@ -106,8 +109,8 @@ void ParserTracing::DispatchPrintRunTrace(const std::wstring_view string) const
{
if (string.size() == 1)
{
wchar_t wch = string.front();
INT16 sch = (INT16)wch;
const auto wch = til::at(string, 0);
const auto sch = gsl::narrow_cast<INT16>(wch);
TraceLoggingWrite(g_hConsoleVirtTermParserEventTraceProvider,
"StateMachine_PrintRun",
TraceLoggingWChar(wch),
@ -125,3 +128,5 @@ void ParserTracing::DispatchPrintRunTrace(const std::wstring_view string) const
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
}
#pragma warning(pop)

View File

@ -21,19 +21,18 @@ namespace Microsoft::Console::VirtualTerminal
class ParserTracing sealed
{
public:
ParserTracing();
~ParserTracing();
ParserTracing() noexcept;
void TraceStateChange(const std::wstring_view name) const;
void TraceOnAction(const std::wstring_view name) const;
void TraceStateChange(const std::wstring_view name) const noexcept;
void TraceOnAction(const std::wstring_view name) const noexcept;
void TraceOnExecute(const wchar_t wch) const;
void TraceOnExecuteFromEscape(const wchar_t wch) const;
void TraceOnEvent(const std::wstring_view name) const;
void TraceOnEvent(const std::wstring_view name) const noexcept;
void TraceCharInput(const wchar_t wch);
void AddSequenceTrace(const wchar_t wch);
void DispatchSequenceTrace(const bool fSuccess);
void ClearSequenceTrace();
void DispatchSequenceTrace(const bool fSuccess) noexcept;
void ClearSequenceTrace() noexcept;
void DispatchPrintRunTrace(const std::wstring_view string) const;
private:

View File

@ -689,63 +689,63 @@ public:
*this = dispatch;
}
bool CursorUp(_In_ size_t const uiDistance) override
bool CursorUp(_In_ size_t const uiDistance) noexcept override
{
_cursorUp = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorDown(_In_ size_t const uiDistance) override
bool CursorDown(_In_ size_t const uiDistance) noexcept override
{
_cursorDown = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorBackward(_In_ size_t const uiDistance) override
bool CursorBackward(_In_ size_t const uiDistance) noexcept override
{
_cursorBackward = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorForward(_In_ size_t const uiDistance) override
bool CursorForward(_In_ size_t const uiDistance) noexcept override
{
_cursorForward = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorNextLine(_In_ size_t const uiDistance) override
bool CursorNextLine(_In_ size_t const uiDistance) noexcept override
{
_cursorNextLine = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorPrevLine(_In_ size_t const uiDistance) override
bool CursorPrevLine(_In_ size_t const uiDistance) noexcept override
{
_cursorPreviousLine = true;
_cursorDistance = uiDistance;
return true;
}
bool CursorHorizontalPositionAbsolute(_In_ size_t const uiPosition) override
bool CursorHorizontalPositionAbsolute(_In_ size_t const uiPosition) noexcept override
{
_cursorHorizontalPositionAbsolute = true;
_cursorDistance = uiPosition;
return true;
}
bool VerticalLinePositionAbsolute(_In_ size_t const uiPosition) override
bool VerticalLinePositionAbsolute(_In_ size_t const uiPosition) noexcept override
{
_verticalLinePositionAbsolute = true;
_cursorDistance = uiPosition;
return true;
}
bool CursorPosition(_In_ size_t const uiLine, _In_ size_t const uiColumn) override
bool CursorPosition(_In_ size_t const uiLine, _In_ size_t const uiColumn) noexcept override
{
_cursorPosition = true;
_line = uiLine;
@ -753,61 +753,62 @@ public:
return true;
}
bool CursorSaveState() override
bool CursorSaveState() noexcept override
{
_cursorSave = true;
return true;
}
bool CursorRestoreState() override
bool CursorRestoreState() noexcept override
{
_cursorLoad = true;
return true;
}
bool EraseInDisplay(const DispatchTypes::EraseType eraseType) override
bool EraseInDisplay(const DispatchTypes::EraseType eraseType) noexcept override
{
_eraseDisplay = true;
_eraseType = eraseType;
return true;
}
bool EraseInLine(const DispatchTypes::EraseType eraseType) override
bool EraseInLine(const DispatchTypes::EraseType eraseType) noexcept override
{
_eraseLine = true;
_eraseType = eraseType;
return true;
}
bool InsertCharacter(_In_ size_t const uiCount) override
bool InsertCharacter(_In_ size_t const uiCount) noexcept override
{
_insertCharacter = true;
_cursorDistance = uiCount;
return true;
}
bool DeleteCharacter(_In_ size_t const uiCount) override
bool DeleteCharacter(_In_ size_t const uiCount) noexcept override
{
_deleteCharacter = true;
_cursorDistance = uiCount;
return true;
}
bool CursorVisibility(const bool fIsVisible) override
bool CursorVisibility(const bool fIsVisible) noexcept override
{
_cursorVisible = fIsVisible;
return true;
}
bool SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> options) override
bool SetGraphicsRendition(const std::basic_string_view<DispatchTypes::GraphicsOptions> options) noexcept override
try
{
_options.assign(options.cbegin(), options.cend());
_setGraphics = true;
return true;
}
CATCH_LOG_RETURN_FALSE()
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) override
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) noexcept override
{
_deviceStatusReport = true;
_statusReportType = statusType;
@ -815,7 +816,7 @@ public:
return true;
}
bool DeviceAttributes() override
bool DeviceAttributes() noexcept override
{
_deviceAttributes = true;
@ -869,53 +870,53 @@ public:
return cFailures == 0;
}
bool SetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> params) override
bool SetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> params) noexcept override
{
return _SetResetPrivateModesHelper(params, true);
}
bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> params) override
bool ResetPrivateModes(const std::basic_string_view<DispatchTypes::PrivateModeParams> params) noexcept override
{
return _SetResetPrivateModesHelper(params, false);
}
bool SetColumns(_In_ size_t const uiColumns) override
bool SetColumns(_In_ size_t const uiColumns) noexcept override
{
_windowWidth = uiColumns;
return true;
}
bool SetVirtualTerminalInputMode(const bool fApplicationMode)
bool SetVirtualTerminalInputMode(const bool fApplicationMode) noexcept
{
_cursorKeysMode = fApplicationMode;
return true;
}
bool EnableCursorBlinking(const bool bEnable) override
bool EnableCursorBlinking(const bool bEnable) noexcept override
{
_cursorBlinking = bEnable;
return true;
}
bool SetOriginMode(const bool fRelativeMode) override
bool SetOriginMode(const bool fRelativeMode) noexcept override
{
_isOriginModeRelative = fRelativeMode;
return true;
}
bool EnableDECCOLMSupport(const bool fEnabled) override
bool EnableDECCOLMSupport(const bool fEnabled) noexcept override
{
_isDECCOLMAllowed = fEnabled;
return true;
}
bool UseAlternateScreenBuffer() override
bool UseAlternateScreenBuffer() noexcept override
{
_isAltBuffer = true;
return true;
}
bool UseMainScreenBuffer() override
bool UseMainScreenBuffer() noexcept override
{
_isAltBuffer = false;
return true;

View File

@ -11,19 +11,6 @@ Author(s):
- Mike Griese (migrie) 12-Jun-2018
--*/
// Inspired from RETURN_IF_WIN32_BOOL_FALSE
// WIL doesn't include a RETURN_BOOL_IF_FALSE, and RETURN_IF_WIN32_BOOL_FALSE
// will actually return the value of GLE.
#define RETURN_BOOL_IF_FALSE(b) \
do \
{ \
BOOL __boolRet = wil::verify_bool(b); \
if (!__boolRet) \
{ \
return __boolRet; \
} \
} while (0, 0)
namespace Microsoft::Console::Utils
{
bool IsValidHandle(const HANDLE handle) noexcept;