mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-19 18:11:39 -05:00
Previously this project used a great variety of types to present text buffer coordinates: `short`, `unsigned short`, `int`, `unsigned int`, `size_t`, `ptrdiff_t`, `COORD`/`SMALL_RECT` (aka `short`), and more. This massive commit migrates almost all use of those types over to the centralized types `til::point`/`size`/`rect`/`inclusive_rect` and their underlying type `til::CoordType` (aka `int32_t`). Due to the size of the changeset and statistics I expect it to contain bugs. The biggest risk I see is that some code potentially, maybe implicitly, expected arithmetic to be mod 2^16 and that this code now allows it to be mod 2^32. Any narrowing into `short` later on would then throw exceptions. ## PR Checklist * [x] Closes #4015 * [x] I work here * [x] Tests added/passed ## Validation Steps Performed Casual usage of OpenConsole and Windows Terminal. ✅
329 lines
9.2 KiB
C++
329 lines
9.2 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "pch.h"
|
|
#include "Terminal.hpp"
|
|
#include "../src/inc/unicode.hpp"
|
|
|
|
using namespace Microsoft::Terminal::Core;
|
|
using namespace Microsoft::Console::Render;
|
|
using namespace Microsoft::Console::Types;
|
|
using namespace Microsoft::Console::VirtualTerminal;
|
|
|
|
// Print puts the text in the buffer and moves the cursor
|
|
void Terminal::PrintString(const std::wstring_view string)
|
|
{
|
|
_WriteBuffer(string);
|
|
}
|
|
|
|
void Terminal::ReturnResponse(const std::wstring_view response)
|
|
{
|
|
if (_pfnWriteInput)
|
|
{
|
|
_pfnWriteInput(response);
|
|
}
|
|
}
|
|
|
|
Microsoft::Console::VirtualTerminal::StateMachine& Terminal::GetStateMachine()
|
|
{
|
|
return *_stateMachine;
|
|
}
|
|
|
|
TextBuffer& Terminal::GetTextBuffer()
|
|
{
|
|
return _activeBuffer();
|
|
}
|
|
|
|
til::rect Terminal::GetViewport() const
|
|
{
|
|
return til::rect{ _GetMutableViewport().ToInclusive() };
|
|
}
|
|
|
|
void Terminal::SetViewportPosition(const til::point position)
|
|
{
|
|
// The viewport is fixed at 0,0 for the alt buffer, so this is a no-op.
|
|
if (!_inAltBuffer())
|
|
{
|
|
const auto dimensions = _GetMutableViewport().Dimensions();
|
|
_mutableViewport = Viewport::FromDimensions(position, dimensions);
|
|
Terminal::_NotifyScrollEvent();
|
|
}
|
|
}
|
|
|
|
void Terminal::SetTextAttributes(const TextAttribute& attrs)
|
|
{
|
|
_activeBuffer().SetCurrentAttributes(attrs);
|
|
}
|
|
|
|
void Terminal::SetAutoWrapMode(const bool /*wrapAtEOL*/)
|
|
{
|
|
// TODO: This will be needed to support DECAWM.
|
|
}
|
|
|
|
void Terminal::SetScrollingRegion(const til::inclusive_rect& /*scrollMargins*/)
|
|
{
|
|
// TODO: This will be needed to fully support DECSTBM.
|
|
}
|
|
|
|
void Terminal::WarningBell()
|
|
{
|
|
_pfnWarningBell();
|
|
}
|
|
|
|
bool Terminal::GetLineFeedMode() const
|
|
{
|
|
// TODO: This will be needed to support LNM.
|
|
return false;
|
|
}
|
|
|
|
void Terminal::LineFeed(const bool withReturn)
|
|
{
|
|
auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
|
|
|
// since we explicitly just moved down a row, clear the wrap status on the
|
|
// row we just came from
|
|
_activeBuffer().GetRowByOffset(cursorPos.Y).SetWrapForced(false);
|
|
|
|
cursorPos.Y++;
|
|
if (withReturn)
|
|
{
|
|
cursorPos.X = 0;
|
|
}
|
|
_AdjustCursorPosition(cursorPos);
|
|
}
|
|
|
|
void Terminal::SetWindowTitle(const std::wstring_view title)
|
|
{
|
|
if (!_suppressApplicationTitle)
|
|
{
|
|
_title.emplace(title);
|
|
_pfnTitleChanged(_title.value());
|
|
}
|
|
}
|
|
|
|
CursorType Terminal::GetUserDefaultCursorStyle() const
|
|
{
|
|
return _defaultCursorShape;
|
|
}
|
|
|
|
bool Terminal::ResizeWindow(const til::CoordType /*width*/, const til::CoordType /*height*/)
|
|
{
|
|
// TODO: This will be needed to support various resizing sequences. See also GH#1860.
|
|
return false;
|
|
}
|
|
|
|
void Terminal::SetConsoleOutputCP(const unsigned int /*codepage*/)
|
|
{
|
|
// TODO: This will be needed to support 8-bit charsets and DOCS sequences.
|
|
}
|
|
|
|
unsigned int Terminal::GetConsoleOutputCP() const
|
|
{
|
|
// TODO: See SetConsoleOutputCP above.
|
|
return CP_UTF8;
|
|
}
|
|
|
|
void Terminal::EnableXtermBracketedPasteMode(const bool enabled)
|
|
{
|
|
_bracketedPasteMode = enabled;
|
|
}
|
|
|
|
void Terminal::CopyToClipboard(std::wstring_view content)
|
|
{
|
|
_pfnCopyToClipboard(content);
|
|
}
|
|
|
|
// Method Description:
|
|
// - Updates the taskbar progress indicator
|
|
// Arguments:
|
|
// - state: indicates the progress state
|
|
// - progress: indicates the progress value
|
|
// Return Value:
|
|
// - <none>
|
|
void Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress)
|
|
{
|
|
_taskbarState = static_cast<size_t>(state);
|
|
|
|
switch (state)
|
|
{
|
|
case DispatchTypes::TaskbarState::Clear:
|
|
// Always set progress to 0 in this case
|
|
_taskbarProgress = 0;
|
|
break;
|
|
case DispatchTypes::TaskbarState::Set:
|
|
// Always set progress to the value given in this case
|
|
_taskbarProgress = progress;
|
|
break;
|
|
case DispatchTypes::TaskbarState::Indeterminate:
|
|
// Leave the progress value unchanged in this case
|
|
break;
|
|
case DispatchTypes::TaskbarState::Error:
|
|
case DispatchTypes::TaskbarState::Paused:
|
|
// In these 2 cases, if the given progress value is 0, then
|
|
// leave the progress value unchanged, unless the current progress
|
|
// value is 0, in which case set it to a 'minimum' value (10 in our case);
|
|
// if the given progress value is greater than 0, then set the progress value
|
|
if (progress == 0)
|
|
{
|
|
if (_taskbarProgress == 0)
|
|
{
|
|
_taskbarProgress = TaskbarMinProgress;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_taskbarProgress = progress;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (_pfnTaskbarProgressChanged)
|
|
{
|
|
_pfnTaskbarProgressChanged();
|
|
}
|
|
}
|
|
|
|
void Terminal::SetWorkingDirectory(std::wstring_view uri)
|
|
{
|
|
_workingDirectory = uri;
|
|
}
|
|
|
|
void Terminal::PlayMidiNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration)
|
|
{
|
|
_pfnPlayMidiNote(noteNumber, velocity, duration);
|
|
}
|
|
|
|
void Terminal::UseAlternateScreenBuffer()
|
|
{
|
|
// the new alt buffer is exactly the size of the viewport.
|
|
_altBufferSize = _mutableViewport.Dimensions();
|
|
|
|
const auto cursorSize = _mainBuffer->GetCursor().GetSize();
|
|
|
|
ClearSelection();
|
|
_mainBuffer->ClearPatternRecognizers();
|
|
|
|
// Create a new alt buffer
|
|
_altBuffer = std::make_unique<TextBuffer>(_altBufferSize,
|
|
TextAttribute{},
|
|
cursorSize,
|
|
true,
|
|
_mainBuffer->GetRenderer());
|
|
_mainBuffer->SetAsActiveBuffer(false);
|
|
|
|
// Copy our cursor state to the new buffer's cursor
|
|
{
|
|
// Update the alt buffer's cursor style, visibility, and position to match our own.
|
|
auto& myCursor = _mainBuffer->GetCursor();
|
|
auto& tgtCursor = _altBuffer->GetCursor();
|
|
tgtCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
|
|
tgtCursor.SetIsVisible(myCursor.IsVisible());
|
|
tgtCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
|
|
|
// The new position should match the viewport-relative position of the main buffer.
|
|
auto tgtCursorPos = myCursor.GetPosition();
|
|
tgtCursorPos.Y -= _mutableViewport.Top();
|
|
tgtCursor.SetPosition(tgtCursorPos);
|
|
}
|
|
|
|
// update all the hyperlinks on the screen
|
|
_updateUrlDetection();
|
|
|
|
// GH#3321: Make sure we let the TerminalInput know that we switched
|
|
// buffers. This might affect how we interpret certain mouse events.
|
|
_terminalInput->UseAlternateScreenBuffer();
|
|
|
|
// Update scrollbars
|
|
_NotifyScrollEvent();
|
|
|
|
// redraw the screen
|
|
try
|
|
{
|
|
_activeBuffer().TriggerRedrawAll();
|
|
}
|
|
CATCH_LOG();
|
|
}
|
|
void Terminal::UseMainScreenBuffer()
|
|
{
|
|
// Short-circuit: do nothing.
|
|
if (!_inAltBuffer())
|
|
{
|
|
return;
|
|
}
|
|
|
|
ClearSelection();
|
|
|
|
// Copy our cursor state back to the main buffer's cursor
|
|
{
|
|
// Update the alt buffer's cursor style, visibility, and position to match our own.
|
|
auto& myCursor = _altBuffer->GetCursor();
|
|
auto& tgtCursor = _mainBuffer->GetCursor();
|
|
tgtCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
|
|
tgtCursor.SetIsVisible(myCursor.IsVisible());
|
|
tgtCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
|
|
|
// The new position should match the viewport-relative position of the main buffer.
|
|
// This is the equal and opposite effect of what we did in UseAlternateScreenBuffer
|
|
auto tgtCursorPos = myCursor.GetPosition();
|
|
tgtCursorPos.Y += _mutableViewport.Top();
|
|
tgtCursor.SetPosition(tgtCursorPos);
|
|
}
|
|
|
|
_mainBuffer->SetAsActiveBuffer(true);
|
|
// destroy the alt buffer
|
|
_altBuffer = nullptr;
|
|
|
|
if (_deferredResize.has_value())
|
|
{
|
|
LOG_IF_FAILED(UserResize(_deferredResize.value()));
|
|
_deferredResize = std::nullopt;
|
|
}
|
|
|
|
// update all the hyperlinks on the screen
|
|
_mainBuffer->ClearPatternRecognizers();
|
|
_updateUrlDetection();
|
|
|
|
// GH#3321: Make sure we let the TerminalInput know that we switched
|
|
// buffers. This might affect how we interpret certain mouse events.
|
|
_terminalInput->UseMainScreenBuffer();
|
|
|
|
// Update scrollbars
|
|
_NotifyScrollEvent();
|
|
|
|
// redraw the screen
|
|
try
|
|
{
|
|
_activeBuffer().TriggerRedrawAll();
|
|
}
|
|
CATCH_LOG();
|
|
}
|
|
|
|
// Method Description:
|
|
// - Reacts to a client asking us to show or hide the window.
|
|
// Arguments:
|
|
// - showOrHide - True for show. False for hide.
|
|
// Return Value:
|
|
// - <none>
|
|
void Terminal::ShowWindow(bool showOrHide)
|
|
{
|
|
if (_pfnShowWindowChanged)
|
|
{
|
|
_pfnShowWindowChanged(showOrHide);
|
|
}
|
|
}
|
|
|
|
bool Terminal::IsConsolePty() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool Terminal::IsVtInputEnabled() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void Terminal::NotifyAccessibilityChange(const til::rect& /*changedRect*/)
|
|
{
|
|
// This is only needed in conhost. Terminal handles accessibility in another way.
|
|
}
|