Refactor and simplify the ConGetSet API (#12247)

## Summary of the Pull Request

This PR refactors the `ConGetSet` API, eliminating some of the bloat produced by the `DoSrvPrivateXXXX` functions, simplifying the method naming to more closely match the `ITerminalApi` interface, and making better use of exceptions for error conditions in place of boolean return values.

## References

This is another small step towards merging the `AdaptDispatch` and `TerminalDispatch` classes (#3849).

## PR Checklist
* [x] Closes #12193
* [x] Closes #12194
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #3849

## Detailed Description of the Pull Request / Additional comments

There are two main parts to this. The first step was to get rid of all the `DoSrvPrivateXXX` functions, and move their implementation directly into the `ConhostInternalGetSet` class. For the most part this was just copying and pasting the code, but I also fixed a couple of bugs where we were using the wrong output buffer (the global buffer rather than the one associated with the output handle), and got rid of some unnecessary calls to `GetActiveBuffer`.

The second part was to make better use of exceptions for error conditions. Instead of catching the exceptions at the `ConGetSet` level, we now allow them to fall through all the way to the `StateMachine`. This greatly simplifies the `AdaptDispatch` implementation since it no longer needs to check a boolean return value on every `ConGetSet` call. This also enables the getter methods to return properties directly instead of having to use a reference parameter.

## Validation Steps Performed

A number of the unit tests had to be updated to match the new API. Sometimes this just required changes to method names, but in other cases error conditions that were previously detected with boolean returns now needed to be caught as exceptions. 

There were also a few direct calls to `DoSrvPrivateXXX` functions that now needed to be invoked through other means: either by generating an equivalent escape sequence, or calling a lower level API serving the same purpose.

And in the adapter tests, the mock `ConGetSet` implementation required significant refactoring to match the new interface, mostly to account for the changes in error handling.
This commit is contained in:
James Holderness 2022-02-04 12:00:49 +00:00 коммит произвёл GitHub
Родитель e064c15675
Коммит 5238235268
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 1717 добавлений и 2493 удалений

Просмотреть файл

@ -303,7 +303,7 @@ void ConptyRoundtripTests::_resizeConpty(const unsigned short sx,
void ConptyRoundtripTests::_clearConpty()
{
// Taken verbatim from implementation in PtySignalInputThread::_DoClearBuffer
_pConApi->PrivateClearBuffer();
_pConApi->ClearBuffer();
}
[[nodiscard]] std::tuple<TextBuffer*, TextBuffer*> ConptyRoundtripTests::_performResize(const til::size newSize)

Просмотреть файл

@ -145,7 +145,7 @@ void PtySignalInputThread::_DoResizeWindow(const ResizeWindowData& data)
void PtySignalInputThread::_DoClearBuffer()
{
_pConApi->PrivateClearBuffer();
_pConApi->ClearBuffer();
}
// Method Description:

Просмотреть файл

@ -148,8 +148,6 @@ void RedrawCommandLine(COOKED_READ_DATA& cookedReadData);
bool IsWordDelim(const wchar_t wch);
bool IsWordDelim(const std::wstring_view charData);
[[nodiscard]] HRESULT DoSrvSetConsoleTitleW(const std::wstring_view title) noexcept;
bool IsValidStringBuffer(_In_ bool Unicode, _In_reads_bytes_(Size) PVOID Buffer, _In_ ULONG Size, _In_ ULONG Count, ...);
void SetCurrentCommandLine(COOKED_READ_DATA& cookedReadData, _In_ SHORT Index);

Просмотреть файл

@ -443,24 +443,6 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
CATCH_RETURN();
}
// Routine Description:
// - Writes events to the input buffer already formed into IInputEvents (private call)
// Arguments:
// - context - the input buffer to write to
// - events - the events to written
// - written - on output, the number of events written
// - append - true if events should be written to the end of the input
// buffer, false if they should be written to the front
// Return Value:
// - HRESULT indicating success or failure
[[nodiscard]] HRESULT DoSrvPrivateWriteConsoleInputW(_Inout_ InputBuffer* const pInputBuffer,
_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
_Out_ size_t& eventsWritten,
const bool append) noexcept
{
return _WriteConsoleInputWImplHelper(*pInputBuffer, events, eventsWritten, append);
}
// Routine Description:
// - Writes events to the input buffer, translating from codepage to unicode first
// Arguments:
@ -534,32 +516,6 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
CATCH_RETURN();
}
// Function Description:
// - Writes the input KeyEvent to the console as a console control event. This
// can be used for potentially generating Ctrl-C events, as
// HandleGenericKeyEvent will correctly generate the Ctrl-C response in
// the same way that it'd be handled from the window proc, with the proper
// processed vs raw input handling.
// If the input key is *not* a Ctrl-C key, then it will get written to the
// buffer just the same as any other KeyEvent.
// Arguments:
// - pInputBuffer - the input buffer to write to. Currently unused, as
// HandleGenericKeyEvent just gets the global input buffer, but all
// ConGetSet API's require an input or output object.
// - key - The keyevent to send to the console.
// Return Value:
// - HRESULT indicating success or failure
[[nodiscard]] HRESULT DoSrvPrivateWriteConsoleControlInput(_Inout_ InputBuffer* const /*pInputBuffer*/,
_In_ KeyEvent key)
{
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
HandleGenericKeyEvent(key, false);
return S_OK;
}
// Routine Description:
// - This is used when the app is reading output as cells and needs them converted
// into a particular codepage on the way out.

Просмотреть файл

@ -21,15 +21,7 @@ Revision History:
class SCREEN_INFORMATION;
[[nodiscard]] HRESULT DoSrvPrivateWriteConsoleInputW(_Inout_ InputBuffer* const pInputBuffer,
_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
_Out_ size_t& eventsWritten,
const bool append) noexcept;
[[nodiscard]] NTSTATUS ConsoleCreateScreenBuffer(std::unique_ptr<ConsoleHandleData>& handle,
_In_ PCONSOLE_API_MSG Message,
_In_ PCD_CREATE_OBJECT_INFORMATION Information,
_In_ PCONSOLE_CREATESCREENBUFFER_MSG a);
[[nodiscard]] NTSTATUS DoSrvPrivateWriteConsoleControlInput(_Inout_ InputBuffer* const pInputBuffer,
_In_ KeyEvent key);

Просмотреть файл

@ -1059,12 +1059,6 @@ void ApiRoutines::GetConsoleInputCodePageImpl(ULONG& codepage) noexcept
CATCH_LOG();
}
void DoSrvGetConsoleOutputCodePage(unsigned int& codepage)
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
codepage = gci.OutputCP;
}
// Routine Description:
// - Gets the codepage used for translating text when calling A versions of functions affecting the output buffer.
// Arguments:
@ -1075,9 +1069,8 @@ void ApiRoutines::GetConsoleOutputCodePageImpl(ULONG& codepage) noexcept
{
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
unsigned int cp;
DoSrvGetConsoleOutputCodePage(cp);
codepage = cp;
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
codepage = gci.OutputCP;
}
CATCH_LOG();
}
@ -1247,289 +1240,6 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
CATCH_RETURN();
}
// Routine Description:
// - A private API call for setting the ENABLE_WRAP_AT_EOL_OUTPUT mode.
// This controls whether the cursor moves to the beginning of the next row
// when it reaches the end of the current row.
// Parameters:
// - wrapAtEOL - set to true to wrap, false to overwrite the last character.
// Return value:
// - STATUS_SUCCESS if handled successfully.
[[nodiscard]] NTSTATUS DoSrvPrivateSetAutoWrapMode(const bool wrapAtEOL)
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& outputMode = gci.GetActiveOutputBuffer().GetActiveBuffer().OutputMode;
WI_UpdateFlag(outputMode, ENABLE_WRAP_AT_EOL_OUTPUT, wrapAtEOL);
return STATUS_SUCCESS;
}
// Routine Description:
// - A private API call for making the cursor visible or not. Does not modify
// blinking state.
// Parameters:
// - show - set to true to make the cursor visible, false to hide.
// Return value:
// - <none>
void DoSrvPrivateShowCursor(SCREEN_INFORMATION& screenInfo, const bool show) noexcept
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetIsVisible(show);
}
// Routine Description:
// - A private API call for enabling or disabling the cursor blinking.
// Parameters:
// - fEnable - set to true to enable blinking, false to disable
// Return value:
// - True if handled successfully. False otherwise.
void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool fEnable)
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetBlinkingAllowed(fEnable);
// GH#2642 - From what we've gathered from other terminals, when blinking is
// disabled, the cursor should remain On always, and have the visibility
// controlled by the IsVisible property. So when you do a printf "\e[?12l"
// to disable blinking, the cursor stays stuck On. At this point, only the
// cursor visibility property controls whether the user can see it or not.
// (Yes, the cursor can be On and NOT Visible)
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetIsOn(true);
}
// Routine Description:
// - A private API call for setting the top and bottom scrolling margins for
// the current page. This creates a subsection of the screen that scrolls
// when input reaches the end of the region, leaving the rest of the screen
// untouched.
// Currently only accessible through the use of ANSI sequence DECSTBM
// Parameters:
// - scrollMargins - A rect who's Top and Bottom members will be used to set
// the new values of the top and bottom margins. If (0,0), then the margins
// will be disabled. NOTE: This is a rect in the case that we'll need the
// left and right margins in the future.
// Return value:
// - True if handled successfully. False otherwise.
[[nodiscard]] NTSTATUS DoSrvPrivateSetScrollingRegion(SCREEN_INFORMATION& screenInfo, const SMALL_RECT& scrollMargins)
{
NTSTATUS Status = STATUS_SUCCESS;
if (scrollMargins.Top > scrollMargins.Bottom)
{
Status = STATUS_INVALID_PARAMETER;
}
if (NT_SUCCESS(Status))
{
SMALL_RECT srScrollMargins = screenInfo.GetRelativeScrollMargins().ToInclusive();
srScrollMargins.Top = scrollMargins.Top;
srScrollMargins.Bottom = scrollMargins.Bottom;
screenInfo.GetActiveBuffer().SetScrollMargins(Viewport::FromInclusive(srScrollMargins));
}
return Status;
}
// Routine Description:
// - A private API call for performing a line feed, possibly preceded by carriage return.
// Moves the cursor down one line, and possibly also to the leftmost column.
// Parameters:
// - screenInfo - A pointer to the screen buffer that should perform the line feed.
// - withReturn - Set to true if a carriage return should be performed as well.
// Return value:
// - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error.
[[nodiscard]] NTSTATUS DoSrvPrivateLineFeed(SCREEN_INFORMATION& screenInfo, const bool withReturn)
{
auto& textBuffer = screenInfo.GetTextBuffer();
auto cursorPosition = textBuffer.GetCursor().GetPosition();
// We turn the cursor on before an operation that might scroll the viewport, otherwise
// that can result in an old copy of the cursor being left behind on the screen.
textBuffer.GetCursor().SetIsOn(true);
// Since we are explicitly moving down a row, clear the wrap status on the row we're leaving
textBuffer.GetRowByOffset(cursorPosition.Y).SetWrapForced(false);
cursorPosition.Y += 1;
if (withReturn)
{
cursorPosition.X = 0;
}
else
{
cursorPosition = textBuffer.ClampPositionWithinLine(cursorPosition);
}
return AdjustCursorPosition(screenInfo, cursorPosition, FALSE, nullptr);
}
// Routine Description:
// - A private API call for performing a "Reverse line feed", essentially, the opposite of '\n'.
// Moves the cursor up one line, and tries to keep its position in the line
// Parameters:
// - screenInfo - a pointer to the screen buffer that should perform the reverse line feed
// Return value:
// - True if handled successfully. False otherwise.
[[nodiscard]] NTSTATUS DoSrvPrivateReverseLineFeed(SCREEN_INFORMATION& screenInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
const SMALL_RECT viewport = screenInfo.GetActiveBuffer().GetViewport().ToInclusive();
const COORD oldCursorPosition = screenInfo.GetTextBuffer().GetCursor().GetPosition();
COORD newCursorPosition = { oldCursorPosition.X, oldCursorPosition.Y - 1 };
newCursorPosition = screenInfo.GetTextBuffer().ClampPositionWithinLine(newCursorPosition);
// If the cursor is at the top of the viewport, we don't want to shift the viewport up.
// We want it to stay exactly where it is.
// In that case, shift the buffer contents down, to emulate inserting a line
// at the top of the buffer.
if (oldCursorPosition.Y > viewport.Top)
{
// Cursor is below the top line of the viewport
Status = AdjustCursorPosition(screenInfo, newCursorPosition, TRUE, nullptr);
}
else
{
// If we don't have margins, or the cursor is within the boundaries of the margins
// It's important to check if the cursor is in the margins,
// If it's not, but the margins are set, then we don't want to scroll anything
if (screenInfo.IsCursorInMargins(oldCursorPosition))
{
// Cursor is at the top of the viewport
// Rectangle to cut out of the existing buffer. This is inclusive.
// It will be clipped to the buffer boundaries so SHORT_MAX gives us the full buffer width.
SMALL_RECT srScroll;
srScroll.Left = 0;
srScroll.Right = SHORT_MAX;
srScroll.Top = viewport.Top;
srScroll.Bottom = viewport.Bottom;
// Clip to the DECSTBM margin boundary
if (screenInfo.AreMarginsSet())
{
srScroll.Bottom = screenInfo.GetAbsoluteScrollMargins().BottomInclusive();
}
// Paste coordinate for cut text above
COORD coordDestination;
coordDestination.X = 0;
coordDestination.Y = viewport.Top + 1;
// Note the revealed lines are filled with the standard erase attributes.
Status = NTSTATUS_FROM_HRESULT(DoSrvPrivateScrollRegion(screenInfo,
srScroll,
srScroll,
coordDestination,
true));
}
}
return Status;
}
// Routine Description:
// - A private API call for swapping to the alternate screen buffer. In virtual terminals, there exists both a "main"
// screen buffer and an alternate. ASBSET creates a new alternate, and switches to it. If there is an already
// existing alternate, it is discarded.
// Parameters:
// - screenInfo - a reference to the screen buffer that should use an alternate buffer
// Return value:
// - True if handled successfully. False otherwise.
[[nodiscard]] NTSTATUS DoSrvPrivateUseAlternateScreenBuffer(SCREEN_INFORMATION& screenInfo)
{
return screenInfo.GetActiveBuffer().UseAlternateScreenBuffer();
}
// Routine Description:
// - A private API call for swapping to the main screen buffer. From the
// alternate buffer, returns to the main screen buffer. From the main
// screen buffer, does nothing. The alternate is discarded.
// Parameters:
// - screenInfo - a reference to the screen buffer that should use the main buffer
// Return value:
// - True if handled successfully. False otherwise.
void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo)
{
screenInfo.GetActiveBuffer().UseMainScreenBuffer();
}
// Routine Description:
// - A private API call for performing a VT-style erase all operation on the buffer.
// See SCREEN_INFORMATION::VtEraseAll's description for details.
// Parameters:
// The ScreenBuffer to perform the erase on.
// Return value:
// - S_OK if we succeeded, otherwise the HRESULT of the failure.
[[nodiscard]] HRESULT DoSrvPrivateEraseAll(SCREEN_INFORMATION& screenInfo)
{
return screenInfo.GetActiveBuffer().VtEraseAll();
}
// See SCREEN_INFORMATION::ClearBuffer's description for details.
[[nodiscard]] HRESULT DoSrvPrivateClearBuffer(SCREEN_INFORMATION& screenInfo)
{
return screenInfo.GetActiveBuffer().ClearBuffer();
}
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
const CursorType cursorType)
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
}
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri,
const std::wstring_view params)
{
auto attr = screenInfo.GetAttributes();
const auto id = screenInfo.GetTextBuffer().GetHyperlinkId(uri, params);
attr.SetHyperlinkId(id);
screenInfo.GetTextBuffer().SetCurrentAttributes(attr);
screenInfo.GetTextBuffer().AddHyperlinkToMap(uri, id);
}
void DoSrvEndHyperlink(SCREEN_INFORMATION& screenInfo)
{
auto attr = screenInfo.GetAttributes();
attr.SetHyperlinkId(0);
screenInfo.GetTextBuffer().SetCurrentAttributes(attr);
}
// Routine Description:
// - A private API call for updating the active soft font.
// Arguments:
// - bitPattern - An array of scanlines representing all the glyphs in the font.
// - cellSize - The cell size for an individual glyph.
// - centeringHint - The horizontal extent that glyphs are offset from center.
// Return Value:
// - S_OK if we succeeded, otherwise the HRESULT of the failure.
[[nodiscard]] HRESULT DoSrvUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept
{
try
{
auto* pRender = ServiceLocator::LocateGlobals().pRender;
if (pRender)
{
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
}
return S_OK;
}
CATCH_RETURN();
}
// Routine Description:
// - A private API call for forcing the renderer to repaint the screen. If the
// input screen buffer is not the active one, then just do nothing. We only
// want to redraw the screen buffer that requested the repaint, and
// switching screen buffers will already force a repaint.
// Parameters:
// The ScreenBuffer to perform the repaint for.
// Return value:
// - None
void DoSrvPrivateRefreshWindow(_In_ const SCREEN_INFORMATION& screenInfo)
{
Globals& g = ServiceLocator::LocateGlobals();
if (&screenInfo == &g.getConsoleInformation().GetActiveOutputBuffer().GetActiveBuffer())
{
g.pRender->TriggerRedrawAll();
}
}
// Routine Description:
// - Gets title information from the console. It can be truncated if the buffer is too small.
// Arguments:
@ -1792,219 +1502,6 @@ void DoSrvPrivateRefreshWindow(_In_ const SCREEN_INFORMATION& screenInfo)
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
return DoSrvSetConsoleTitleW(title);
}
[[nodiscard]] HRESULT DoSrvSetConsoleTitleW(const std::wstring_view title) noexcept
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.SetTitle(title);
ServiceLocator::LocateGlobals().getConsoleInformation().SetTitle(title);
return S_OK;
}
// Routine Description:
// - A private API call for forcing the VT Renderer to NOT paint the next resize
// event. This is used by InteractDispatch, to prevent resizes from echoing
// between terminal and host.
// Parameters:
// <none>
// Return value:
// - STATUS_SUCCESS if we succeeded, otherwise the NTSTATUS version of the failure.
[[nodiscard]] NTSTATUS DoSrvPrivateSuppressResizeRepaint()
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
FAIL_FAST_IF(!(gci.IsInVtIoMode()));
return NTSTATUS_FROM_HRESULT(gci.GetVtIo()->SuppressResizeRepaint());
}
// Routine Description:
// - An API call for checking if the console host is acting as a pty.
// Parameters:
// - isPty: receives the bool indicating whether or not we're in pty mode.
// Return value:
// <none>
void DoSrvIsConsolePty(bool& isPty)
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
isPty = gci.IsInVtIoMode();
}
// Routine Description:
// - internal logic for adding or removing lines in the active screen buffer
// this also moves the cursor to the left margin, which is expected behavior for IL and DL
// Parameters:
// - count - the number of lines to modify
// - insert - true if inserting lines, false if deleting lines
void DoSrvPrivateModifyLinesImpl(const size_t count, const bool insert)
{
auto& screenInfo = ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetActiveBuffer();
auto& textBuffer = screenInfo.GetTextBuffer();
const auto cursorPosition = textBuffer.GetCursor().GetPosition();
if (screenInfo.IsCursorInMargins(cursorPosition))
{
// Rectangle to cut out of the existing buffer. This is inclusive.
// It will be clipped to the buffer boundaries so SHORT_MAX gives us the full buffer width.
SMALL_RECT srScroll;
srScroll.Left = 0;
srScroll.Right = SHORT_MAX;
srScroll.Top = cursorPosition.Y;
srScroll.Bottom = screenInfo.GetViewport().BottomInclusive();
// Clip to the DECSTBM margin boundary
if (screenInfo.AreMarginsSet())
{
srScroll.Bottom = screenInfo.GetAbsoluteScrollMargins().BottomInclusive();
}
// Paste coordinate for cut text above
COORD coordDestination;
coordDestination.X = 0;
if (insert)
{
coordDestination.Y = (cursorPosition.Y) + gsl::narrow<short>(count);
}
else
{
coordDestination.Y = (cursorPosition.Y) - gsl::narrow<short>(count);
}
// Note the revealed lines are filled with the standard erase attributes.
LOG_IF_FAILED(DoSrvPrivateScrollRegion(screenInfo,
srScroll,
srScroll,
coordDestination,
true));
// The IL and DL controls are also expected to move the cursor to the left margin.
// For now this is just column 0, since we don't yet support DECSLRM.
LOG_IF_NTSTATUS_FAILED(screenInfo.SetCursorPosition({ 0, cursorPosition.Y }, false));
}
}
// Routine Description:
// - a private API call for deleting lines in the active screen buffer.
// Parameters:
// - count - the number of lines to delete
void DoSrvPrivateDeleteLines(const size_t count)
{
DoSrvPrivateModifyLinesImpl(count, false);
}
// Routine Description:
// - a private API call for inserting lines in the active screen buffer.
// Parameters:
// - count - the number of lines to insert
void DoSrvPrivateInsertLines(const size_t count)
{
DoSrvPrivateModifyLinesImpl(count, true);
}
// Method Description:
// - Snaps the screen buffer's viewport to the "virtual bottom", the last place
//the viewport was before the user scrolled it (with the mouse or scrollbar)
// Arguments:
// - screenInfo: the buffer to move the viewport for.
// Return Value:
// - <none>
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
{
screenInfo.GetActiveBuffer().MoveToBottom();
}
// Routine Description:
// - A private API call for filling a region of the screen buffer.
// Arguments:
// - screenInfo - Reference to screen buffer info.
// - startPosition - The position to begin filling at.
// - fillLength - The number of characters to fill.
// - fillChar - Character to fill the target region with.
// - standardFillAttrs - If true, fill with the standard erase attributes.
// If false, fill with the default attributes.
// Return value:
// - S_OK or failure code from thrown exception
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) noexcept
{
try
{
if (fillLength == 0)
{
return S_OK;
}
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
// For most VT erasing operations, the standard requires that the
// erased area be filled with the current background color, but with
// no additional meta attributes set. For all other cases, we just
// fill with the default attributes.
auto fillAttrs = TextAttribute{};
if (standardFillAttrs)
{
fillAttrs = screenInfo.GetAttributes();
fillAttrs.SetStandardErase();
}
const auto fillData = OutputCellIterator{ fillChar, fillAttrs, fillLength };
screenInfo.Write(fillData, startPosition, false);
// Notify accessibility
if (screenInfo.HasAccessibilityEventing())
{
auto endPosition = startPosition;
const auto bufferSize = screenInfo.GetBufferSize();
bufferSize.MoveInBounds(fillLength - 1, endPosition);
screenInfo.NotifyAccessibilityEventing(startPosition.X, startPosition.Y, endPosition.X, endPosition.Y);
}
return S_OK;
}
CATCH_RETURN();
}
// Routine Description:
// - A private API call for moving a block of data in the screen buffer,
// optionally limiting the effects of the move to a clipping rectangle.
// Arguments:
// - screenInfo - Reference to screen buffer info.
// - scrollRect - Region to copy/move (source and size).
// - clipRect - Optional clip region to contain buffer change effects.
// - destinationOrigin - Upper left corner of target region.
// - standardFillAttrs - If true, fill with the standard erase attributes.
// If false, fill with the default attributes.
// Return value:
// - S_OK or failure code from thrown exception
[[nodiscard]] HRESULT DoSrvPrivateScrollRegion(SCREEN_INFORMATION& screenInfo,
const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) noexcept
{
try
{
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
// For most VT scrolling operations, the standard requires that the
// erased area be filled with the current background color, but with
// no additional meta attributes set. For all other cases, we just
// fill with the default attributes.
auto fillAttrs = TextAttribute{};
if (standardFillAttrs)
{
fillAttrs = screenInfo.GetAttributes();
fillAttrs.SetStandardErase();
}
ScrollRegion(screenInfo,
scrollRect,
clipRect,
destinationOrigin,
UNICODE_SPACE,
fillAttrs);
return S_OK;
}
CATCH_RETURN();
}

Просмотреть файл

@ -18,56 +18,4 @@ Revision History:
#include "../inc/conattrs.hpp"
class SCREEN_INFORMATION;
[[nodiscard]] NTSTATUS DoSrvPrivateSetAutoWrapMode(const bool wrapAtEOL);
void DoSrvPrivateShowCursor(SCREEN_INFORMATION& screenInfo, const bool show) noexcept;
void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool fEnable);
[[nodiscard]] NTSTATUS DoSrvPrivateSetScrollingRegion(SCREEN_INFORMATION& screenInfo, const SMALL_RECT& scrollMargins);
[[nodiscard]] NTSTATUS DoSrvPrivateLineFeed(SCREEN_INFORMATION& screenInfo, const bool withReturn);
[[nodiscard]] NTSTATUS DoSrvPrivateReverseLineFeed(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] NTSTATUS DoSrvPrivateUseAlternateScreenBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateEraseAll(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateClearBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
const CursorType cursorType);
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri,
const std::wstring_view params);
void DoSrvEndHyperlink(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept;
void DoSrvPrivateRefreshWindow(const SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvSetConsoleOutputCodePage(const unsigned int codepage);
void DoSrvGetConsoleOutputCodePage(unsigned int& codepage);
[[nodiscard]] NTSTATUS DoSrvPrivateSuppressResizeRepaint();
void DoSrvIsConsolePty(bool& isPty);
void DoSrvPrivateDeleteLines(const size_t count);
void DoSrvPrivateInsertLines(const size_t count);
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateScrollRegion(SCREEN_INFORMATION& screenInfo,
const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) noexcept;

Просмотреть файл

@ -8,6 +8,7 @@
#include "_stream.h"
#include "getset.h"
#include "directio.h"
#include "output.h"
#include "../interactivity/inc/ServiceLocator.hpp"
@ -109,11 +110,10 @@ ConhostInternalGetSet::ConhostInternalGetSet(_In_ IIoProvider& io) :
// Arguments:
// - screenBufferInfo - Structure to hold screen buffer information like the public API call.
// Return Value:
// - true if successful (see DoSrvGetConsoleScreenBufferInfo). false otherwise.
bool ConhostInternalGetSet::GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const
// - <none>
void ConhostInternalGetSet::GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const
{
ServiceLocator::LocateGlobals().api.GetConsoleScreenBufferInfoExImpl(_io.GetActiveOutputBuffer(), screenBufferInfo);
return true;
}
// Routine Description:
@ -121,35 +121,34 @@ bool ConhostInternalGetSet::GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_I
// Arguments:
// - screenBufferInfo - Structure containing screen buffer information like the public API call.
// Return Value:
// - true if successful (see DoSrvSetConsoleScreenBufferInfo). false otherwise.
bool ConhostInternalGetSet::SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo)
// - <none>
void ConhostInternalGetSet::SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo)
{
return SUCCEEDED(ServiceLocator::LocateGlobals().api.SetConsoleScreenBufferInfoExImpl(_io.GetActiveOutputBuffer(), screenBufferInfo));
THROW_IF_FAILED(ServiceLocator::LocateGlobals().api.SetConsoleScreenBufferInfoExImpl(_io.GetActiveOutputBuffer(), screenBufferInfo));
}
// Routine Description:
// - Connects the SetConsoleCursorPosition API call directly into our Driver Message servicing call inside Conhost.exe
// - Connects the SetCursorPosition API call directly into our Driver Message servicing call inside Conhost.exe
// Arguments:
// - position - new cursor position to set like the public API call.
// Return Value:
// - true if successful (see DoSrvSetConsoleCursorPosition). false otherwise.
bool ConhostInternalGetSet::SetConsoleCursorPosition(const COORD position)
// - <none>
void ConhostInternalGetSet::SetCursorPosition(const COORD position)
{
auto& info = _io.GetActiveOutputBuffer();
const auto clampedPosition = info.GetTextBuffer().ClampPositionWithinLine(position);
return SUCCEEDED(ServiceLocator::LocateGlobals().api.SetConsoleCursorPositionImpl(info, clampedPosition));
THROW_IF_FAILED(ServiceLocator::LocateGlobals().api.SetConsoleCursorPositionImpl(info, clampedPosition));
}
// Method Description:
// - Retrieves the current TextAttribute of the active screen buffer.
// Arguments:
// - attrs: Receives the TextAttribute value.
// - <none>
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::PrivateGetTextAttributes(TextAttribute& attrs) const
// - the TextAttribute value.
TextAttribute ConhostInternalGetSet::GetTextAttributes() const
{
attrs = _io.GetActiveOutputBuffer().GetAttributes();
return true;
return _io.GetActiveOutputBuffer().GetAttributes();
}
// Method Description:
@ -158,11 +157,10 @@ bool ConhostInternalGetSet::PrivateGetTextAttributes(TextAttribute& attrs) const
// Arguments:
// - attrs: The new TextAttribute to use
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::PrivateSetTextAttributes(const TextAttribute& attrs)
// - <none>
void ConhostInternalGetSet::SetTextAttributes(const TextAttribute& attrs)
{
_io.GetActiveOutputBuffer().SetAttributes(attrs);
return true;
}
// Method Description:
@ -171,12 +169,11 @@ bool ConhostInternalGetSet::PrivateSetTextAttributes(const TextAttribute& attrs)
// Arguments:
// - lineRendition: The new LineRendition attribute to use
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::PrivateSetCurrentLineRendition(const LineRendition lineRendition)
// - <none>
void ConhostInternalGetSet::SetCurrentLineRendition(const LineRendition lineRendition)
{
auto& textBuffer = _io.GetActiveOutputBuffer().GetTextBuffer();
textBuffer.SetCurrentLineRendition(lineRendition);
return true;
}
// Method Description:
@ -186,12 +183,11 @@ bool ConhostInternalGetSet::PrivateSetCurrentLineRendition(const LineRendition l
// - startRow: The row number of first line to be modified
// - endRow: The row number following the last line to be modified
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::PrivateResetLineRenditionRange(const size_t startRow, const size_t endRow)
// - <none>
void ConhostInternalGetSet::ResetLineRenditionRange(const size_t startRow, const size_t endRow)
{
auto& textBuffer = _io.GetActiveOutputBuffer().GetTextBuffer();
textBuffer.ResetLineRenditionRange(startRow, endRow);
return true;
}
// Method Description:
@ -201,41 +197,35 @@ bool ConhostInternalGetSet::PrivateResetLineRenditionRange(const size_t startRow
// - row: The row number of the line to measure
// Return Value:
// - the number of cells that will fit on the line
SHORT ConhostInternalGetSet::PrivateGetLineWidth(const size_t row) const
SHORT ConhostInternalGetSet::GetLineWidth(const size_t row) const
{
const auto& textBuffer = _io.GetActiveOutputBuffer().GetTextBuffer();
return textBuffer.GetLineWidth(row);
}
// Routine Description:
// - Connects the WriteConsoleInput API call directly into our Driver Message servicing call inside Conhost.exe
// - Writes events to the input buffer already formed into IInputEvents
// Arguments:
// - events - the input events to be copied into the head of the input
// buffer for the underlying attached process
// - eventsWritten - on output, the number of events written
// Return Value:
// - true if successful (see DoSrvWriteConsoleInput). false otherwise.
bool ConhostInternalGetSet::PrivateWriteConsoleInputW(std::deque<std::unique_ptr<IInputEvent>>& events,
size_t& eventsWritten)
// - <none>
void ConhostInternalGetSet::WriteInput(std::deque<std::unique_ptr<IInputEvent>>& events, size_t& eventsWritten)
{
eventsWritten = 0;
return SUCCEEDED(DoSrvPrivateWriteConsoleInputW(_io.GetActiveInputBuffer(),
events,
eventsWritten,
true)); // append
eventsWritten = _io.GetActiveInputBuffer()->Write(events);
}
// Routine Description:
// - Connects the SetConsoleWindowInfo API call directly into our Driver Message servicing call inside Conhost.exe
// - Connects the SetWindowInfo API call directly into our Driver Message servicing call inside Conhost.exe
// Arguments:
// - absolute - Should the window be moved to an absolute position? If false, the movement is relative to the current pos.
// - window - Info about how to move the viewport
// Return Value:
// - true if successful (see DoSrvSetConsoleWindowInfo). false otherwise.
bool ConhostInternalGetSet::SetConsoleWindowInfo(const bool absolute, const SMALL_RECT& window)
// - <none>
void ConhostInternalGetSet::SetWindowInfo(const bool absolute, const SMALL_RECT& window)
{
return SUCCEEDED(ServiceLocator::LocateGlobals().api.SetConsoleWindowInfoImpl(_io.GetActiveOutputBuffer(), absolute, window));
THROW_IF_FAILED(ServiceLocator::LocateGlobals().api.SetConsoleWindowInfoImpl(_io.GetActiveOutputBuffer(), absolute, window));
}
// Routine Description:
@ -260,7 +250,7 @@ bool ConhostInternalGetSet::SetInputMode(const TerminalInput::Mode mode, const b
// us that SSH 7.7 _also_ requests mouse input and that can have a user interface
// impact on the actual connected terminal. We can't remove this check,
// because SSH <=7.7 is out in the wild on all versions of Windows <=2004.
return !(IsConsolePty() && PrivateIsVtInputEnabled());
return !(IsConsolePty() && IsVtInputEnabled());
}
// Routine Description:
@ -271,12 +261,11 @@ bool ConhostInternalGetSet::SetInputMode(const TerminalInput::Mode mode, const b
// - mode - the parser mode to change.
// - enabled - set to true to enable the mode, false to disable it.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::SetParserMode(const StateMachine::Mode mode, const bool enabled)
// - <none>
void ConhostInternalGetSet::SetParserMode(const StateMachine::Mode mode, const bool enabled)
{
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
stateMachine.SetParserMode(mode, enabled);
return true;
}
// Routine Description:
@ -299,8 +288,8 @@ bool ConhostInternalGetSet::GetParserMode(const Microsoft::Console::VirtualTermi
// - mode - the render mode to change.
// - enabled - set to true to enable the mode, false to disable it.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::SetRenderMode(const RenderSettings::Mode mode, const bool enabled)
// - <none>
void ConhostInternalGetSet::SetRenderMode(const RenderSettings::Mode mode, const bool enabled)
{
auto& g = ServiceLocator::LocateGlobals();
auto& renderSettings = g.getConsoleInformation().GetRenderSettings();
@ -310,71 +299,75 @@ bool ConhostInternalGetSet::SetRenderMode(const RenderSettings::Mode mode, const
{
g.pRender->TriggerRedrawAll();
}
return true;
}
// Routine Description:
// - Connects the PrivateSetAutoWrapMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateSetAutoWrapMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Sets the ENABLE_WRAP_AT_EOL_OUTPUT mode. This controls whether the cursor moves
// to the beginning of the next row when it reaches the end of the current row.
// Arguments:
// - wrapAtEOL - set to true to wrap, false to overwrite the last character.
// Return Value:
// - true if successful (see DoSrvPrivateSetAutoWrapMode). false otherwise.
bool ConhostInternalGetSet::PrivateSetAutoWrapMode(const bool wrapAtEOL)
// - <none>
void ConhostInternalGetSet::SetAutoWrapMode(const bool wrapAtEOL)
{
return NT_SUCCESS(DoSrvPrivateSetAutoWrapMode(wrapAtEOL));
auto& outputMode = _io.GetActiveOutputBuffer().OutputMode;
WI_UpdateFlag(outputMode, ENABLE_WRAP_AT_EOL_OUTPUT, wrapAtEOL);
}
// Routine Description:
// - Connects the PrivateShowCursor call directly into our Driver Message servicing call inside Conhost.exe
// PrivateShowCursor is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Makes the cursor visible or hidden. Does not modify blinking state.
// Arguments:
// - show - set to true to make the cursor visible, false to hide.
// - visible - set to true to make the cursor visible, false to hide.
// Return Value:
// - true if successful (see DoSrvPrivateShowCursor). false otherwise.
bool ConhostInternalGetSet::PrivateShowCursor(const bool show) noexcept
// - <none>
void ConhostInternalGetSet::SetCursorVisibility(const bool visible)
{
DoSrvPrivateShowCursor(_io.GetActiveOutputBuffer(), show);
return true;
auto& textBuffer = _io.GetActiveOutputBuffer().GetTextBuffer();
textBuffer.GetCursor().SetIsVisible(visible);
}
// Routine Description:
// - Connects the PrivateAllowCursorBlinking call directly into our Driver Message servicing call inside Conhost.exe
// PrivateAllowCursorBlinking is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Enables or disables the cursor blinking.
// Arguments:
// - fEnable - set to true to enable blinking, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateAllowCursorBlinking). false otherwise.
bool ConhostInternalGetSet::PrivateAllowCursorBlinking(const bool fEnable)
// - true if successful. false otherwise.
bool ConhostInternalGetSet::EnableCursorBlinking(const bool fEnable)
{
DoSrvPrivateAllowCursorBlinking(_io.GetActiveOutputBuffer(), fEnable);
auto& textBuffer = _io.GetActiveOutputBuffer().GetTextBuffer();
textBuffer.GetCursor().SetBlinkingAllowed(fEnable);
// GH#2642 - From what we've gathered from other terminals, when blinking is
// disabled, the cursor should remain On always, and have the visibility
// controlled by the IsVisible property. So when you do a printf "\e[?12l"
// to disable blinking, the cursor stays stuck On. At this point, only the
// cursor visibility property controls whether the user can see it or not.
// (Yes, the cursor can be On and NOT Visible)
textBuffer.GetCursor().SetIsOn(true);
bool isPty;
DoSrvIsConsolePty(isPty);
// If we are connected to a pty, return that we could not handle this
// so that the VT sequence gets flushed to terminal.
// Note: we technically don't need to handle it ourselves at all if
// we are connected to a pty (i.e. we could have just returned false
// immediately without needing to call DoSrvPrivateAllowCursorBlinking),
// but we call it anyway for consistency, just in case.
return !isPty;
return !IsConsolePty();
}
// Routine Description:
// - Connects the PrivateSetScrollingRegion call directly into our Driver Message servicing call inside Conhost.exe
// PrivateSetScrollingRegion is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Sets the top and bottom scrolling margins for the current page. This creates
// a subsection of the screen that scrolls when input reaches the end of the
// region, leaving the rest of the screen untouched.
// Arguments:
// - scrollMargins - The bounds of the region to be the scrolling region of the viewport.
// - scrollMargins - A rect who's Top and Bottom members will be used to set
// the new values of the top and bottom margins. If (0,0), then the margins
// will be disabled. NOTE: This is a rect in the case that we'll need the
// left and right margins in the future.
// Return Value:
// - true if successful (see DoSrvPrivateSetScrollingRegion). false otherwise.
bool ConhostInternalGetSet::PrivateSetScrollingRegion(const SMALL_RECT& scrollMargins)
// - <none>
void ConhostInternalGetSet::SetScrollingRegion(const SMALL_RECT& scrollMargins)
{
return NT_SUCCESS(DoSrvPrivateSetScrollingRegion(_io.GetActiveOutputBuffer(), scrollMargins));
auto& screenInfo = _io.GetActiveOutputBuffer();
auto srScrollMargins = screenInfo.GetRelativeScrollMargins().ToInclusive();
srScrollMargins.Top = scrollMargins.Top;
srScrollMargins.Bottom = scrollMargins.Bottom;
screenInfo.SetScrollMargins(Viewport::FromInclusive(srScrollMargins));
}
// Method Description:
@ -383,146 +376,214 @@ bool ConhostInternalGetSet::PrivateSetScrollingRegion(const SMALL_RECT& scrollMa
// - None
// Return Value:
// - true if a line feed also produces a carriage return. false otherwise.
bool ConhostInternalGetSet::PrivateGetLineFeedMode() const
bool ConhostInternalGetSet::GetLineFeedMode() const
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.IsReturnOnNewlineAutomatic();
}
// Routine Description:
// - Connects the PrivateLineFeed call directly into our Driver Message servicing call inside Conhost.exe
// PrivateLineFeed is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// - Performs a line feed, possibly preceded by carriage return.
// Arguments:
// - withReturn - Set to true if a carriage return should be performed as well.
// Return Value:
// - true if successful (see DoSrvPrivateLineFeed). false otherwise.
bool ConhostInternalGetSet::PrivateLineFeed(const bool withReturn)
// - <none>
void ConhostInternalGetSet::LineFeed(const bool withReturn)
{
return NT_SUCCESS(DoSrvPrivateLineFeed(_io.GetActiveOutputBuffer(), withReturn));
auto& screenInfo = _io.GetActiveOutputBuffer();
auto& textBuffer = screenInfo.GetTextBuffer();
auto cursorPosition = textBuffer.GetCursor().GetPosition();
// We turn the cursor on before an operation that might scroll the viewport, otherwise
// that can result in an old copy of the cursor being left behind on the screen.
textBuffer.GetCursor().SetIsOn(true);
// Since we are explicitly moving down a row, clear the wrap status on the row we're leaving
textBuffer.GetRowByOffset(cursorPosition.Y).SetWrapForced(false);
cursorPosition.Y += 1;
if (withReturn)
{
cursorPosition.X = 0;
}
else
{
cursorPosition = textBuffer.ClampPositionWithinLine(cursorPosition);
}
THROW_IF_NTSTATUS_FAILED(AdjustCursorPosition(screenInfo, cursorPosition, FALSE, nullptr));
}
// Routine Description:
// - Sends a notify message to play the "SystemHand" sound event.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::PrivateWarningBell()
// - <none>
void ConhostInternalGetSet::WarningBell()
{
return _io.GetActiveOutputBuffer().SendNotifyBeep();
_io.GetActiveOutputBuffer().SendNotifyBeep();
}
// Routine Description:
// - Connects the PrivateReverseLineFeed call directly into our Driver Message servicing call inside Conhost.exe
// PrivateReverseLineFeed is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Performs a "Reverse line feed", essentially, the opposite of '\n'.
// Return Value:
// - true if successful (see DoSrvPrivateReverseLineFeed). false otherwise.
bool ConhostInternalGetSet::PrivateReverseLineFeed()
// - <none>
void ConhostInternalGetSet::ReverseLineFeed()
{
return NT_SUCCESS(DoSrvPrivateReverseLineFeed(_io.GetActiveOutputBuffer()));
auto& screenInfo = _io.GetActiveOutputBuffer();
const SMALL_RECT viewport = screenInfo.GetViewport().ToInclusive();
const COORD oldCursorPosition = screenInfo.GetTextBuffer().GetCursor().GetPosition();
COORD newCursorPosition = { oldCursorPosition.X, oldCursorPosition.Y - 1 };
newCursorPosition = screenInfo.GetTextBuffer().ClampPositionWithinLine(newCursorPosition);
// If the cursor is at the top of the viewport, we don't want to shift the viewport up.
// We want it to stay exactly where it is.
// In that case, shift the buffer contents down, to emulate inserting a line
// at the top of the buffer.
if (oldCursorPosition.Y > viewport.Top)
{
// Cursor is below the top line of the viewport
THROW_IF_NTSTATUS_FAILED(AdjustCursorPosition(screenInfo, newCursorPosition, TRUE, nullptr));
}
else
{
// If we don't have margins, or the cursor is within the boundaries of the margins
// It's important to check if the cursor is in the margins,
// If it's not, but the margins are set, then we don't want to scroll anything
if (screenInfo.IsCursorInMargins(oldCursorPosition))
{
// Cursor is at the top of the viewport
// Rectangle to cut out of the existing buffer. This is inclusive.
// It will be clipped to the buffer boundaries so SHORT_MAX gives us the full buffer width.
SMALL_RECT srScroll;
srScroll.Left = 0;
srScroll.Right = SHORT_MAX;
srScroll.Top = viewport.Top;
srScroll.Bottom = viewport.Bottom;
// Clip to the DECSTBM margin boundary
if (screenInfo.AreMarginsSet())
{
srScroll.Bottom = screenInfo.GetAbsoluteScrollMargins().BottomInclusive();
}
// Paste coordinate for cut text above
COORD coordDestination;
coordDestination.X = 0;
coordDestination.Y = viewport.Top + 1;
// Note the revealed lines are filled with the standard erase attributes.
ScrollRegion(srScroll, srScroll, coordDestination, true);
}
}
}
// Routine Description:
// - Connects the SetConsoleTitleW API call directly into our Driver Message servicing call inside Conhost.exe
// - Sets the title of the console window.
// Arguments:
// - title - The null-terminated string to set as the window title
// Return Value:
// - true if successful (see DoSrvSetConsoleTitle). false otherwise.
bool ConhostInternalGetSet::SetConsoleTitleW(std::wstring_view title)
// - <none>
void ConhostInternalGetSet::SetWindowTitle(std::wstring_view title)
{
return SUCCEEDED(DoSrvSetConsoleTitleW(title));
ServiceLocator::LocateGlobals().getConsoleInformation().SetTitle(title);
}
// Routine Description:
// - Connects the PrivateUseAlternateScreenBuffer call directly into our Driver Message servicing call inside Conhost.exe
// PrivateUseAlternateScreenBuffer is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Swaps to the alternate screen buffer. In virtual terminals, there exists both a "main"
// screen buffer and an alternate. This creates a new alternate, and switches to it.
// If there is an already existing alternate, it is discarded.
// Return Value:
// - true if successful (see DoSrvPrivateUseAlternateScreenBuffer). false otherwise.
bool ConhostInternalGetSet::PrivateUseAlternateScreenBuffer()
// - <none>
void ConhostInternalGetSet::UseAlternateScreenBuffer()
{
return NT_SUCCESS(DoSrvPrivateUseAlternateScreenBuffer(_io.GetActiveOutputBuffer()));
THROW_IF_NTSTATUS_FAILED(_io.GetActiveOutputBuffer().UseAlternateScreenBuffer());
}
// Routine Description:
// - Connects the PrivateUseMainScreenBuffer call directly into our Driver Message servicing call inside Conhost.exe
// PrivateUseMainScreenBuffer is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// - Swaps to the main screen buffer. From the alternate buffer, returns to the main screen
// buffer. From the main screen buffer, does nothing. The alternate is discarded.
// Return Value:
// - true if successful (see DoSrvPrivateUseMainScreenBuffer). false otherwise.
bool ConhostInternalGetSet::PrivateUseMainScreenBuffer()
// - <none>
void ConhostInternalGetSet::UseMainScreenBuffer()
{
DoSrvPrivateUseMainScreenBuffer(_io.GetActiveOutputBuffer());
return true;
_io.GetActiveOutputBuffer().UseMainScreenBuffer();
}
// Routine Description:
// - Connects the PrivateEraseAll call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEraseAll is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// Arguments:
// <none>
// - Performs a VT-style erase all operation on the buffer.
// See SCREEN_INFORMATION::VtEraseAll's description for details.
// Return Value:
// - true if successful (see DoSrvPrivateEraseAll). false otherwise.
bool ConhostInternalGetSet::PrivateEraseAll()
// - <none>
void ConhostInternalGetSet::EraseAll()
{
return SUCCEEDED(DoSrvPrivateEraseAll(_io.GetActiveOutputBuffer()));
THROW_IF_FAILED(_io.GetActiveOutputBuffer().VtEraseAll());
}
bool ConhostInternalGetSet::PrivateClearBuffer()
// Routine Description:
// - Clears the entire contents of the viewport, except for the cursor's row,
// which is moved to the top line of the viewport.
// See SCREEN_INFORMATION::ClearBuffer's description for details.
// Return Value:
// - <none>
void ConhostInternalGetSet::ClearBuffer()
{
return SUCCEEDED(DoSrvPrivateClearBuffer(_io.GetActiveOutputBuffer()));
THROW_IF_FAILED(_io.GetActiveOutputBuffer().ClearBuffer());
}
// Method Description:
// - Retrieves the current user default cursor style.
// Arguments:
// - style - Structure to receive cursor style.
// - <none>
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::GetUserDefaultCursorStyle(CursorType& style)
// - the default cursor style.
CursorType ConhostInternalGetSet::GetUserDefaultCursorStyle() const
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
style = gci.GetCursorType();
return true;
return gci.GetCursorType();
}
// Routine Description:
// - Connects the SetCursorStyle call directly into our Driver Message servicing call inside Conhost.exe
// SetCursorStyle is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// - Sets the current cursor style.
// Arguments:
// - style: The style of cursor to change the cursor to.
// Return Value:
// - true if successful (see DoSrvSetCursorStyle). false otherwise.
bool ConhostInternalGetSet::SetCursorStyle(const CursorType style)
// - <none>
void ConhostInternalGetSet::SetCursorStyle(const CursorType style)
{
DoSrvSetCursorStyle(_io.GetActiveOutputBuffer(), style);
return true;
_io.GetActiveOutputBuffer().GetTextBuffer().GetCursor().SetType(style);
}
// Routine Description:
// - Connects the PrivatePrependConsoleInput API call directly into our Driver Message servicing call inside Conhost.exe
// - Forces the renderer to repaint the screen. If the input screen buffer is
// not the active one, then just do nothing. We only want to redraw the
// screen buffer that requested the repaint, and switching screen buffers
// will already force a repaint.
// Arguments:
// - <none>
// Return Value:
// - true if successful (see DoSrvPrivateRefreshWindow). false otherwise.
bool ConhostInternalGetSet::PrivateRefreshWindow()
// - <none>
void ConhostInternalGetSet::RefreshWindow()
{
DoSrvPrivateRefreshWindow(_io.GetActiveOutputBuffer());
return true;
auto& g = ServiceLocator::LocateGlobals();
if (&_io.GetActiveOutputBuffer() == &g.getConsoleInformation().GetActiveOutputBuffer())
{
g.pRender->TriggerRedrawAll();
}
}
// Routine Description:
// - Connects the PrivateWriteConsoleControlInput API call directly into our Driver Message servicing call inside Conhost.exe
// - Writes the input KeyEvent to the console as a console control event. This
// can be used for potentially generating Ctrl-C events, as
// HandleGenericKeyEvent will correctly generate the Ctrl-C response in
// the same way that it'd be handled from the window proc, with the proper
// processed vs raw input handling.
// If the input key is *not* a Ctrl-C key, then it will get written to the
// buffer just the same as any other KeyEvent.
// Arguments:
// - key - a KeyEvent representing a special type of keypress, typically Ctrl-C
// - key - The keyevent to send to the console.
// Return Value:
// - true if successful (see DoSrvPrivateWriteConsoleControlInput). false otherwise.
bool ConhostInternalGetSet::PrivateWriteConsoleControlInput(const KeyEvent key)
// - <none>
void ConhostInternalGetSet::WriteControlInput(const KeyEvent key)
{
return SUCCEEDED(DoSrvPrivateWriteConsoleControlInput(_io.GetActiveInputBuffer(),
key));
HandleGenericKeyEvent(key, false);
}
// Routine Description:
@ -530,74 +591,121 @@ bool ConhostInternalGetSet::PrivateWriteConsoleControlInput(const KeyEvent key)
// Arguments:
// - codepage - the new output codepage of the console.
// Return Value:
// - true if successful (see DoSrvSetConsoleOutputCodePage). false otherwise.
bool ConhostInternalGetSet::SetConsoleOutputCP(const unsigned int codepage)
// - <none>
void ConhostInternalGetSet::SetConsoleOutputCP(const unsigned int codepage)
{
return SUCCEEDED(DoSrvSetConsoleOutputCodePage(codepage));
THROW_IF_FAILED(DoSrvSetConsoleOutputCodePage(codepage));
}
// Routine Description:
// - Connects the GetConsoleOutputCP API call directly into our Driver Message servicing call inside Conhost.exe
// Arguments:
// - codepage - receives the outputCP of the console.
// Return Value:
// - true if successful (see DoSrvPrivateWriteConsoleControlInput). false otherwise.
bool ConhostInternalGetSet::GetConsoleOutputCP(unsigned int& codepage)
{
DoSrvGetConsoleOutputCodePage(codepage);
return true;
}
// Routine Description:
// - Connects the PrivateSuppressResizeRepaint API call directly into our Driver
// Message servicing call inside Conhost.exe
// - Gets the codepage used for translating text when calling A versions of functions affecting the output buffer.
// Arguments:
// - <none>
// Return Value:
// - true if successful (see DoSrvPrivateSuppressResizeRepaint). false otherwise.
bool ConhostInternalGetSet::PrivateSuppressResizeRepaint()
// - the outputCP of the console.
unsigned int ConhostInternalGetSet::GetConsoleOutputCP() const
{
return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint());
return ServiceLocator::LocateGlobals().getConsoleInformation().OutputCP;
}
// Routine Description:
// - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe
// - NOTE: This ONE method behaves differently! The rest of the methods on this
// interface return true if successful. This one just returns the result.
// - Forces the VT Renderer to NOT paint the next resize event. This is used by
// InteractDispatch, to prevent resizes from echoing between terminal and host.
// Arguments:
// - isPty: receives the bool indicating whether or not we're in pty mode.
// - <none>
// Return Value:
// - <none>
void ConhostInternalGetSet::SuppressResizeRepaint()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
THROW_IF_FAILED(gci.GetVtIo()->SuppressResizeRepaint());
}
// Routine Description:
// - Checks if the console host is acting as a pty.
// Arguments:
// - <none>
// Return Value:
// - true if we're in pty mode.
bool ConhostInternalGetSet::IsConsolePty() const
{
bool isPty = false;
DoSrvIsConsolePty(isPty);
return isPty;
return ServiceLocator::LocateGlobals().getConsoleInformation().IsInVtIoMode();
}
bool ConhostInternalGetSet::DeleteLines(const size_t count)
// Routine Description:
// - Deletes lines in the active screen buffer.
// Parameters:
// - count - the number of lines to delete
void ConhostInternalGetSet::DeleteLines(const size_t count)
{
DoSrvPrivateDeleteLines(count);
return true;
_modifyLines(count, false);
}
bool ConhostInternalGetSet::InsertLines(const size_t count)
// Routine Description:
// - Inserts lines in the active screen buffer.
// Parameters:
// - count - the number of lines to insert
void ConhostInternalGetSet::InsertLines(const size_t count)
{
DoSrvPrivateInsertLines(count);
return true;
_modifyLines(count, true);
}
// Routine Description:
// - internal logic for adding or removing lines in the active screen buffer
// this also moves the cursor to the left margin, which is expected behavior for IL and DL
// Parameters:
// - count - the number of lines to modify
// - insert - true if inserting lines, false if deleting lines
void ConhostInternalGetSet::_modifyLines(const size_t count, const bool insert)
{
auto& screenInfo = _io.GetActiveOutputBuffer();
auto& textBuffer = screenInfo.GetTextBuffer();
const auto cursorPosition = textBuffer.GetCursor().GetPosition();
if (screenInfo.IsCursorInMargins(cursorPosition))
{
// Rectangle to cut out of the existing buffer. This is inclusive.
// It will be clipped to the buffer boundaries so SHORT_MAX gives us the full buffer width.
SMALL_RECT srScroll;
srScroll.Left = 0;
srScroll.Right = SHORT_MAX;
srScroll.Top = cursorPosition.Y;
srScroll.Bottom = screenInfo.GetViewport().BottomInclusive();
// Clip to the DECSTBM margin boundary
if (screenInfo.AreMarginsSet())
{
srScroll.Bottom = screenInfo.GetAbsoluteScrollMargins().BottomInclusive();
}
// Paste coordinate for cut text above
COORD coordDestination;
coordDestination.X = 0;
if (insert)
{
coordDestination.Y = (cursorPosition.Y) + gsl::narrow<short>(count);
}
else
{
coordDestination.Y = (cursorPosition.Y) - gsl::narrow<short>(count);
}
// Note the revealed lines are filled with the standard erase attributes.
ScrollRegion(srScroll, srScroll, coordDestination, true);
// The IL and DL controls are also expected to move the cursor to the left margin.
// For now this is just column 0, since we don't yet support DECSLRM.
THROW_IF_NTSTATUS_FAILED(screenInfo.SetCursorPosition({ 0, cursorPosition.Y }, false));
}
}
// Method Description:
// - Connects the MoveToBottom call directly into our Driver Message servicing
// call inside Conhost.exe
// - Snaps the screen buffer's viewport to the "virtual bottom", the last place
// the viewport was before the user scrolled it (with the mouse or scrollbar)
// Arguments:
// <none>
// - <none>
// Return Value:
// - true if successful (see DoSrvPrivateMoveToBottom). false otherwise.
bool ConhostInternalGetSet::MoveToBottom() const
// - <none>
void ConhostInternalGetSet::MoveToBottom()
{
DoSrvPrivateMoveToBottom(_io.GetActiveOutputBuffer());
return true;
_io.GetActiveOutputBuffer().MoveToBottom();
}
// Method Description:
@ -606,17 +714,12 @@ bool ConhostInternalGetSet::MoveToBottom() const
// - tableIndex: the index of the color table to retrieve.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF ConhostInternalGetSet::GetColorTableEntry(const size_t tableIndex) const noexcept
try
COLORREF ConhostInternalGetSet::GetColorTableEntry(const size_t tableIndex) const
{
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
return gci.GetColorTableEntry(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
}
// Method Description:
// - Updates the value in the colortable at index tableIndex to the new color
@ -626,8 +729,7 @@ catch (...)
// - color: the new COLORREF to use as that color table value.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept
try
bool ConhostInternalGetSet::SetColorTableEntry(const size_t tableIndex, const COLORREF color)
{
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
@ -646,7 +748,6 @@ try
// correct color.
return !gci.IsInVtIoMode();
}
CATCH_RETURN_FALSE()
// Routine Description:
// - Sets the position in the color table for the given color alias.
@ -655,43 +756,61 @@ CATCH_RETURN_FALSE()
// - tableIndex: the new position of the alias in the color table.
// Return Value:
// - <none>
void ConhostInternalGetSet::SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) noexcept
void ConhostInternalGetSet::SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex)
{
auto& renderSettings = ServiceLocator::LocateGlobals().getConsoleInformation().GetRenderSettings();
renderSettings.SetColorAliasIndex(alias, tableIndex);
}
// Routine Description:
// - Connects the PrivateFillRegion call directly into our Driver Message servicing
// call inside Conhost.exe
// PrivateFillRegion is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// - Fills a region of the screen buffer.
// Arguments:
// - screenInfo - Reference to screen buffer info.
// - startPosition - The position to begin filling at.
// - fillLength - The number of characters to fill.
// - fillChar - Character to fill the target region with.
// - standardFillAttrs - If true, fill with the standard erase attributes.
// If false, fill with the default attributes.
// Return value:
// - true if successful (see DoSrvPrivateScrollRegion). false otherwise.
bool ConhostInternalGetSet::PrivateFillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) noexcept
// - <none>
void ConhostInternalGetSet::FillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs)
{
return SUCCEEDED(DoSrvPrivateFillRegion(_io.GetActiveOutputBuffer(),
startPosition,
fillLength,
fillChar,
standardFillAttrs));
auto& screenInfo = _io.GetActiveOutputBuffer();
if (fillLength == 0)
{
return;
}
// For most VT erasing operations, the standard requires that the
// erased area be filled with the current background color, but with
// no additional meta attributes set. For all other cases, we just
// fill with the default attributes.
auto fillAttrs = TextAttribute{};
if (standardFillAttrs)
{
fillAttrs = screenInfo.GetAttributes();
fillAttrs.SetStandardErase();
}
const auto fillData = OutputCellIterator{ fillChar, fillAttrs, fillLength };
screenInfo.Write(fillData, startPosition, false);
// Notify accessibility
if (screenInfo.HasAccessibilityEventing())
{
auto endPosition = startPosition;
const auto bufferSize = screenInfo.GetBufferSize();
bufferSize.MoveInBounds(fillLength - 1, endPosition);
screenInfo.NotifyAccessibilityEventing(startPosition.X, startPosition.Y, endPosition.X, endPosition.Y);
}
}
// Routine Description:
// - Connects the PrivateScrollRegion call directly into our Driver Message servicing
// call inside Conhost.exe
// PrivateScrollRegion is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// - Moves a block of data in the screen buffer, optionally limiting the effects
// of the move to a clipping rectangle.
// Arguments:
// - scrollRect - Region to copy/move (source and size).
// - clipRect - Optional clip region to contain buffer change effects.
@ -699,28 +818,37 @@ bool ConhostInternalGetSet::PrivateFillRegion(const COORD startPosition,
// - standardFillAttrs - If true, fill with the standard erase attributes.
// If false, fill with the default attributes.
// Return value:
// - true if successful (see DoSrvPrivateScrollRegion). false otherwise.
bool ConhostInternalGetSet::PrivateScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) noexcept
// - <none>
void ConhostInternalGetSet::ScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs)
{
return SUCCEEDED(DoSrvPrivateScrollRegion(_io.GetActiveOutputBuffer(),
scrollRect,
clipRect,
destinationOrigin,
standardFillAttrs));
auto& screenInfo = _io.GetActiveOutputBuffer();
// For most VT scrolling operations, the standard requires that the
// erased area be filled with the current background color, but with
// no additional meta attributes set. For all other cases, we just
// fill with the default attributes.
auto fillAttrs = TextAttribute{};
if (standardFillAttrs)
{
fillAttrs = screenInfo.GetAttributes();
fillAttrs.SetStandardErase();
}
::ScrollRegion(screenInfo, scrollRect, clipRect, destinationOrigin, UNICODE_SPACE, fillAttrs);
}
// Routine Description:
// - Checks if the InputBuffer is willing to accept VT Input directly
// PrivateIsVtInputEnabled is an internal-only "API" call that the vt commands can execute,
// IsVtInputEnabled is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// Arguments:
// - <none>
// Return value:
// - true if enabled (see IsInVirtualTerminalInputMode). false otherwise.
bool ConhostInternalGetSet::PrivateIsVtInputEnabled() const
bool ConhostInternalGetSet::IsVtInputEnabled() const
{
return _io.GetActiveInputBuffer()->IsInVirtualTerminalInputMode();
}
@ -731,17 +859,23 @@ bool ConhostInternalGetSet::PrivateIsVtInputEnabled() const
// Arguments:
// - The hyperlink URI
// Return Value:
// - true
bool ConhostInternalGetSet::PrivateAddHyperlink(const std::wstring_view uri, const std::wstring_view params) const
// - <none>
void ConhostInternalGetSet::AddHyperlink(const std::wstring_view uri, const std::wstring_view params) const
{
DoSrvAddHyperlink(_io.GetActiveOutputBuffer(), uri, params);
return true;
auto& screenInfo = _io.GetActiveOutputBuffer();
auto attr = screenInfo.GetAttributes();
const auto id = screenInfo.GetTextBuffer().GetHyperlinkId(uri, params);
attr.SetHyperlinkId(id);
screenInfo.GetTextBuffer().SetCurrentAttributes(attr);
screenInfo.GetTextBuffer().AddHyperlinkToMap(uri, id);
}
bool ConhostInternalGetSet::PrivateEndHyperlink() const
void ConhostInternalGetSet::EndHyperlink() const
{
DoSrvEndHyperlink(_io.GetActiveOutputBuffer());
return true;
auto& screenInfo = _io.GetActiveOutputBuffer();
auto attr = screenInfo.GetAttributes();
attr.SetHyperlinkId(0);
screenInfo.GetTextBuffer().SetCurrentAttributes(attr);
}
// Routine Description:
@ -751,10 +885,14 @@ bool ConhostInternalGetSet::PrivateEndHyperlink() const
// - cellSize - The cell size for an individual glyph.
// - centeringHint - The horizontal extent that glyphs are offset from center.
// Return Value:
// - true if successful (see DoSrvUpdateSoftFont). false otherwise.
bool ConhostInternalGetSet::PrivateUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept
// - <none>
void ConhostInternalGetSet::UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint)
{
return SUCCEEDED(DoSrvUpdateSoftFont(bitPattern, cellSize, centeringHint));
auto* pRender = ServiceLocator::LocateGlobals().pRender;
if (pRender)
{
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
}
}

Просмотреть файл

@ -54,93 +54,93 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
public:
ConhostInternalGetSet(_In_ Microsoft::Console::IIoProvider& io);
bool GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const override;
bool SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) override;
void GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const override;
void SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) override;
bool SetConsoleCursorPosition(const COORD position) override;
void SetCursorPosition(const COORD position) override;
bool PrivateGetTextAttributes(TextAttribute& attrs) const override;
bool PrivateSetTextAttributes(const TextAttribute& attrs) override;
TextAttribute GetTextAttributes() const override;
void SetTextAttributes(const TextAttribute& attrs) override;
bool PrivateSetCurrentLineRendition(const LineRendition lineRendition) override;
bool PrivateResetLineRenditionRange(const size_t startRow, const size_t endRow) override;
SHORT PrivateGetLineWidth(const size_t row) const override;
void SetCurrentLineRendition(const LineRendition lineRendition) override;
void ResetLineRenditionRange(const size_t startRow, const size_t endRow) override;
SHORT GetLineWidth(const size_t row) const override;
bool PrivateWriteConsoleInputW(std::deque<std::unique_ptr<IInputEvent>>& events,
size_t& eventsWritten) override;
void WriteInput(std::deque<std::unique_ptr<IInputEvent>>& events, size_t& eventsWritten) override;
bool SetConsoleWindowInfo(bool const absolute,
const SMALL_RECT& window) override;
void SetWindowInfo(bool const absolute, const SMALL_RECT& window) override;
bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
bool SetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode, const bool enabled) override;
void SetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode, const bool enabled) override;
bool GetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode) const override;
bool SetRenderMode(const RenderSettings::Mode mode, const bool enabled) override;
void SetRenderMode(const RenderSettings::Mode mode, const bool enabled) override;
bool PrivateSetAutoWrapMode(const bool wrapAtEOL) override;
void SetAutoWrapMode(const bool wrapAtEOL) override;
bool PrivateShowCursor(const bool show) noexcept override;
bool PrivateAllowCursorBlinking(const bool enable) override;
void SetCursorVisibility(const bool visible) override;
bool EnableCursorBlinking(const bool enable) override;
bool PrivateSetScrollingRegion(const SMALL_RECT& scrollMargins) override;
void SetScrollingRegion(const SMALL_RECT& scrollMargins) override;
bool PrivateWarningBell() override;
void WarningBell() override;
bool PrivateGetLineFeedMode() const override;
bool PrivateLineFeed(const bool withReturn) override;
bool PrivateReverseLineFeed() override;
bool GetLineFeedMode() const override;
void LineFeed(const bool withReturn) override;
void ReverseLineFeed() override;
bool SetConsoleTitleW(const std::wstring_view title) override;
void SetWindowTitle(const std::wstring_view title) override;
bool PrivateUseAlternateScreenBuffer() override;
void UseAlternateScreenBuffer() override;
bool PrivateUseMainScreenBuffer() override;
void UseMainScreenBuffer() override;
bool PrivateEraseAll() override;
bool PrivateClearBuffer() override;
void EraseAll() override;
void ClearBuffer() override;
bool GetUserDefaultCursorStyle(CursorType& style) override;
bool SetCursorStyle(CursorType const style) override;
CursorType GetUserDefaultCursorStyle() const override;
void SetCursorStyle(CursorType const style) override;
bool PrivateRefreshWindow() override;
void RefreshWindow() override;
bool PrivateSuppressResizeRepaint() override;
void SuppressResizeRepaint() override;
bool PrivateWriteConsoleControlInput(const KeyEvent key) override;
void WriteControlInput(const KeyEvent key) override;
bool SetConsoleOutputCP(const unsigned int codepage) override;
bool GetConsoleOutputCP(unsigned int& codepage) override;
void SetConsoleOutputCP(const unsigned int codepage) override;
unsigned int GetConsoleOutputCP() const override;
bool IsConsolePty() const override;
bool DeleteLines(const size_t count) override;
bool InsertLines(const size_t count) override;
void DeleteLines(const size_t count) override;
void InsertLines(const size_t count) override;
bool MoveToBottom() const override;
void MoveToBottom() override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) noexcept override;
COLORREF GetColorTableEntry(const size_t tableIndex) const override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) override;
void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) override;
bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) noexcept override;
void FillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) override;
bool PrivateScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) noexcept override;
void ScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) override;
bool PrivateIsVtInputEnabled() const override;
bool IsVtInputEnabled() const override;
bool PrivateAddHyperlink(const std::wstring_view uri, const std::wstring_view params) const override;
bool PrivateEndHyperlink() const override;
void AddHyperlink(const std::wstring_view uri, const std::wstring_view params) const override;
void EndHyperlink() const override;
bool PrivateUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept override;
void UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) override;
private:
void _modifyLines(const size_t count, const bool insert);
Microsoft::Console::IIoProvider& _io;
};

Просмотреть файл

@ -384,7 +384,7 @@ void ConptyOutputTests::SetConsoleTitleWithControlChars()
std::wstringstream titleText;
titleText << L"Hello " << wchar_t(control) << L"World!";
VERIFY_SUCCEEDED(DoSrvSetConsoleTitleW(titleText.str()));
g.getConsoleInformation().SetTitle(titleText.str());
// This is the standard init sequences for the first frame.
expectedOutput.push_back("\x1b[2J");

Просмотреть файл

@ -416,6 +416,7 @@ void ScreenBufferTests::TestReverseLineFeed()
auto& stateMachine = screenInfo.GetStateMachine();
auto& cursor = screenInfo._textBuffer->GetCursor();
auto viewport = screenInfo.GetViewport();
const auto reverseLineFeed = L"\033M";
VERIFY_ARE_EQUAL(viewport.Top(), 0);
@ -427,7 +428,7 @@ void ScreenBufferTests::TestReverseLineFeed()
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 1);
VERIFY_ARE_EQUAL(viewport.Top(), 0);
VERIFY_SUCCEEDED(DoSrvPrivateReverseLineFeed(screenInfo));
stateMachine.ProcessString(reverseLineFeed);
VERIFY_ARE_EQUAL(cursor.GetPosition().X, 3);
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 0);
@ -448,7 +449,7 @@ void ScreenBufferTests::TestReverseLineFeed()
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 0);
VERIFY_ARE_EQUAL(screenInfo.GetViewport().Top(), 0);
VERIFY_SUCCEEDED(DoSrvPrivateReverseLineFeed(screenInfo));
stateMachine.ProcessString(reverseLineFeed);
VERIFY_ARE_EQUAL(cursor.GetPosition().X, 9);
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 0);
@ -473,7 +474,7 @@ void ScreenBufferTests::TestReverseLineFeed()
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 5);
VERIFY_ARE_EQUAL(screenInfo.GetViewport().Top(), 5);
LOG_IF_FAILED(DoSrvPrivateReverseLineFeed(screenInfo));
stateMachine.ProcessString(reverseLineFeed);
VERIFY_ARE_EQUAL(cursor.GetPosition().X, 8);
VERIFY_ARE_EQUAL(cursor.GetPosition().Y, 5);

Просмотреть файл

@ -24,47 +24,36 @@ bool DispatchCommon::s_ResizeWindow(ConGetSet& conApi,
SHORT sColumns = 0;
SHORT sRows = 0;
THROW_IF_FAILED(SizeTToShort(width, &sColumns));
THROW_IF_FAILED(SizeTToShort(height, &sRows));
// We should do nothing if 0 is passed in for a size.
bool success = SUCCEEDED(SizeTToShort(width, &sColumns)) &&
SUCCEEDED(SizeTToShort(height, &sRows)) &&
(width > 0 && height > 0);
RETURN_BOOL_IF_FALSE(width > 0 && height > 0);
if (success)
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
conApi.GetConsoleScreenBufferInfoEx(csbiex);
const Viewport oldViewport = Viewport::FromInclusive(csbiex.srWindow);
const Viewport newViewport = Viewport::FromDimensions(oldViewport.Origin(), sColumns, sRows);
// Always resize the width of the console
csbiex.dwSize.X = sColumns;
// Only set the screen buffer's height if it's currently less than
// what we're requesting.
if (sRows > csbiex.dwSize.Y)
{
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
success = conApi.GetConsoleScreenBufferInfoEx(csbiex);
if (success)
{
const Viewport oldViewport = Viewport::FromInclusive(csbiex.srWindow);
const Viewport newViewport = Viewport::FromDimensions(oldViewport.Origin(),
sColumns,
sRows);
// Always resize the width of the console
csbiex.dwSize.X = sColumns;
// Only set the screen buffer's height if it's currently less than
// what we're requesting.
if (sRows > csbiex.dwSize.Y)
{
csbiex.dwSize.Y = sRows;
}
// SetConsoleWindowInfo expect inclusive rects
const auto sri = newViewport.ToInclusive();
// SetConsoleScreenBufferInfoEx however expects exclusive rects
const auto sre = newViewport.ToExclusive();
csbiex.srWindow = sre;
success = conApi.SetConsoleScreenBufferInfoEx(csbiex);
if (success)
{
success = conApi.SetConsoleWindowInfo(true, sri);
}
}
csbiex.dwSize.Y = sRows;
}
return success;
// SetWindowInfo expect inclusive rects
const auto sri = newViewport.ToInclusive();
// SetConsoleScreenBufferInfoEx however expects exclusive rects
const auto sre = newViewport.ToExclusive();
csbiex.srWindow = sre;
conApi.SetConsoleScreenBufferInfoEx(csbiex);
conApi.SetWindowInfo(true, sri);
return true;
}
// Routine Description:
@ -72,10 +61,10 @@ bool DispatchCommon::s_ResizeWindow(ConGetSet& conApi,
// Arguments:
// - conApi: The ConGetSet implementation to call back into.
// Return Value:
// True if handled successfully. False otherwise.
bool DispatchCommon::s_RefreshWindow(ConGetSet& conApi)
// - <none>
void DispatchCommon::s_RefreshWindow(ConGetSet& conApi)
{
return conApi.PrivateRefreshWindow();
conApi.RefreshWindow();
}
// Routine Description:
@ -86,8 +75,8 @@ bool DispatchCommon::s_RefreshWindow(ConGetSet& conApi)
// Arguments:
// - conApi: The ConGetSet implementation to call back into.
// Return Value:
// True if handled successfully. False otherwise.
bool DispatchCommon::s_SuppressResizeRepaint(ConGetSet& conApi)
// - <none>
void DispatchCommon::s_SuppressResizeRepaint(ConGetSet& conApi)
{
return conApi.PrivateSuppressResizeRepaint();
conApi.SuppressResizeRepaint();
}

Просмотреть файл

@ -26,8 +26,8 @@ namespace Microsoft::Console::VirtualTerminal
const size_t width,
const size_t height);
static bool s_RefreshWindow(ConGetSet& conApi);
static void s_RefreshWindow(ConGetSet& conApi);
static bool s_SuppressResizeRepaint(ConGetSet& conApi);
static void s_SuppressResizeRepaint(ConGetSet& conApi);
};
}

Просмотреть файл

@ -29,11 +29,12 @@ InteractDispatch::InteractDispatch(std::unique_ptr<ConGetSet> pConApi) :
// Arguments:
// - inputEvents: a collection of IInputEvents
// Return Value:
// True if handled successfully. False otherwise.
// - True.
bool InteractDispatch::WriteInput(std::deque<std::unique_ptr<IInputEvent>>& inputEvents)
{
size_t written = 0;
return _pConApi->PrivateWriteConsoleInputW(inputEvents, written);
_pConApi->WriteInput(inputEvents, written);
return true;
}
// Method Description:
@ -44,10 +45,11 @@ bool InteractDispatch::WriteInput(std::deque<std::unique_ptr<IInputEvent>>& inpu
// Arguments:
// - event: The key to send to the host.
// Return Value:
// True if handled successfully. False otherwise.
// - True.
bool InteractDispatch::WriteCtrlKey(const KeyEvent& event)
{
return _pConApi->PrivateWriteConsoleControlInput(event);
_pConApi->WriteControlInput(event);
return true;
}
// Method Description:
@ -56,18 +58,12 @@ bool InteractDispatch::WriteCtrlKey(const KeyEvent& event)
// Arguments:
// - string : a string to write to the console.
// Return Value:
// True if handled successfully. False otherwise.
// - True.
bool InteractDispatch::WriteString(const std::wstring_view string)
{
if (string.empty())
{
return true;
}
unsigned int codepage = 0;
bool success = _pConApi->GetConsoleOutputCP(codepage);
if (success)
if (!string.empty())
{
const auto codepage = _pConApi->GetConsoleOutputCP();
std::deque<std::unique_ptr<IInputEvent>> keyEvents;
for (const auto& wch : string)
@ -79,9 +75,9 @@ bool InteractDispatch::WriteString(const std::wstring_view string)
std::back_inserter(keyEvents));
}
success = WriteInput(keyEvents);
WriteInput(keyEvents);
}
return success;
return true;
}
//Method Description:
@ -100,30 +96,25 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio
const VTParameter parameter1,
const VTParameter parameter2)
{
bool success = false;
// Other Window Manipulation functions:
// MSFT:13271098 - QueryViewport
// MSFT:13271146 - QueryScreenSize
switch (function)
{
case DispatchTypes::WindowManipulationType::RefreshWindow:
success = DispatchCommon::s_RefreshWindow(*_pConApi);
break;
DispatchCommon::s_RefreshWindow(*_pConApi);
return true;
case DispatchTypes::WindowManipulationType::ResizeWindowInCharacters:
// TODO:GH#1765 We should introduce a better `ResizeConpty` function to
// the ConGetSet interface, that specifically handles a conpty resize.
success = DispatchCommon::s_ResizeWindow(*_pConApi, parameter2.value_or(0), parameter1.value_or(0));
if (success)
if (DispatchCommon::s_ResizeWindow(*_pConApi, parameter2.value_or(0), parameter1.value_or(0)))
{
DispatchCommon::s_SuppressResizeRepaint(*_pConApi);
}
break;
return true;
default:
success = false;
break;
return false;
}
return success;
}
//Method Description:
@ -133,71 +124,39 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio
// - row: The row to move the cursor to.
// - col: The column to move the cursor to.
// Return value:
// True if we successfully moved the cursor to the given location.
// False otherwise, including if given invalid coordinates (either component being 0)
// or if any API calls failed.
// - True.
bool InteractDispatch::MoveCursor(const size_t row, const size_t col)
{
size_t rowFixed = row;
size_t colFixed = col;
// The parser should never return 0 (0 maps to 1), so this is a failure condition.
THROW_HR_IF(E_INVALIDARG, row == 0);
THROW_HR_IF(E_INVALIDARG, col == 0);
bool success = true;
// In VT, the origin is 1,1. For our array, it's 0,0. So subtract 1.
if (row != 0)
{
rowFixed = row - 1;
}
else
{
// The parser should never return 0 (0 maps to 1), so this is a failure condition.
success = false;
}
const size_t rowFixed = row - 1;
const size_t colFixed = col - 1;
if (col != 0)
{
colFixed = col - 1;
}
else
{
// The parser should never return 0 (0 maps to 1), so this is a failure condition.
success = false;
}
// First retrieve some information about the buffer
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
_pConApi->GetConsoleScreenBufferInfoEx(csbiex);
if (success)
{
// First retrieve some information about the buffer
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
success = _pConApi->GetConsoleScreenBufferInfoEx(csbiex);
COORD coordCursor = csbiex.dwCursorPosition;
if (success)
{
COORD coordCursor = csbiex.dwCursorPosition;
// Safely convert the size_t positions we were given into shorts (which is the size the console deals with)
THROW_IF_FAILED(SizeTToShort(rowFixed, &coordCursor.Y));
THROW_IF_FAILED(SizeTToShort(colFixed, &coordCursor.X));
// Safely convert the size_t positions we were given into shorts (which is the size the console deals with)
success = SUCCEEDED(SizeTToShort(rowFixed, &coordCursor.Y)) &&
SUCCEEDED(SizeTToShort(colFixed, &coordCursor.X));
// Set the line and column values as offsets from the viewport edge. Use safe math to prevent overflow.
THROW_IF_FAILED(ShortAdd(coordCursor.Y, csbiex.srWindow.Top, &coordCursor.Y));
THROW_IF_FAILED(ShortAdd(coordCursor.X, csbiex.srWindow.Left, &coordCursor.X));
if (success)
{
// Set the line and column values as offsets from the viewport edge. Use safe math to prevent overflow.
success = SUCCEEDED(ShortAdd(coordCursor.Y, csbiex.srWindow.Top, &coordCursor.Y)) &&
SUCCEEDED(ShortAdd(coordCursor.X, csbiex.srWindow.Left, &coordCursor.X));
// Apply boundary tests to ensure the cursor isn't outside the viewport rectangle.
coordCursor.Y = std::clamp(coordCursor.Y, csbiex.srWindow.Top, gsl::narrow<SHORT>(csbiex.srWindow.Bottom - 1));
coordCursor.X = std::clamp(coordCursor.X, csbiex.srWindow.Left, gsl::narrow<SHORT>(csbiex.srWindow.Right - 1));
if (success)
{
// Apply boundary tests to ensure the cursor isn't outside the viewport rectangle.
coordCursor.Y = std::clamp(coordCursor.Y, csbiex.srWindow.Top, gsl::narrow<SHORT>(csbiex.srWindow.Bottom - 1));
coordCursor.X = std::clamp(coordCursor.X, csbiex.srWindow.Left, gsl::narrow<SHORT>(csbiex.srWindow.Right - 1));
// Finally, attempt to set the adjusted cursor position back into the console.
success = _pConApi->SetConsoleCursorPosition(coordCursor);
}
}
}
}
return success;
// Finally, attempt to set the adjusted cursor position back into the console.
_pConApi->SetCursorPosition(coordCursor);
return true;
}
// Routine Description:
@ -208,5 +167,5 @@ bool InteractDispatch::MoveCursor(const size_t row, const size_t col)
// - true if enabled (see IsInVirtualTerminalInputMode). false otherwise.
bool InteractDispatch::IsVtInputEnabled() const
{
return _pConApi->PrivateIsVtInputEnabled();
return _pConApi->IsVtInputEnabled();
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -171,25 +171,25 @@ namespace Microsoft::Console::VirtualTerminal
};
bool _CursorMovePosition(const Offset rowOffset, const Offset colOffset, const bool clampInMargins) const;
bool _EraseSingleLineHelper(const CONSOLE_SCREEN_BUFFER_INFOEX& csbiex,
void _EraseSingleLineHelper(const CONSOLE_SCREEN_BUFFER_INFOEX& csbiex,
const DispatchTypes::EraseType eraseType,
const size_t lineId) const;
bool _EraseScrollback();
bool _EraseAll();
bool _InsertDeleteHelper(const size_t count, const bool isInsert) const;
bool _ScrollMovement(const ScrollDirection dir, const size_t distance) const;
void _EraseScrollback();
void _EraseAll();
void _InsertDeleteHelper(const size_t count, const bool isInsert) const;
void _ScrollMovement(const ScrollDirection dir, const size_t distance) const;
bool _DoSetTopBottomScrollingMargins(const size_t topMargin,
void _DoSetTopBottomScrollingMargins(const size_t topMargin,
const size_t bottomMargin);
bool _OperatingStatus() const;
bool _CursorPositionReport() const;
void _OperatingStatus() const;
void _CursorPositionReport() const;
bool _WriteResponse(const std::wstring_view reply) const;
void _WriteResponse(const std::wstring_view reply) const;
bool _ModeParamsHelper(const DispatchTypes::ModeParams param, const bool enable);
bool _DoDECCOLMHelper(const size_t columns);
bool _ClearSingleTabStop();
bool _ClearAllTabStops() noexcept;
void _ClearSingleTabStop();
void _ClearAllTabStops() noexcept;
void _ResetTabStops() noexcept;
void _InitTabStopsForWidth(const size_t width);

Просмотреть файл

@ -72,196 +72,192 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const VTParameters options,
// - options - An array of options that will be applied from 0 to N, in order,
// one at a time by setting or removing flags in the font style properties.
// Return Value:
// - True if handled successfully. False otherwise.
// - True.
bool AdaptDispatch::SetGraphicsRendition(const VTParameters options)
{
TextAttribute attr;
bool success = _pConApi->PrivateGetTextAttributes(attr);
TextAttribute attr = _pConApi->GetTextAttributes();
if (success)
// Run through the graphics options and apply them
for (size_t i = 0; i < options.size(); i++)
{
// Run through the graphics options and apply them
for (size_t i = 0; i < options.size(); i++)
const GraphicsOptions opt = options.at(i);
switch (opt)
{
const GraphicsOptions opt = options.at(i);
switch (opt)
{
case Off:
attr.SetDefaultForeground();
attr.SetDefaultBackground();
attr.SetDefaultMetaAttrs();
break;
case ForegroundDefault:
attr.SetDefaultForeground();
break;
case BackgroundDefault:
attr.SetDefaultBackground();
break;
case Intense:
attr.SetIntense(true);
break;
case RGBColorOrFaint:
attr.SetFaint(true);
break;
case NotIntenseOrFaint:
attr.SetIntense(false);
attr.SetFaint(false);
break;
case Italics:
attr.SetItalic(true);
break;
case NotItalics:
attr.SetItalic(false);
break;
case BlinkOrXterm256Index:
case RapidBlink: // We just interpret rapid blink as an alias of blink.
attr.SetBlinking(true);
break;
case Steady:
attr.SetBlinking(false);
break;
case Invisible:
attr.SetInvisible(true);
break;
case Visible:
attr.SetInvisible(false);
break;
case CrossedOut:
attr.SetCrossedOut(true);
break;
case NotCrossedOut:
attr.SetCrossedOut(false);
break;
case Negative:
attr.SetReverseVideo(true);
break;
case Positive:
attr.SetReverseVideo(false);
break;
case Underline:
attr.SetUnderlined(true);
break;
case DoublyUnderlined:
attr.SetDoublyUnderlined(true);
break;
case NoUnderline:
attr.SetUnderlined(false);
attr.SetDoublyUnderlined(false);
break;
case Overline:
attr.SetOverlined(true);
break;
case NoOverline:
attr.SetOverlined(false);
break;
case ForegroundBlack:
attr.SetIndexedForeground(TextColor::DARK_BLACK);
break;
case ForegroundBlue:
attr.SetIndexedForeground(TextColor::DARK_BLUE);
break;
case ForegroundGreen:
attr.SetIndexedForeground(TextColor::DARK_GREEN);
break;
case ForegroundCyan:
attr.SetIndexedForeground(TextColor::DARK_CYAN);
break;
case ForegroundRed:
attr.SetIndexedForeground(TextColor::DARK_RED);
break;
case ForegroundMagenta:
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
break;
case ForegroundYellow:
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
break;
case ForegroundWhite:
attr.SetIndexedForeground(TextColor::DARK_WHITE);
break;
case BackgroundBlack:
attr.SetIndexedBackground(TextColor::DARK_BLACK);
break;
case BackgroundBlue:
attr.SetIndexedBackground(TextColor::DARK_BLUE);
break;
case BackgroundGreen:
attr.SetIndexedBackground(TextColor::DARK_GREEN);
break;
case BackgroundCyan:
attr.SetIndexedBackground(TextColor::DARK_CYAN);
break;
case BackgroundRed:
attr.SetIndexedBackground(TextColor::DARK_RED);
break;
case BackgroundMagenta:
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
break;
case BackgroundYellow:
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
break;
case BackgroundWhite:
attr.SetIndexedBackground(TextColor::DARK_WHITE);
break;
case BrightForegroundBlack:
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
break;
case BrightForegroundBlue:
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
break;
case BrightForegroundGreen:
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
break;
case BrightForegroundCyan:
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
break;
case BrightForegroundRed:
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
break;
case BrightForegroundMagenta:
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
break;
case BrightForegroundYellow:
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
break;
case BrightForegroundWhite:
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
break;
case BrightBackgroundBlack:
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
break;
case BrightBackgroundBlue:
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
break;
case BrightBackgroundGreen:
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
break;
case BrightBackgroundCyan:
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
break;
case BrightBackgroundRed:
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
break;
case BrightBackgroundMagenta:
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
break;
case BrightBackgroundYellow:
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
break;
case BrightBackgroundWhite:
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
break;
case ForegroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
break;
case BackgroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, false);
break;
}
case Off:
attr.SetDefaultForeground();
attr.SetDefaultBackground();
attr.SetDefaultMetaAttrs();
break;
case ForegroundDefault:
attr.SetDefaultForeground();
break;
case BackgroundDefault:
attr.SetDefaultBackground();
break;
case Intense:
attr.SetIntense(true);
break;
case RGBColorOrFaint:
attr.SetFaint(true);
break;
case NotIntenseOrFaint:
attr.SetIntense(false);
attr.SetFaint(false);
break;
case Italics:
attr.SetItalic(true);
break;
case NotItalics:
attr.SetItalic(false);
break;
case BlinkOrXterm256Index:
case RapidBlink: // We just interpret rapid blink as an alias of blink.
attr.SetBlinking(true);
break;
case Steady:
attr.SetBlinking(false);
break;
case Invisible:
attr.SetInvisible(true);
break;
case Visible:
attr.SetInvisible(false);
break;
case CrossedOut:
attr.SetCrossedOut(true);
break;
case NotCrossedOut:
attr.SetCrossedOut(false);
break;
case Negative:
attr.SetReverseVideo(true);
break;
case Positive:
attr.SetReverseVideo(false);
break;
case Underline:
attr.SetUnderlined(true);
break;
case DoublyUnderlined:
attr.SetDoublyUnderlined(true);
break;
case NoUnderline:
attr.SetUnderlined(false);
attr.SetDoublyUnderlined(false);
break;
case Overline:
attr.SetOverlined(true);
break;
case NoOverline:
attr.SetOverlined(false);
break;
case ForegroundBlack:
attr.SetIndexedForeground(TextColor::DARK_BLACK);
break;
case ForegroundBlue:
attr.SetIndexedForeground(TextColor::DARK_BLUE);
break;
case ForegroundGreen:
attr.SetIndexedForeground(TextColor::DARK_GREEN);
break;
case ForegroundCyan:
attr.SetIndexedForeground(TextColor::DARK_CYAN);
break;
case ForegroundRed:
attr.SetIndexedForeground(TextColor::DARK_RED);
break;
case ForegroundMagenta:
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
break;
case ForegroundYellow:
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
break;
case ForegroundWhite:
attr.SetIndexedForeground(TextColor::DARK_WHITE);
break;
case BackgroundBlack:
attr.SetIndexedBackground(TextColor::DARK_BLACK);
break;
case BackgroundBlue:
attr.SetIndexedBackground(TextColor::DARK_BLUE);
break;
case BackgroundGreen:
attr.SetIndexedBackground(TextColor::DARK_GREEN);
break;
case BackgroundCyan:
attr.SetIndexedBackground(TextColor::DARK_CYAN);
break;
case BackgroundRed:
attr.SetIndexedBackground(TextColor::DARK_RED);
break;
case BackgroundMagenta:
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
break;
case BackgroundYellow:
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
break;
case BackgroundWhite:
attr.SetIndexedBackground(TextColor::DARK_WHITE);
break;
case BrightForegroundBlack:
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
break;
case BrightForegroundBlue:
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
break;
case BrightForegroundGreen:
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
break;
case BrightForegroundCyan:
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
break;
case BrightForegroundRed:
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
break;
case BrightForegroundMagenta:
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
break;
case BrightForegroundYellow:
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
break;
case BrightForegroundWhite:
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
break;
case BrightBackgroundBlack:
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
break;
case BrightBackgroundBlue:
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
break;
case BrightBackgroundGreen:
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
break;
case BrightBackgroundCyan:
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
break;
case BrightBackgroundRed:
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
break;
case BrightBackgroundMagenta:
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
break;
case BrightBackgroundYellow:
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
break;
case BrightBackgroundWhite:
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
break;
case ForegroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
break;
case BackgroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, false);
break;
}
success = _pConApi->PrivateSetTextAttributes(attr);
}
_pConApi->SetTextAttributes(attr);
return success;
return true;
}
// Method Description:
@ -271,20 +267,12 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options)
// be saved. Options that are not supported are ignored. If no options are specified,
// all attributes are stored.
// Return Value:
// - True if handled successfully. False otherwise.
// - True.
bool AdaptDispatch::PushGraphicsRendition(const VTParameters options)
{
bool success = true;
TextAttribute currentAttributes;
success = _pConApi->PrivateGetTextAttributes(currentAttributes);
if (success)
{
_sgrStack.Push(currentAttributes, options);
}
return success;
const auto currentAttributes = _pConApi->GetTextAttributes();
_sgrStack.Push(currentAttributes, options);
return true;
}
// Method Description:
@ -293,18 +281,10 @@ bool AdaptDispatch::PushGraphicsRendition(const VTParameters options)
// Arguments:
// - <none>
// Return Value:
// - True if handled successfully. False otherwise.
// - True.
bool AdaptDispatch::PopGraphicsRendition()
{
bool success = true;
TextAttribute currentAttributes;
success = _pConApi->PrivateGetTextAttributes(currentAttributes);
if (success)
{
success = _pConApi->PrivateSetTextAttributes(_sgrStack.Pop(currentAttributes));
}
return success;
const auto currentAttributes = _pConApi->GetTextAttributes();
_pConApi->SetTextAttributes(_sgrStack.Pop(currentAttributes));
return true;
}

Просмотреть файл

@ -34,80 +34,78 @@ namespace Microsoft::Console::VirtualTerminal
public:
virtual ~ConGetSet() = default;
virtual bool GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const = 0;
virtual bool SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) = 0;
virtual bool SetConsoleCursorPosition(const COORD position) = 0;
virtual void GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const = 0;
virtual void SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) = 0;
virtual void SetCursorPosition(const COORD position) = 0;
virtual bool PrivateIsVtInputEnabled() const = 0;
virtual bool IsVtInputEnabled() const = 0;
virtual bool PrivateGetTextAttributes(TextAttribute& attrs) const = 0;
virtual bool PrivateSetTextAttributes(const TextAttribute& attrs) = 0;
virtual TextAttribute GetTextAttributes() const = 0;
virtual void SetTextAttributes(const TextAttribute& attrs) = 0;
virtual bool PrivateSetCurrentLineRendition(const LineRendition lineRendition) = 0;
virtual bool PrivateResetLineRenditionRange(const size_t startRow, const size_t endRow) = 0;
virtual SHORT PrivateGetLineWidth(const size_t row) const = 0;
virtual void SetCurrentLineRendition(const LineRendition lineRendition) = 0;
virtual void ResetLineRenditionRange(const size_t startRow, const size_t endRow) = 0;
virtual SHORT GetLineWidth(const size_t row) const = 0;
virtual bool PrivateWriteConsoleInputW(std::deque<std::unique_ptr<IInputEvent>>& events,
size_t& eventsWritten) = 0;
virtual bool SetConsoleWindowInfo(const bool absolute,
const SMALL_RECT& window) = 0;
virtual void WriteInput(std::deque<std::unique_ptr<IInputEvent>>& events, size_t& eventsWritten) = 0;
virtual void SetWindowInfo(const bool absolute, const SMALL_RECT& window) = 0;
virtual bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) = 0;
virtual bool SetParserMode(const StateMachine::Mode mode, const bool enabled) = 0;
virtual void SetParserMode(const StateMachine::Mode mode, const bool enabled) = 0;
virtual bool GetParserMode(const StateMachine::Mode mode) const = 0;
virtual bool SetRenderMode(const RenderSettings::Mode mode, const bool enabled) = 0;
virtual void SetRenderMode(const RenderSettings::Mode mode, const bool enabled) = 0;
virtual bool PrivateSetAutoWrapMode(const bool wrapAtEOL) = 0;
virtual void SetAutoWrapMode(const bool wrapAtEOL) = 0;
virtual bool PrivateShowCursor(const bool show) = 0;
virtual bool PrivateAllowCursorBlinking(const bool enable) = 0;
virtual void SetCursorVisibility(const bool visible) = 0;
virtual bool EnableCursorBlinking(const bool enable) = 0;
virtual bool PrivateSetScrollingRegion(const SMALL_RECT& scrollMargins) = 0;
virtual bool PrivateWarningBell() = 0;
virtual bool PrivateGetLineFeedMode() const = 0;
virtual bool PrivateLineFeed(const bool withReturn) = 0;
virtual bool PrivateReverseLineFeed() = 0;
virtual bool SetConsoleTitleW(const std::wstring_view title) = 0;
virtual bool PrivateUseAlternateScreenBuffer() = 0;
virtual bool PrivateUseMainScreenBuffer() = 0;
virtual void SetScrollingRegion(const SMALL_RECT& scrollMargins) = 0;
virtual void WarningBell() = 0;
virtual bool GetLineFeedMode() const = 0;
virtual void LineFeed(const bool withReturn) = 0;
virtual void ReverseLineFeed() = 0;
virtual void SetWindowTitle(const std::wstring_view title) = 0;
virtual void UseAlternateScreenBuffer() = 0;
virtual void UseMainScreenBuffer() = 0;
virtual bool PrivateEraseAll() = 0;
virtual bool PrivateClearBuffer() = 0;
virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0;
virtual bool SetCursorStyle(const CursorType style) = 0;
virtual bool PrivateWriteConsoleControlInput(const KeyEvent key) = 0;
virtual bool PrivateRefreshWindow() = 0;
virtual void EraseAll() = 0;
virtual void ClearBuffer() = 0;
virtual CursorType GetUserDefaultCursorStyle() const = 0;
virtual void SetCursorStyle(const CursorType style) = 0;
virtual void WriteControlInput(const KeyEvent key) = 0;
virtual void RefreshWindow() = 0;
virtual bool SetConsoleOutputCP(const unsigned int codepage) = 0;
virtual bool GetConsoleOutputCP(unsigned int& codepage) = 0;
virtual void SetConsoleOutputCP(const unsigned int codepage) = 0;
virtual unsigned int GetConsoleOutputCP() const = 0;
virtual bool PrivateSuppressResizeRepaint() = 0;
virtual void SuppressResizeRepaint() = 0;
virtual bool IsConsolePty() const = 0;
virtual bool DeleteLines(const size_t count) = 0;
virtual bool InsertLines(const size_t count) = 0;
virtual void DeleteLines(const size_t count) = 0;
virtual void InsertLines(const size_t count) = 0;
virtual bool MoveToBottom() const = 0;
virtual void MoveToBottom() = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) = 0;
virtual void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) = 0;
virtual bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) = 0;
virtual void FillRegion(const COORD startPosition,
const size_t fillLength,
const wchar_t fillChar,
const bool standardFillAttrs) = 0;
virtual bool PrivateScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) = 0;
virtual void ScrollRegion(const SMALL_RECT scrollRect,
const std::optional<SMALL_RECT> clipRect,
const COORD destinationOrigin,
const bool standardFillAttrs) = 0;
virtual bool PrivateAddHyperlink(const std::wstring_view uri, const std::wstring_view params) const = 0;
virtual bool PrivateEndHyperlink() const = 0;
virtual void AddHyperlink(const std::wstring_view uri, const std::wstring_view params) const = 0;
virtual void EndHyperlink() const = 0;
virtual bool PrivateUpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) = 0;
virtual void UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) = 0;
};
}

Просмотреть файл

@ -58,58 +58,43 @@ using namespace Microsoft::Console::VirtualTerminal;
class TestGetSet final : public ConGetSet
{
public:
bool GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& sbiex) const override
void GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& sbiex) const override
{
Log::Comment(L"GetConsoleScreenBufferInfoEx MOCK returning data...");
if (_getConsoleScreenBufferInfoExResult)
{
sbiex.dwSize = _bufferSize;
sbiex.srWindow = _viewport;
sbiex.dwCursorPosition = _cursorPos;
sbiex.wAttributes = _attribute.GetLegacyAttributes();
}
return _getConsoleScreenBufferInfoExResult;
THROW_HR_IF(E_FAIL, !_getConsoleScreenBufferInfoExResult);
sbiex.dwSize = _bufferSize;
sbiex.srWindow = _viewport;
sbiex.dwCursorPosition = _cursorPos;
sbiex.wAttributes = _attribute.GetLegacyAttributes();
}
bool SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& sbiex) override
void SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& sbiex) override
{
Log::Comment(L"SetConsoleScreenBufferInfoEx MOCK returning data...");
if (_setConsoleScreenBufferInfoExResult)
{
VERIFY_ARE_EQUAL(_expectedCursorPos, sbiex.dwCursorPosition);
VERIFY_ARE_EQUAL(_expectedScreenBufferSize, sbiex.dwSize);
VERIFY_ARE_EQUAL(_expectedScreenBufferViewport, sbiex.srWindow);
VERIFY_ARE_EQUAL(_expectedAttribute, TextAttribute{ sbiex.wAttributes });
}
return _setConsoleScreenBufferInfoExResult;
THROW_HR_IF(E_FAIL, !_setConsoleScreenBufferInfoExResult);
VERIFY_ARE_EQUAL(_expectedCursorPos, sbiex.dwCursorPosition);
VERIFY_ARE_EQUAL(_expectedScreenBufferSize, sbiex.dwSize);
VERIFY_ARE_EQUAL(_expectedScreenBufferViewport, sbiex.srWindow);
VERIFY_ARE_EQUAL(_expectedAttribute, TextAttribute{ sbiex.wAttributes });
}
bool SetConsoleCursorPosition(const COORD position) override
void SetCursorPosition(const COORD position) override
{
Log::Comment(L"SetConsoleCursorPosition MOCK called...");
Log::Comment(L"SetCursorPosition MOCK called...");
if (_setConsoleCursorPositionResult)
{
VERIFY_ARE_EQUAL(_expectedCursorPos, position);
_cursorPos = position;
}
return _setConsoleCursorPositionResult;
THROW_HR_IF(E_FAIL, !_setCursorPositionResult);
VERIFY_ARE_EQUAL(_expectedCursorPos, position);
_cursorPos = position;
}
bool SetConsoleWindowInfo(const bool absolute, const SMALL_RECT& window) override
void SetWindowInfo(const bool absolute, const SMALL_RECT& window) override
{
Log::Comment(L"SetConsoleWindowInfo MOCK called...");
Log::Comment(L"SetWindowInfo MOCK called...");
if (_setConsoleWindowInfoResult)
{
VERIFY_ARE_EQUAL(_expectedWindowAbsolute, absolute);
VERIFY_ARE_EQUAL(_expectedConsoleWindow, window);
_viewport = window;
}
return _setConsoleWindowInfoResult;
THROW_HR_IF(E_FAIL, !_setWindowInfoResult);
VERIFY_ARE_EQUAL(_expectedWindowAbsolute, absolute);
VERIFY_ARE_EQUAL(_expectedConsoleWindow, window);
_viewport = window;
}
bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) override
@ -125,7 +110,7 @@ public:
return _setInputModeResult;
}
bool SetParserMode(const StateMachine::Mode mode, const bool enabled) override
void SetParserMode(const StateMachine::Mode mode, const bool enabled) override
{
Log::Comment(L"SetParserMode MOCK called...");
@ -134,8 +119,6 @@ public:
VERIFY_ARE_EQUAL(_expectedParserMode, mode);
VERIFY_ARE_EQUAL(_expectedParserModeEnabled, enabled);
}
return _setParserModeResult;
}
bool GetParserMode(const StateMachine::Mode /*mode*/) const override
@ -145,263 +128,208 @@ public:
return false;
}
bool SetRenderMode(const RenderSettings::Mode /*mode*/, const bool /*enabled*/) override
void SetRenderMode(const RenderSettings::Mode /*mode*/, const bool /*enabled*/) override
{
Log::Comment(L"SetRenderMode MOCK called...");
return false;
}
bool PrivateSetAutoWrapMode(const bool /*wrapAtEOL*/) override
void SetAutoWrapMode(const bool /*wrapAtEOL*/) override
{
Log::Comment(L"PrivateSetAutoWrapMode MOCK called...");
return false;
Log::Comment(L"SetAutoWrapMode MOCK called...");
}
bool PrivateShowCursor(const bool show) override
void SetCursorVisibility(const bool visible) override
{
Log::Comment(L"PrivateShowCursor MOCK called...");
Log::Comment(L"SetCursorVisibility MOCK called...");
if (_privateShowCursorResult)
{
VERIFY_ARE_EQUAL(_expectedShowCursor, show);
}
return _privateShowCursorResult;
THROW_HR_IF(E_FAIL, !_setCursorVisibilityResult);
VERIFY_ARE_EQUAL(_expectedCursorVisibility, visible);
}
bool PrivateAllowCursorBlinking(const bool enable) override
bool EnableCursorBlinking(const bool enable) override
{
Log::Comment(L"PrivateAllowCursorBlinking MOCK called...");
Log::Comment(L"EnableCursorBlinking MOCK called...");
if (_privateAllowCursorBlinkingResult)
if (_enableCursorBlinkingResult)
{
VERIFY_ARE_EQUAL(_enable, enable);
}
return _privateAllowCursorBlinkingResult;
return _enableCursorBlinkingResult;
}
bool PrivateIsVtInputEnabled() const override
bool IsVtInputEnabled() const override
{
return false;
}
bool PrivateGetTextAttributes(TextAttribute& attrs) const
TextAttribute GetTextAttributes() const
{
Log::Comment(L"PrivateGetTextAttributes MOCK called...");
Log::Comment(L"GetTextAttributes MOCK called...");
if (_privateGetTextAttributesResult)
{
attrs = _attribute;
}
return _privateGetTextAttributesResult;
THROW_HR_IF(E_FAIL, !_getTextAttributesResult);
return _attribute;
}
bool PrivateSetTextAttributes(const TextAttribute& attrs)
void SetTextAttributes(const TextAttribute& attrs)
{
Log::Comment(L"PrivateSetTextAttributes MOCK called...");
Log::Comment(L"SetTextAttributes MOCK called...");
if (_privateSetTextAttributesResult)
{
VERIFY_ARE_EQUAL(_expectedAttribute, attrs);
_attribute = attrs;
}
return _privateSetTextAttributesResult;
THROW_HR_IF(E_FAIL, !_setTextAttributesResult);
VERIFY_ARE_EQUAL(_expectedAttribute, attrs);
_attribute = attrs;
}
bool PrivateSetCurrentLineRendition(const LineRendition /*lineRendition*/)
void SetCurrentLineRendition(const LineRendition /*lineRendition*/)
{
Log::Comment(L"PrivateSetCurrentLineRendition MOCK called...");
return false;
Log::Comment(L"SetCurrentLineRendition MOCK called...");
}
bool PrivateResetLineRenditionRange(const size_t /*startRow*/, const size_t /*endRow*/)
void ResetLineRenditionRange(const size_t /*startRow*/, const size_t /*endRow*/)
{
Log::Comment(L"PrivateResetLineRenditionRange MOCK called...");
return false;
Log::Comment(L"ResetLineRenditionRange MOCK called...");
}
SHORT PrivateGetLineWidth(const size_t /*row*/) const
SHORT GetLineWidth(const size_t /*row*/) const
{
Log::Comment(L"PrivateGetLineWidth MOCK called...");
Log::Comment(L"GetLineWidth MOCK called...");
return _bufferSize.X;
}
bool PrivateWriteConsoleInputW(std::deque<std::unique_ptr<IInputEvent>>& events,
size_t& eventsWritten) override
void WriteInput(std::deque<std::unique_ptr<IInputEvent>>& events, size_t& eventsWritten) override
{
Log::Comment(L"PrivateWriteConsoleInputW MOCK called...");
Log::Comment(L"WriteInput MOCK called...");
if (_privateWriteConsoleInputWResult)
THROW_HR_IF(E_FAIL, !_writeInputResult);
// move all the input events we were given into local storage so we can test against them
Log::Comment(NoThrowString().Format(L"Moving %zu input events into local storage...", events.size()));
if (_retainInput)
{
// move all the input events we were given into local storage so we can test against them
Log::Comment(NoThrowString().Format(L"Moving %zu input events into local storage...", events.size()));
if (_retainInput)
{
std::move(events.begin(), events.end(), std::back_inserter(_events));
}
else
{
_events.clear();
_events.swap(events);
}
eventsWritten = _events.size();
std::move(events.begin(), events.end(), std::back_inserter(_events));
}
return _privateWriteConsoleInputWResult;
else
{
_events.clear();
_events.swap(events);
}
eventsWritten = _events.size();
}
bool PrivateWriteConsoleControlInput(_In_ KeyEvent key) override
void WriteControlInput(_In_ KeyEvent key) override
{
Log::Comment(L"PrivateWriteConsoleControlInput MOCK called...");
Log::Comment(L"WriteControlInput MOCK called...");
if (_privateWriteConsoleControlInputResult)
{
VERIFY_ARE_EQUAL('C', key.GetVirtualKeyCode());
VERIFY_ARE_EQUAL(0x3, key.GetCharData());
VERIFY_ARE_EQUAL(true, key.IsCtrlPressed());
}
return _privateWriteConsoleControlInputResult;
THROW_HR_IF(E_FAIL, !_writeControlInputResult);
VERIFY_ARE_EQUAL('C', key.GetVirtualKeyCode());
VERIFY_ARE_EQUAL(0x3, key.GetCharData());
VERIFY_ARE_EQUAL(true, key.IsCtrlPressed());
}
bool PrivateSetScrollingRegion(const SMALL_RECT& scrollMargins) override
void SetScrollingRegion(const SMALL_RECT& scrollMargins) override
{
Log::Comment(L"PrivateSetScrollingRegion MOCK called...");
Log::Comment(L"SetScrollingRegion MOCK called...");
if (_privateSetScrollingRegionResult)
if (_setScrollingRegionResult)
{
VERIFY_ARE_EQUAL(_expectedScrollRegion, scrollMargins);
_activeScrollRegion = scrollMargins;
}
return _privateSetScrollingRegionResult;
}
bool PrivateWarningBell() override
void WarningBell() override
{
Log::Comment(L"PrivateWarningBell MOCK called...");
// We made it through the adapter, woo! Return true.
return TRUE;
Log::Comment(L"WarningBell MOCK called...");
}
bool PrivateGetLineFeedMode() const override
bool GetLineFeedMode() const override
{
Log::Comment(L"PrivateGetLineFeedMode MOCK called...");
return _privateGetLineFeedModeResult;
Log::Comment(L"GetLineFeedMode MOCK called...");
return _getLineFeedModeResult;
}
bool PrivateLineFeed(const bool withReturn) override
void LineFeed(const bool withReturn) override
{
Log::Comment(L"PrivateLineFeed MOCK called...");
Log::Comment(L"LineFeed MOCK called...");
if (_privateLineFeedResult)
{
VERIFY_ARE_EQUAL(_expectedLineFeedWithReturn, withReturn);
}
return _privateLineFeedResult;
THROW_HR_IF(E_FAIL, !_lineFeedResult);
VERIFY_ARE_EQUAL(_expectedLineFeedWithReturn, withReturn);
}
bool PrivateReverseLineFeed() override
void ReverseLineFeed() override
{
Log::Comment(L"PrivateReverseLineFeed MOCK called...");
// We made it through the adapter, woo! Return true.
return TRUE;
Log::Comment(L"ReverseLineFeed MOCK called...");
}
bool SetConsoleTitleW(const std::wstring_view title)
void SetWindowTitle(const std::wstring_view title)
{
Log::Comment(L"SetConsoleTitleW MOCK called...");
Log::Comment(L"SetWindowTitle MOCK called...");
if (_setConsoleTitleWResult)
if (_setWindowTitleResult)
{
// Put into WEX strings for rich logging when they don't compare.
VERIFY_ARE_EQUAL(String(_expectedWindowTitle.data(), gsl::narrow<int>(_expectedWindowTitle.size())),
String(title.data(), gsl::narrow<int>(title.size())));
}
return TRUE;
}
bool PrivateUseAlternateScreenBuffer() override
void UseAlternateScreenBuffer() override
{
Log::Comment(L"PrivateUseAlternateScreenBuffer MOCK called...");
return true;
Log::Comment(L"UseAlternateScreenBuffer MOCK called...");
}
bool PrivateUseMainScreenBuffer() override
void UseMainScreenBuffer() override
{
Log::Comment(L"PrivateUseMainScreenBuffer MOCK called...");
return true;
Log::Comment(L"UseMainScreenBuffer MOCK called...");
}
bool PrivateEraseAll() override
void EraseAll() override
{
Log::Comment(L"PrivateEraseAll MOCK called...");
return TRUE;
Log::Comment(L"EraseAll MOCK called...");
}
bool PrivateClearBuffer() override
void ClearBuffer() override
{
Log::Comment(L"PrivateClearBuffer MOCK called...");
return TRUE;
Log::Comment(L"ClearBuffer MOCK called...");
}
bool GetUserDefaultCursorStyle(CursorType& style) override
CursorType GetUserDefaultCursorStyle() const override
{
style = CursorType::Legacy;
return true;
return CursorType::Legacy;
}
bool SetCursorStyle(const CursorType cursorType) override
void SetCursorStyle(const CursorType cursorType) override
{
Log::Comment(L"SetCursorStyle MOCK called...");
if (_setCursorStyleResult)
{
VERIFY_ARE_EQUAL(_expectedCursorStyle, cursorType);
}
return _setCursorStyleResult;
THROW_HR_IF(E_FAIL, !_setCursorStyleResult);
VERIFY_ARE_EQUAL(_expectedCursorStyle, cursorType);
}
bool PrivateRefreshWindow() override
void RefreshWindow() override
{
Log::Comment(L"PrivateRefreshWindow MOCK called...");
// We made it through the adapter, woo! Return true.
return TRUE;
Log::Comment(L"RefreshWindow MOCK called...");
}
bool PrivateSuppressResizeRepaint() override
void SuppressResizeRepaint() override
{
Log::Comment(L"PrivateSuppressResizeRepaint MOCK called...");
Log::Comment(L"SuppressResizeRepaint MOCK called...");
VERIFY_IS_TRUE(false, L"AdaptDispatch should never be calling this function.");
return FALSE;
}
bool SetConsoleOutputCP(const unsigned int codepage) override
void SetConsoleOutputCP(const unsigned int codepage) override
{
Log::Comment(L"SetConsoleOutputCP MOCK called...");
if (_setConsoleOutputCPResult)
{
VERIFY_ARE_EQUAL(_expectedOutputCP, codepage);
}
return _setConsoleOutputCPResult;
THROW_HR_IF(E_FAIL, !_setConsoleOutputCPResult);
VERIFY_ARE_EQUAL(_expectedOutputCP, codepage);
}
bool GetConsoleOutputCP(unsigned int& codepage) override
unsigned int GetConsoleOutputCP() const override
{
Log::Comment(L"GetConsoleOutputCP MOCK called...");
if (_getConsoleOutputCPResult)
{
codepage = _expectedOutputCP;
}
return _getConsoleOutputCPResult;
return _expectedOutputCP;
}
bool IsConsolePty() const override
@ -410,22 +338,19 @@ public:
return _isPty;
}
bool DeleteLines(const size_t /*count*/) override
void DeleteLines(const size_t /*count*/) override
{
Log::Comment(L"DeleteLines MOCK called...");
return TRUE;
}
bool InsertLines(const size_t /*count*/) override
void InsertLines(const size_t /*count*/) override
{
Log::Comment(L"InsertLines MOCK called...");
return TRUE;
}
bool MoveToBottom() const override
void MoveToBottom() override
{
Log::Comment(L"MoveToBottom MOCK called...");
return _moveToBottomResult;
}
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override
@ -460,37 +385,31 @@ public:
Log::Comment(L"SetColorAliasIndex MOCK called...");
}
bool PrivateFillRegion(const COORD /*startPosition*/,
const size_t /*fillLength*/,
const wchar_t /*fillChar*/,
const bool /*standardFillAttrs*/) noexcept override
void FillRegion(const COORD /*startPosition*/,
const size_t /*fillLength*/,
const wchar_t /*fillChar*/,
const bool /*standardFillAttrs*/) noexcept override
{
Log::Comment(L"PrivateFillRegion MOCK called...");
return TRUE;
Log::Comment(L"FillRegion MOCK called...");
}
bool PrivateScrollRegion(const SMALL_RECT /*scrollRect*/,
const std::optional<SMALL_RECT> /*clipRect*/,
const COORD /*destinationOrigin*/,
const bool /*standardFillAttrs*/) noexcept override
void ScrollRegion(const SMALL_RECT /*scrollRect*/,
const std::optional<SMALL_RECT> /*clipRect*/,
const COORD /*destinationOrigin*/,
const bool /*standardFillAttrs*/) noexcept override
{
Log::Comment(L"PrivateScrollRegion MOCK called...");
return TRUE;
Log::Comment(L"ScrollRegion MOCK called...");
}
bool PrivateUpdateSoftFont(const gsl::span<const uint16_t> /*bitPattern*/,
const SIZE cellSize,
const size_t /*centeringHint*/) noexcept override
void UpdateSoftFont(const gsl::span<const uint16_t> /*bitPattern*/,
const SIZE cellSize,
const size_t /*centeringHint*/) noexcept override
{
Log::Comment(L"PrivateUpdateSoftFont MOCK called...");
Log::Comment(L"UpdateSoftFont MOCK called...");
Log::Comment(NoThrowString().Format(L"Cell size: %dx%d", cellSize.cx, cellSize.cy));
VERIFY_ARE_EQUAL(_expectedCellSize.cx, cellSize.cx);
VERIFY_ARE_EQUAL(_expectedCellSize.cy, cellSize.cy);
return TRUE;
}
void PrepData()
@ -522,13 +441,13 @@ public:
Log::Comment(L"Resetting mock data state.");
// APIs succeed by default
_setConsoleCursorPositionResult = TRUE;
_setCursorPositionResult = TRUE;
_getConsoleScreenBufferInfoExResult = TRUE;
_privateGetTextAttributesResult = TRUE;
_privateSetTextAttributesResult = TRUE;
_privateWriteConsoleInputWResult = TRUE;
_privateWriteConsoleControlInputResult = TRUE;
_setConsoleWindowInfoResult = TRUE;
_getTextAttributesResult = TRUE;
_setTextAttributesResult = TRUE;
_writeInputResult = TRUE;
_writeControlInputResult = TRUE;
_setWindowInfoResult = TRUE;
_moveToBottomResult = true;
_bufferSize.X = 100;
@ -618,18 +537,14 @@ public:
}
}
bool PrivateAddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) const
void AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) const
{
Log::Comment(L"PrivateAddHyperlink MOCK called...");
return TRUE;
Log::Comment(L"AddHyperlink MOCK called...");
}
bool PrivateEndHyperlink() const
void EndHyperlink() const
{
Log::Comment(L"PrivateEndHyperlink MOCK called...");
return TRUE;
Log::Comment(L"EndHyperlink MOCK called...");
}
void _SetMarginsHelper(SMALL_RECT* rect, SHORT top, SHORT bottom)
@ -668,6 +583,7 @@ public:
SMALL_RECT _expectedConsoleWindow = { 0, 0, 0, 0 };
COORD _cursorPos = { 0, 0 };
SMALL_RECT _expectedScrollRegion = { 0, 0, 0, 0 };
SMALL_RECT _activeScrollRegion = { 0, 0, 0, 0 };
bool _cursorVisible = false;
@ -678,17 +594,17 @@ public:
unsigned int _expectedOutputCP = 0;
bool _isPty = false;
bool _privateShowCursorResult = false;
bool _expectedShowCursor = false;
bool _setCursorVisibilityResult = false;
bool _expectedCursorVisibility = false;
bool _getConsoleScreenBufferInfoExResult = false;
bool _setConsoleCursorPositionResult = false;
bool _privateGetTextAttributesResult = false;
bool _privateSetTextAttributesResult = false;
bool _privateWriteConsoleInputWResult = false;
bool _privateWriteConsoleControlInputResult = false;
bool _setCursorPositionResult = false;
bool _getTextAttributesResult = false;
bool _setTextAttributesResult = false;
bool _writeInputResult = false;
bool _writeControlInputResult = false;
bool _setConsoleWindowInfoResult = false;
bool _setWindowInfoResult = false;
bool _expectedWindowAbsolute = false;
bool _setConsoleScreenBufferInfoExResult = false;
@ -700,15 +616,15 @@ public:
bool _setParserModeResult = false;
StateMachine::Mode _expectedParserMode;
bool _expectedParserModeEnabled = false;
bool _privateAllowCursorBlinkingResult = false;
bool _enableCursorBlinkingResult = false;
bool _enable = false; // for cursor blinking
bool _privateSetScrollingRegionResult = false;
bool _privateGetLineFeedModeResult = false;
bool _privateLineFeedResult = false;
bool _setScrollingRegionResult = false;
bool _getLineFeedModeResult = false;
bool _lineFeedResult = false;
bool _expectedLineFeedWithReturn = false;
bool _privateReverseLineFeedResult = false;
bool _reverseLineFeedResult = false;
bool _setConsoleTitleWResult = false;
bool _setWindowTitleResult = false;
std::wstring_view _expectedWindowTitle{};
bool _setCursorStyleResult = false;
CursorType _expectedCursorStyle;
@ -920,19 +836,19 @@ public:
VERIFY_IS_TRUE((_pDispatch.get()->*(moveFunc))(100));
// error cases
// SetConsoleCursorPosition throws failure. Parameters are otherwise normal.
Log::Comment(L"Test 4: When SetConsoleCursorPosition throws a failure, call fails and cursor doesn't move.");
// SetCursorPosition throws failure. Parameters are otherwise normal.
Log::Comment(L"Test 4: When SetCursorPosition throws a failure, call fails and cursor doesn't move.");
_testGetSet->PrepData(direction);
_testGetSet->_setConsoleCursorPositionResult = FALSE;
_testGetSet->_setCursorPositionResult = FALSE;
VERIFY_IS_FALSE((_pDispatch.get()->*(moveFunc))(0));
VERIFY_THROWS((_pDispatch.get()->*(moveFunc))(0), std::exception);
VERIFY_ARE_EQUAL(_testGetSet->_expectedCursorPos, _testGetSet->_cursorPos);
// GetConsoleScreenBufferInfo throws failure. Parameters are otherwise normal.
Log::Comment(L"Test 5: When GetConsoleScreenBufferInfo throws a failure, call fails and cursor doesn't move.");
_testGetSet->PrepData(CursorX::LEFT, CursorY::TOP);
_testGetSet->_getConsoleScreenBufferInfoExResult = FALSE;
VERIFY_IS_FALSE((_pDispatch.get()->*(moveFunc))(0));
VERIFY_THROWS((_pDispatch.get()->*(moveFunc))(0), std::exception);
VERIFY_ARE_EQUAL(_testGetSet->_expectedCursorPos, _testGetSet->_cursorPos);
}
@ -977,14 +893,14 @@ public:
_testGetSet->_getConsoleScreenBufferInfoExResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->CursorPosition(1, 1));
VERIFY_THROWS(_pDispatch.get()->CursorPosition(1, 1), std::exception);
Log::Comment(L"Test 5: SetCursor API returns false. No move, return false.");
_testGetSet->PrepData(CursorX::LEFT, CursorY::TOP);
_testGetSet->_setConsoleCursorPositionResult = FALSE;
_testGetSet->_setCursorPositionResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->CursorPosition(1, 1));
VERIFY_THROWS(_pDispatch.get()->CursorPosition(1, 1), std::exception);
}
TEST_METHOD(CursorSingleDimensionMoveTest)
@ -1066,16 +982,16 @@ public:
sVal = 1;
VERIFY_IS_FALSE((_pDispatch.get()->*(moveFunc))(sVal));
VERIFY_THROWS((_pDispatch.get()->*(moveFunc))(sVal), std::exception);
Log::Comment(L"Test 5: SetCursor API returns false. No move, return false.");
_testGetSet->PrepData(CursorX::LEFT, CursorY::TOP);
_testGetSet->_setConsoleCursorPositionResult = FALSE;
_testGetSet->_setCursorPositionResult = FALSE;
sVal = 1;
VERIFY_IS_FALSE((_pDispatch.get()->*(moveFunc))(sVal));
VERIFY_THROWS((_pDispatch.get()->*(moveFunc))(sVal), std::exception);
}
TEST_METHOD(CursorSaveRestoreTest)
@ -1134,14 +1050,14 @@ public:
Log::Comment(L"Test 1: Verify successful API call modifies visibility state.");
_testGetSet->PrepData();
_testGetSet->_cursorVisible = fStart;
_testGetSet->_privateShowCursorResult = true;
_testGetSet->_expectedShowCursor = fEnd;
_testGetSet->_setCursorVisibilityResult = true;
_testGetSet->_expectedCursorVisibility = fEnd;
VERIFY_IS_TRUE(_pDispatch.get()->CursorVisibility(fEnd));
Log::Comment(L"Test 3: When we fail to set updated cursor information, the dispatch should fail.");
_testGetSet->PrepData();
_testGetSet->_privateShowCursorResult = false;
VERIFY_IS_FALSE(_pDispatch.get()->CursorVisibility(fEnd));
_testGetSet->_setCursorVisibilityResult = false;
VERIFY_THROWS(_pDispatch.get()->CursorVisibility(fEnd), std::exception);
}
TEST_METHOD(GraphicsBaseTests)
@ -1160,18 +1076,18 @@ public:
Log::Comment(L"Test 2: Gracefully fail when getting attribute data fails.");
_testGetSet->PrepData();
_testGetSet->_privateGetTextAttributesResult = FALSE;
_testGetSet->_getTextAttributesResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_THROWS(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }), std::exception);
Log::Comment(L"Test 3: Gracefully fail when setting attribute data fails.");
_testGetSet->PrepData();
_testGetSet->_privateSetTextAttributesResult = FALSE;
_testGetSet->_setTextAttributesResult = FALSE;
// Need at least one option in order for the call to be able to fail.
rgOptions[0] = (DispatchTypes::GraphicsOptions)0;
cOptions = 1;
VERIFY_IS_FALSE(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }));
VERIFY_THROWS(_pDispatch.get()->SetGraphicsRendition({ rgOptions, cOptions }), std::exception);
}
TEST_METHOD(GraphicsSingleTests)
@ -1815,11 +1731,11 @@ public:
PCWSTR pwszExpectedResponse = L"\x1b[?1;0c";
_testGetSet->ValidateInputEvent(pwszExpectedResponse);
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work.");
_testGetSet->PrepData();
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
_testGetSet->_writeInputResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->DeviceAttributes());
VERIFY_THROWS(_pDispatch.get()->DeviceAttributes(), std::exception);
}
TEST_METHOD(SecondaryDeviceAttributesTests)
@ -1833,11 +1749,11 @@ public:
PCWSTR pwszExpectedResponse = L"\x1b[>0;10;1c";
_testGetSet->ValidateInputEvent(pwszExpectedResponse);
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work.");
_testGetSet->PrepData();
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
_testGetSet->_writeInputResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->SecondaryDeviceAttributes());
VERIFY_THROWS(_pDispatch.get()->SecondaryDeviceAttributes(), std::exception);
}
TEST_METHOD(TertiaryDeviceAttributesTests)
@ -1851,11 +1767,11 @@ public:
PCWSTR pwszExpectedResponse = L"\x1bP!|00000000\x1b\\";
_testGetSet->ValidateInputEvent(pwszExpectedResponse);
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work.");
_testGetSet->PrepData();
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
_testGetSet->_writeInputResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->TertiaryDeviceAttributes());
VERIFY_THROWS(_pDispatch.get()->TertiaryDeviceAttributes(), std::exception);
}
TEST_METHOD(RequestTerminalParametersTests)
@ -1876,10 +1792,10 @@ public:
_testGetSet->PrepData();
VERIFY_IS_FALSE(_pDispatch.get()->RequestTerminalParameters((DispatchTypes::ReportingPermission)2));
Log::Comment(L"Test 4: Verify failure when WriteConsoleInput doesn't work.");
Log::Comment(L"Test 4: Verify failure when WriteInput doesn't work.");
_testGetSet->PrepData();
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
VERIFY_IS_FALSE(_pDispatch.get()->RequestTerminalParameters(DispatchTypes::ReportingPermission::Unsolicited));
_testGetSet->_writeInputResult = FALSE;
VERIFY_THROWS(_pDispatch.get()->RequestTerminalParameters(DispatchTypes::ReportingPermission::Unsolicited), std::exception);
}
TEST_METHOD(RequestSettingsTests)
@ -2058,14 +1974,14 @@ public:
// success cases
// set numeric mode = true
Log::Comment(L"Test 1: enable blinking = true");
_testGetSet->_privateAllowCursorBlinkingResult = TRUE;
_testGetSet->_enableCursorBlinkingResult = TRUE;
_testGetSet->_enable = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableCursorBlinking(true));
// set numeric mode = false
Log::Comment(L"Test 2: enable blinking = false");
_testGetSet->_privateAllowCursorBlinkingResult = TRUE;
_testGetSet->_enableCursorBlinkingResult = TRUE;
_testGetSet->_enable = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableCursorBlinking(false));
@ -2084,8 +2000,8 @@ public:
Log::Comment(L"Test 1: Verify having both values is valid.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 2, 6);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setConsoleCursorPositionResult = true;
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_setCursorPositionResult = true;
_testGetSet->_moveToBottomResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
@ -2093,30 +2009,32 @@ public:
_testGetSet->_SetMarginsHelper(&srTestMargins, 7, 0);
_testGetSet->_expectedScrollRegion.Bottom = _testGetSet->_viewport.Bottom - 1; // We expect the bottom to be the bottom of the viewport, exclusive.
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
Log::Comment(L"Test 3: Verify having only bottom is valid.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 0, 7);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
Log::Comment(L"Test 4: Verify having no values is valid.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 0, 0);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
Log::Comment(L"Test 5: Verify having both values, but bad bounds is invalid.");
Log::Comment(L"Test 5: Verify having both values, but bad bounds has no effect.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 7, 3);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
VERIFY_IS_FALSE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_activeScrollRegion = {};
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
VERIFY_ARE_EQUAL(SMALL_RECT{}, _testGetSet->_activeScrollRegion);
Log::Comment(L"Test 6: Verify setting margins to (0, height) clears them");
// First set,
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_SetMarginsHelper(&srTestMargins, 2, 6);
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
// Then clear
@ -2127,7 +2045,7 @@ public:
Log::Comment(L"Test 7: Verify setting margins to (1, height) clears them");
// First set,
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_SetMarginsHelper(&srTestMargins, 2, 6);
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
// Then clear
@ -2138,7 +2056,7 @@ public:
Log::Comment(L"Test 8: Verify setting margins to (1, 0) clears them");
// First set,
_testGetSet->_privateSetScrollingRegionResult = TRUE;
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_SetMarginsHelper(&srTestMargins, 2, 6);
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
// Then clear
@ -2147,23 +2065,29 @@ public:
_testGetSet->_expectedScrollRegion.Bottom = 0;
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
Log::Comment(L"Test 9: Verify having top and bottom margin the same is invalid.");
Log::Comment(L"Test 9: Verify having top and bottom margin the same has no effect.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 4, 4);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
VERIFY_IS_FALSE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_activeScrollRegion = {};
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
VERIFY_ARE_EQUAL(SMALL_RECT{}, _testGetSet->_activeScrollRegion);
Log::Comment(L"Test 10: Verify having top margin out of bounds is invalid.");
Log::Comment(L"Test 10: Verify having top margin out of bounds has no effect.");
_testGetSet->_SetMarginsHelper(&srTestMargins, sScreenHeight + 1, sScreenHeight + 10);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
VERIFY_IS_FALSE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_activeScrollRegion = {};
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
VERIFY_ARE_EQUAL(SMALL_RECT{}, _testGetSet->_activeScrollRegion);
Log::Comment(L"Test 11: Verify having bottom margin out of bounds is invalid.");
Log::Comment(L"Test 11: Verify having bottom margin out of bounds has no effect.");
_testGetSet->_SetMarginsHelper(&srTestMargins, 1, sScreenHeight + 1);
_testGetSet->_privateSetScrollingRegionResult = TRUE;
VERIFY_IS_FALSE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
_testGetSet->_setScrollingRegionResult = TRUE;
_testGetSet->_activeScrollRegion = {};
VERIFY_IS_TRUE(_pDispatch.get()->SetTopBottomScrollingMargins(srTestMargins.Top, srTestMargins.Bottom));
VERIFY_ARE_EQUAL(SMALL_RECT{}, _testGetSet->_activeScrollRegion);
}
TEST_METHOD(LineFeedTest)
@ -2171,7 +2095,7 @@ public:
Log::Comment(L"Starting test...");
// All test cases need the LineFeed call to succeed.
_testGetSet->_privateLineFeedResult = TRUE;
_testGetSet->_lineFeedResult = TRUE;
Log::Comment(L"Test 1: Line feed without carriage return.");
_testGetSet->_expectedLineFeedWithReturn = false;
@ -2182,12 +2106,12 @@ public:
VERIFY_IS_TRUE(_pDispatch.get()->LineFeed(DispatchTypes::LineFeedType::WithReturn));
Log::Comment(L"Test 3: Line feed depends on mode, and mode reset.");
_testGetSet->_privateGetLineFeedModeResult = false;
_testGetSet->_getLineFeedModeResult = false;
_testGetSet->_expectedLineFeedWithReturn = false;
VERIFY_IS_TRUE(_pDispatch.get()->LineFeed(DispatchTypes::LineFeedType::DependsOnMode));
Log::Comment(L"Test 4: Line feed depends on mode, and mode set.");
_testGetSet->_privateGetLineFeedModeResult = true;
_testGetSet->_getLineFeedModeResult = true;
_testGetSet->_expectedLineFeedWithReturn = true;
VERIFY_IS_TRUE(_pDispatch.get()->LineFeed(DispatchTypes::LineFeedType::DependsOnMode));
}
@ -2197,13 +2121,13 @@ public:
Log::Comment(L"Starting test...");
Log::Comment(L"Test 1: set title to be non-null");
_testGetSet->_setConsoleTitleWResult = TRUE;
_testGetSet->_setWindowTitleResult = TRUE;
_testGetSet->_expectedWindowTitle = L"Foo bar";
VERIFY_IS_TRUE(_pDispatch.get()->SetWindowTitle(_testGetSet->_expectedWindowTitle));
Log::Comment(L"Test 2: set title to be null");
_testGetSet->_setConsoleTitleWResult = FALSE;
_testGetSet->_setWindowTitleResult = FALSE;
_testGetSet->_expectedWindowTitle = {};
VERIFY_IS_TRUE(_pDispatch.get()->SetWindowTitle({}));

Просмотреть файл

@ -276,19 +276,12 @@ bool InputStateMachineEngine::ActionPassThroughString(const std::wstring_view st
// similar to TerminalInput::_SendInputSequence
if (!string.empty())
{
try
std::deque<std::unique_ptr<IInputEvent>> inputEvents;
for (const auto& wch : string)
{
std::deque<std::unique_ptr<IInputEvent>> inputEvents;
for (const auto& wch : string)
{
inputEvents.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, wch, 0));
}
return _pDispatch->WriteInput(inputEvents);
}
catch (...)
{
LOG_HR(wil::ResultFromCaughtException());
inputEvents.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, wch, 0));
}
return _pDispatch->WriteInput(inputEvents);
}
}
return ActionPrintString(string);

Просмотреть файл

@ -893,8 +893,7 @@ bool OutputStateMachineEngine::_GetOscTitle(const std::wstring_view string,
// - True if at least one table index and color was parsed successfully. False otherwise.
bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view string,
std::vector<size_t>& tableIndexes,
std::vector<DWORD>& rgbs) const noexcept
try
std::vector<DWORD>& rgbs) const
{
const auto parts = Utils::SplitString(string, L';');
if (parts.size() < 2)
@ -922,7 +921,6 @@ try
return tableIndexes.size() > 0 && rgbs.size() > 0;
}
CATCH_LOG_RETURN_FALSE()
#pragma warning(push)
#pragma warning(disable : 26445) // Suppress lifetime check for a reference to gsl::span or std::string_view
@ -989,8 +987,7 @@ bool OutputStateMachineEngine::_ParseHyperlink(const std::wstring_view string,
// Return Value:
// - True if at least one color was parsed successfully. False otherwise.
bool OutputStateMachineEngine::_GetOscSetColor(const std::wstring_view string,
std::vector<DWORD>& rgbs) const noexcept
try
std::vector<DWORD>& rgbs) const
{
const auto parts = Utils::SplitString(string, L';');
if (parts.size() < 1)
@ -1016,7 +1013,6 @@ try
return rgbs.size() > 0;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Sets us up to have another terminal acting as the tty instead of conhost.

Просмотреть файл

@ -192,10 +192,10 @@ namespace Microsoft::Console::VirtualTerminal
bool _GetOscSetColorTable(const std::wstring_view string,
std::vector<size_t>& tableIndexes,
std::vector<DWORD>& rgbs) const noexcept;
std::vector<DWORD>& rgbs) const;
bool _GetOscSetColor(const std::wstring_view string,
std::vector<DWORD>& rgbs) const noexcept;
std::vector<DWORD>& rgbs) const;
bool _GetOscSetClipboard(const std::wstring_view string,
std::wstring& content,

Просмотреть файл

@ -385,13 +385,12 @@ static constexpr bool _isActionableFromGround(const wchar_t wch) noexcept
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionExecute(const wchar_t wch)
void StateMachine::_ActionExecute(const wchar_t wch) noexcept
{
_trace.TraceOnExecute(wch);
const bool success = _engine->ActionExecute(wch);
// Trace the result.
_trace.DispatchSequenceTrace(success);
_trace.DispatchSequenceTrace(_SafeExecute([=]() {
return _engine->ActionExecute(wch);
}));
}
// Routine Description:
@ -402,14 +401,12 @@ void StateMachine::_ActionExecute(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionExecuteFromEscape(const wchar_t wch)
void StateMachine::_ActionExecuteFromEscape(const wchar_t wch) noexcept
{
_trace.TraceOnExecuteFromEscape(wch);
const bool success = _engine->ActionExecuteFromEscape(wch);
// Trace the result.
_trace.DispatchSequenceTrace(success);
_trace.DispatchSequenceTrace(_SafeExecute([=]() {
return _engine->ActionExecuteFromEscape(wch);
}));
}
// Routine Description:
@ -418,14 +415,26 @@ void StateMachine::_ActionExecuteFromEscape(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionPrint(const wchar_t wch)
void StateMachine::_ActionPrint(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"Print");
_trace.DispatchSequenceTrace(_SafeExecute([=]() {
return _engine->ActionPrint(wch);
}));
}
const bool success = _engine->ActionPrint(wch);
// Trace the result.
_trace.DispatchSequenceTrace(success);
// Routine Description:
// - Triggers the PrintString action to indicate that the listener should render the characters given.
// Arguments:
// - string - Characters to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionPrintString(const std::wstring_view string)
{
_SafeExecute([=]() {
return _engine->ActionPrintString(string);
});
_trace.DispatchPrintRunTrace(string);
}
// Routine Description:
@ -435,20 +444,12 @@ void StateMachine::_ActionPrint(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionEscDispatch(const wchar_t wch)
void StateMachine::_ActionEscDispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"EscDispatch");
const bool success = _engine->ActionEscDispatch(_identifier.Finalize(wch));
// Trace the result.
_trace.DispatchSequenceTrace(success);
if (!success)
{
// Suppress it and log telemetry on failed cases
TermTelemetry::Instance().LogFailed(wch);
}
_trace.DispatchSequenceTrace(_SafeExecuteWithLog(wch, [=]() {
return _engine->ActionEscDispatch(_identifier.Finalize(wch));
}));
}
// Routine Description:
@ -458,21 +459,12 @@ void StateMachine::_ActionEscDispatch(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionVt52EscDispatch(const wchar_t wch)
void StateMachine::_ActionVt52EscDispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"Vt52EscDispatch");
const bool success = _engine->ActionVt52EscDispatch(_identifier.Finalize(wch),
{ _parameters.data(), _parameters.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
if (!success)
{
// Suppress it and log telemetry on failed cases
TermTelemetry::Instance().LogFailed(wch);
}
_trace.DispatchSequenceTrace(_SafeExecuteWithLog(wch, [=]() {
return _engine->ActionVt52EscDispatch(_identifier.Finalize(wch), { _parameters.data(), _parameters.size() });
}));
}
// Routine Description:
@ -482,21 +474,12 @@ void StateMachine::_ActionVt52EscDispatch(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionCsiDispatch(const wchar_t wch)
void StateMachine::_ActionCsiDispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"CsiDispatch");
const bool success = _engine->ActionCsiDispatch(_identifier.Finalize(wch),
{ _parameters.data(), _parameters.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
if (!success)
{
// Suppress it and log telemetry on failed cases
TermTelemetry::Instance().LogFailed(wch);
}
_trace.DispatchSequenceTrace(_SafeExecuteWithLog(wch, [=]() {
return _engine->ActionCsiDispatch(_identifier.Finalize(wch), { _parameters.data(), _parameters.size() });
}));
}
// Routine Description:
@ -649,20 +632,12 @@ void StateMachine::_ActionOscPut(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionOscDispatch(const wchar_t wch)
void StateMachine::_ActionOscDispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"OscDispatch");
const bool success = _engine->ActionOscDispatch(wch, _oscParameter, _oscString);
// Trace the result.
_trace.DispatchSequenceTrace(success);
if (!success)
{
// Suppress it and log telemetry on failed cases
TermTelemetry::Instance().LogFailed(wch);
}
_trace.DispatchSequenceTrace(_SafeExecuteWithLog(wch, [=]() {
return _engine->ActionOscDispatch(wch, _oscParameter, _oscString);
}));
}
// Routine Description:
@ -672,20 +647,12 @@ void StateMachine::_ActionOscDispatch(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionSs3Dispatch(const wchar_t wch)
void StateMachine::_ActionSs3Dispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"Ss3Dispatch");
const bool success = _engine->ActionSs3Dispatch(wch, { _parameters.data(), _parameters.size() });
// Trace the result.
_trace.DispatchSequenceTrace(success);
if (!success)
{
// Suppress it and log telemetry on failed cases
TermTelemetry::Instance().LogFailed(wch);
}
_trace.DispatchSequenceTrace(_SafeExecuteWithLog(wch, [=]() {
return _engine->ActionSs3Dispatch(wch, { _parameters.data(), _parameters.size() });
}));
}
// Routine Description:
@ -695,15 +662,15 @@ void StateMachine::_ActionSs3Dispatch(const wchar_t wch)
// - wch - Character to dispatch.
// Return Value:
// - <none>
void StateMachine::_ActionDcsDispatch(const wchar_t wch)
void StateMachine::_ActionDcsDispatch(const wchar_t wch) noexcept
{
_trace.TraceOnAction(L"DcsDispatch");
_dcsStringHandler = _engine->ActionDcsDispatch(_identifier.Finalize(wch),
{ _parameters.data(), _parameters.size() });
// If the returned handler is null, the sequence is not supported.
const bool success = _dcsStringHandler != nullptr;
const bool success = _SafeExecuteWithLog(wch, [=]() {
_dcsStringHandler = _engine->ActionDcsDispatch(_identifier.Finalize(wch), { _parameters.data(), _parameters.size() });
// If the returned handler is null, the sequence is not supported.
return _dcsStringHandler != nullptr;
});
// Trace the result.
_trace.DispatchSequenceTrace(success);
@ -715,9 +682,8 @@ void StateMachine::_ActionDcsDispatch(const wchar_t wch)
}
else
{
// Otherwise ignore remaining chars and log telemetry on failed cases
// Otherwise ignore remaining chars.
_EnterDcsIgnore();
TermTelemetry::Instance().LogFailed(wch);
}
}
@ -1012,7 +978,7 @@ void StateMachine::_EnterSosPmApcString() noexcept
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventGround(const wchar_t wch)
void StateMachine::_EventGround(const wchar_t wch) noexcept
{
_trace.TraceOnEvent(L"Ground");
if (_isC0Code(wch) || _isDelete(wch))
@ -1127,7 +1093,7 @@ void StateMachine::_EventEscape(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventEscapeIntermediate(const wchar_t wch)
void StateMachine::_EventEscapeIntermediate(const wchar_t wch) noexcept
{
_trace.TraceOnEvent(L"EscapeIntermediate");
if (_isC0Code(wch))
@ -1221,7 +1187,7 @@ void StateMachine::_EventCsiEntry(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventCsiIntermediate(const wchar_t wch)
void StateMachine::_EventCsiIntermediate(const wchar_t wch) noexcept
{
_trace.TraceOnEvent(L"CsiIntermediate");
if (_isC0Code(wch))
@ -1259,7 +1225,7 @@ void StateMachine::_EventCsiIntermediate(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventCsiIgnore(const wchar_t wch)
void StateMachine::_EventCsiIgnore(const wchar_t wch) noexcept
{
_trace.TraceOnEvent(L"CsiIgnore");
if (_isC0Code(wch))
@ -1608,7 +1574,7 @@ void StateMachine::_EventDcsIgnore() noexcept
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventDcsIntermediate(const wchar_t wch)
void StateMachine::_EventDcsIntermediate(const wchar_t wch) noexcept
{
_trace.TraceOnEvent(L"DcsIntermediate");
if (_isC0Code(wch))
@ -1820,7 +1786,7 @@ void StateMachine::ProcessCharacter(const wchar_t wch)
// - <none>
// Return Value:
// - true if the engine successfully handled the string.
bool StateMachine::FlushToTerminal()
bool StateMachine::FlushToTerminal() noexcept
{
bool success{ true };
@ -1829,7 +1795,9 @@ bool StateMachine::FlushToTerminal()
// Flush the partial sequence to the terminal before we flush the rest of it.
// We always want to clear the sequence, even if we failed, so we don't accumulate bad state
// and dump it out elsewhere later.
success = _engine->ActionPassThroughString(*_cachedSequence);
success = _SafeExecute([=]() {
return _engine->ActionPassThroughString(*_cachedSequence);
});
_cachedSequence.reset();
}
@ -1839,7 +1807,9 @@ bool StateMachine::FlushToTerminal()
// that pwchCurr was processed.
// However, if we're here, then the processing of pwchChar triggered the
// engine to request the entire sequence get passed through, including pwchCurr.
success = _engine->ActionPassThroughString(_CurrentRun());
success = _SafeExecute([=]() {
return _engine->ActionPassThroughString(_CurrentRun());
});
}
return success;
@ -1892,10 +1862,7 @@ void StateMachine::ProcessString(const std::wstring_view string)
// trim it off here since we just determined it's actionable
// and only pass through everything before it.
_runSize -= 1;
const auto allLeadingUpTo = _CurrentRun();
_engine->ActionPrintString(allLeadingUpTo); // ... print all the chars leading up to it as part of the run...
_trace.DispatchPrintRunTrace(allLeadingUpTo);
_ActionPrintString(_CurrentRun()); // ... print all the chars leading up to it as part of the run...
}
_processingIndividually = true; // begin processing future characters individually...
@ -1927,8 +1894,7 @@ void StateMachine::ProcessString(const std::wstring_view string)
if (!_processingIndividually && !run.empty())
{
// print the rest of the characters in the string
_engine->ActionPrintString(run);
_trace.DispatchPrintRunTrace(run);
_ActionPrintString(run);
}
else if (_processingIndividually)
{
@ -2044,3 +2010,26 @@ void StateMachine::_AccumulateTo(const wchar_t wch, size_t& value) noexcept
value = MAX_PARAMETER_VALUE;
}
}
template<typename TLambda>
bool StateMachine::_SafeExecute(TLambda&& lambda) noexcept
try
{
return lambda();
}
catch (...)
{
LOG_HR(wil::ResultFromCaughtException());
return false;
}
template<typename TLambda>
bool StateMachine::_SafeExecuteWithLog(const wchar_t wch, TLambda&& lambda) noexcept
{
const bool success = _SafeExecute(std::forward<TLambda>(lambda));
if (!success)
{
TermTelemetry::Instance().LogFailed(wch);
}
return success;
}

Просмотреть файл

@ -61,25 +61,26 @@ namespace Microsoft::Console::VirtualTerminal
void ResetState() noexcept;
bool FlushToTerminal();
bool FlushToTerminal() noexcept;
const IStateMachineEngine& Engine() const noexcept;
IStateMachineEngine& Engine() noexcept;
private:
void _ActionExecute(const wchar_t wch);
void _ActionExecuteFromEscape(const wchar_t wch);
void _ActionPrint(const wchar_t wch);
void _ActionEscDispatch(const wchar_t wch);
void _ActionVt52EscDispatch(const wchar_t wch);
void _ActionExecute(const wchar_t wch) noexcept;
void _ActionExecuteFromEscape(const wchar_t wch) noexcept;
void _ActionPrint(const wchar_t wch) noexcept;
void _ActionPrintString(const std::wstring_view string);
void _ActionEscDispatch(const wchar_t wch) noexcept;
void _ActionVt52EscDispatch(const wchar_t wch) noexcept;
void _ActionCollect(const wchar_t wch) noexcept;
void _ActionParam(const wchar_t wch);
void _ActionCsiDispatch(const wchar_t wch);
void _ActionCsiDispatch(const wchar_t wch) noexcept;
void _ActionOscParam(const wchar_t wch) noexcept;
void _ActionOscPut(const wchar_t wch);
void _ActionOscDispatch(const wchar_t wch);
void _ActionSs3Dispatch(const wchar_t wch);
void _ActionDcsDispatch(const wchar_t wch);
void _ActionOscDispatch(const wchar_t wch) noexcept;
void _ActionSs3Dispatch(const wchar_t wch) noexcept;
void _ActionDcsDispatch(const wchar_t wch) noexcept;
void _ActionClear();
void _ActionIgnore() noexcept;
@ -105,12 +106,12 @@ namespace Microsoft::Console::VirtualTerminal
void _EnterDcsPassThrough() noexcept;
void _EnterSosPmApcString() noexcept;
void _EventGround(const wchar_t wch);
void _EventGround(const wchar_t wch) noexcept;
void _EventEscape(const wchar_t wch);
void _EventEscapeIntermediate(const wchar_t wch);
void _EventEscapeIntermediate(const wchar_t wch) noexcept;
void _EventCsiEntry(const wchar_t wch);
void _EventCsiIntermediate(const wchar_t wch);
void _EventCsiIgnore(const wchar_t wch);
void _EventCsiIntermediate(const wchar_t wch) noexcept;
void _EventCsiIgnore(const wchar_t wch) noexcept;
void _EventCsiParam(const wchar_t wch);
void _EventOscParam(const wchar_t wch) noexcept;
void _EventOscString(const wchar_t wch);
@ -120,13 +121,18 @@ namespace Microsoft::Console::VirtualTerminal
void _EventVt52Param(const wchar_t wch);
void _EventDcsEntry(const wchar_t wch);
void _EventDcsIgnore() noexcept;
void _EventDcsIntermediate(const wchar_t wch);
void _EventDcsIntermediate(const wchar_t wch) noexcept;
void _EventDcsParam(const wchar_t wch);
void _EventDcsPassThrough(const wchar_t wch);
void _EventSosPmApcString(const wchar_t wch) noexcept;
void _AccumulateTo(const wchar_t wch, size_t& value) noexcept;
template<typename TLambda>
bool _SafeExecute(TLambda&& lambda) noexcept;
template<typename TLambda>
bool _SafeExecuteWithLog(const wchar_t wch, TLambda&& lambda) noexcept;
enum class VTStates
{
Ground,