Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,7 @@ UINTs
uld
uldash
uldb
ULONGLONG
ulwave
Unadvise
unattend
Expand Down
266 changes: 92 additions & 174 deletions src/buffer/out/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,214 +13,157 @@
// - ulSize - The height of the cursor within this buffer
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_parentBuffer{ parentBuffer },
_fIsVisible(true),
_fIsOn(true),
_fIsDouble(false),
_fBlinkingAllowed(true),
_fDelay(false),
_fIsConversionArea(false),
_fDelayedEolWrap(false),
_fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false),
_ulSize(ulSize),
_cursorType(CursorType::Legacy)
_ulSize(ulSize)
{
}

Cursor::~Cursor() = default;

til::point Cursor::GetPosition() const noexcept
{
return _cPosition;
}

bool Cursor::IsVisible() const noexcept
uint64_t Cursor::GetLastMutationId() const noexcept
{
return _fIsVisible;
return _mutationId;
}

bool Cursor::IsOn() const noexcept
bool Cursor::IsVisible() const noexcept
{
return _fIsOn;
return _isVisible;
}

bool Cursor::IsBlinkingAllowed() const noexcept
bool Cursor::IsBlinking() const noexcept
{
return _fBlinkingAllowed;
return _isBlinking;
}

bool Cursor::IsDouble() const noexcept
{
return _fIsDouble;
}

bool Cursor::IsConversionArea() const noexcept
{
return _fIsConversionArea;
}

bool Cursor::GetDelay() const noexcept
{
return _fDelay;
}

ULONG Cursor::GetSize() const noexcept
{
return _ulSize;
}

void Cursor::SetIsVisible(const bool fIsVisible) noexcept
{
_fIsVisible = fIsVisible;
_RedrawCursor();
}

void Cursor::SetIsOn(const bool fIsOn) noexcept
void Cursor::SetIsVisible(bool enable)
{
_fIsOn = fIsOn;
_RedrawCursorAlways();
if (_isVisible != enable)
{
_isVisible = enable;
_redrawIfVisible();
}
}

void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed) noexcept
void Cursor::SetIsBlinking(bool enable)
{
_fBlinkingAllowed = fBlinkingAllowed;
// 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)
_fIsOn = true;
_RedrawCursorAlways();
if (_isBlinking != enable)
{
_isBlinking = enable;
_redrawIfVisible();
}
}

void Cursor::SetIsDouble(const bool fIsDouble) noexcept
{
_fIsDouble = fIsDouble;
_RedrawCursor();
}

void Cursor::SetIsConversionArea(const bool fIsConversionArea) noexcept
{
// Functionally the same as "Hide cursor"
// Never called with TRUE, it's only used in the creation of a
// ConversionAreaInfo, and never changed after that.
_fIsConversionArea = fIsConversionArea;
_RedrawCursorAlways();
}

void Cursor::SetDelay(const bool fDelay) noexcept
{
_fDelay = fDelay;
if (_fIsDouble != fIsDouble)
{
_fIsDouble = fIsDouble;
_redrawIfVisible();
}
}

void Cursor::SetSize(const ULONG ulSize) noexcept
{
_ulSize = ulSize;
_RedrawCursor();
if (_ulSize != ulSize)
{
_ulSize = ulSize;
_redrawIfVisible();
}
}

void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
{
_ulSize = ulSize;
_cursorType = type;

_RedrawCursor();
}

// Routine Description:
// - Sends a redraw message to the renderer only if the cursor is currently on.
// - NOTE: For use with most methods in this class.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Cursor::_RedrawCursor() noexcept
{
// Only trigger the redraw if we're on.
// Don't draw the cursor if this was triggered from a conversion area.
// (Conversion areas have cursors to mark the insertion point internally, but the user's actual cursor is the one on the primary screen buffer.)
if (IsOn() && !IsConversionArea())
if (_ulSize != ulSize || _cursorType != type)
{
if (_fDeferCursorRedraw)
{
_fHaveDeferredCursorRedraw = true;
}
else
{
_RedrawCursorAlways();
}
_ulSize = ulSize;
_cursorType = type;
_redrawIfVisible();
}
}

// Routine Description:
// - Sends a redraw message to the renderer no matter what.
// - NOTE: For use with the method that turns the cursor on and off to force a refresh
// and clear the ON cursor from the screen. Not for use with other methods.
// They should use the other method so refreshes are suppressed while the cursor is off.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Cursor::_RedrawCursorAlways() noexcept
{
_parentBuffer.NotifyPaintFrame();
}

void Cursor::SetPosition(const til::point cPosition) noexcept
{
_RedrawCursor();
_cPosition = cPosition;
_RedrawCursor();
// The VT code assumes that moving the cursor implicitly resets the delayed EOL wrap,
// so we call ResetDelayEOLWrap() independent of _cPosition != cPosition.
// You can see the effect of this with "`e[1;9999Ha`e[1;9999Hb", which should print just "b".
ResetDelayEOLWrap();
if (_cPosition != cPosition)
{
_cPosition = cPosition;
_redrawIfVisible();
}
}

void Cursor::SetXPosition(const til::CoordType NewX) noexcept
{
_RedrawCursor();
_cPosition.x = NewX;
_RedrawCursor();
ResetDelayEOLWrap();
if (_cPosition.x != NewX)
{
_cPosition.x = NewX;
_redrawIfVisible();
}
}

void Cursor::SetYPosition(const til::CoordType NewY) noexcept
{
_RedrawCursor();
_cPosition.y = NewY;
_RedrawCursor();
ResetDelayEOLWrap();
if (_cPosition.y != NewY)
{
_cPosition.y = NewY;
_redrawIfVisible();
}
}

void Cursor::IncrementXPosition(const til::CoordType DeltaX) noexcept
{
_RedrawCursor();
_cPosition.x += DeltaX;
_RedrawCursor();
ResetDelayEOLWrap();
if (DeltaX != 0)
{
_cPosition.x = _cPosition.x + DeltaX;
_redrawIfVisible();
}
}

void Cursor::IncrementYPosition(const til::CoordType DeltaY) noexcept
{
_RedrawCursor();
_cPosition.y += DeltaY;
_RedrawCursor();
ResetDelayEOLWrap();
if (DeltaY != 0)
{
_cPosition.y = _cPosition.y + DeltaY;
_redrawIfVisible();
}
}

void Cursor::DecrementXPosition(const til::CoordType DeltaX) noexcept
{
_RedrawCursor();
_cPosition.x -= DeltaX;
_RedrawCursor();
ResetDelayEOLWrap();
if (DeltaX != 0)
{
_cPosition.x = _cPosition.x - DeltaX;
_redrawIfVisible();
}
}

void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
{
_RedrawCursor();
_cPosition.y -= DeltaY;
_RedrawCursor();
ResetDelayEOLWrap();
if (DeltaY != 0)
{
_cPosition.y = _cPosition.y - DeltaY;
_redrawIfVisible();
}
}

///////////////////////////////////////////////////////////////////////////////
Expand All @@ -233,78 +176,53 @@ void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
// - OtherCursor - The cursor to copy properties from
// Return Value:
// - <none>
void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
void Cursor::CopyProperties(const Cursor& other) noexcept
{
// We shouldn't copy the position as it will be already rearranged by the resize operation.
//_cPosition = pOtherCursor->_cPosition;

_fIsVisible = OtherCursor._fIsVisible;
_fIsOn = OtherCursor._fIsOn;
_fIsDouble = OtherCursor._fIsDouble;
_fBlinkingAllowed = OtherCursor._fBlinkingAllowed;
_fDelay = OtherCursor._fDelay;
_fIsConversionArea = OtherCursor._fIsConversionArea;

// A resize operation should invalidate the delayed end of line status, so do not copy.
//_fDelayedEolWrap = OtherCursor._fDelayedEolWrap;
//_coordDelayedAt = OtherCursor._coordDelayedAt;

_fDeferCursorRedraw = OtherCursor._fDeferCursorRedraw;
_fHaveDeferredCursorRedraw = OtherCursor._fHaveDeferredCursorRedraw;

// Size will be handled separately in the resize operation.
//_ulSize = OtherCursor._ulSize;
_cursorType = OtherCursor._cursorType;
_cPosition = other._cPosition;
_coordDelayedAt = other._coordDelayedAt;
_ulSize = other._ulSize;
_cursorType = other._cursorType;
_isVisible = other._isVisible;
_isBlinking = other._isBlinking;
_fIsDouble = other._fIsDouble;
}

void Cursor::DelayEOLWrap() noexcept
{
_coordDelayedAt = _cPosition;
_fDelayedEolWrap = true;
}

void Cursor::ResetDelayEOLWrap() noexcept
{
_coordDelayedAt = {};
_fDelayedEolWrap = false;
_coordDelayedAt.reset();
}

til::point Cursor::GetDelayedAtPosition() const noexcept
const std::optional<til::point>& Cursor::GetDelayEOLWrap() const noexcept
{
return _coordDelayedAt;
}

bool Cursor::IsDelayedEOLWrap() const noexcept
CursorType Cursor::GetType() const noexcept
{
return _fDelayedEolWrap;
}

void Cursor::StartDeferDrawing() noexcept
{
_fDeferCursorRedraw = true;
return _cursorType;
}

bool Cursor::IsDeferDrawing() noexcept
void Cursor::SetType(const CursorType type) noexcept
{
return _fDeferCursorRedraw;
_cursorType = type;
}

void Cursor::EndDeferDrawing() noexcept
void Cursor::_redrawIfVisible() noexcept
{
if (_fHaveDeferredCursorRedraw)
_mutationId++;
if (_isVisible)
{
_RedrawCursorAlways();
_parentBuffer.NotifyPaintFrame();
}

_fDeferCursorRedraw = FALSE;
}

const CursorType Cursor::GetType() const noexcept
void Cursor::_redraw() noexcept
{
return _cursorType;
}

void Cursor::SetType(const CursorType type) noexcept
{
_cursorType = type;
_mutationId++;
_parentBuffer.NotifyPaintFrame();
}
Loading
Loading