2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "cursor.h"
|
|
|
|
#include "TextBuffer.hpp"
|
|
|
|
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
// Routine Description:
|
|
|
|
// - Constructor to set default properties for Cursor
|
|
|
|
// Arguments:
|
|
|
|
// - ulSize - The height of the cursor within this buffer
|
2019-08-30 00:23:07 +02:00
|
|
|
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept:
|
2019-05-03 00:29:04 +02:00
|
|
|
_parentBuffer{ parentBuffer },
|
|
|
|
_cPosition{ 0 },
|
|
|
|
_fHasMoved(false),
|
|
|
|
_fIsVisible(true),
|
|
|
|
_fIsOn(true),
|
|
|
|
_fIsDouble(false),
|
|
|
|
_fBlinkingAllowed(true),
|
|
|
|
_fDelay(false),
|
|
|
|
_fIsConversionArea(false),
|
|
|
|
_fIsPopupShown(false),
|
|
|
|
_fDelayedEolWrap(false),
|
|
|
|
_coordDelayedAt{ 0 },
|
|
|
|
_fDeferCursorRedraw(false),
|
|
|
|
_fHaveDeferredCursorRedraw(false),
|
|
|
|
_ulSize(ulSize),
|
|
|
|
_cursorType(CursorType::Legacy),
|
|
|
|
_fUseColor(false),
|
|
|
|
_color(s_InvertCursorColor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor::~Cursor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
COORD Cursor::GetPosition() const noexcept
|
|
|
|
{
|
|
|
|
return _cPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::HasMoved() const noexcept
|
|
|
|
{
|
|
|
|
return _fHasMoved;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsVisible() const noexcept
|
|
|
|
{
|
|
|
|
return _fIsVisible;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsOn() const noexcept
|
|
|
|
{
|
|
|
|
return _fIsOn;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsBlinkingAllowed() const noexcept
|
|
|
|
{
|
|
|
|
return _fBlinkingAllowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsDouble() const noexcept
|
|
|
|
{
|
|
|
|
return _fIsDouble;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsConversionArea() const noexcept
|
|
|
|
{
|
|
|
|
return _fIsConversionArea;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::IsPopupShown() const noexcept
|
|
|
|
{
|
|
|
|
return _fIsPopupShown;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cursor::GetDelay() const noexcept
|
|
|
|
{
|
|
|
|
return _fDelay;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG Cursor::GetSize() const noexcept
|
|
|
|
{
|
|
|
|
return _ulSize;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetHasMoved(const bool fHasMoved) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fHasMoved = fHasMoved;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetIsVisible(const bool fIsVisible) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fIsVisible = fIsVisible;
|
|
|
|
_RedrawCursor();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetIsOn(const bool fIsOn) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fIsOn = fIsOn;
|
|
|
|
_RedrawCursorAlways();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fBlinkingAllowed = fBlinkingAllowed;
|
|
|
|
_RedrawCursorAlways();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetIsDouble(const bool fIsDouble) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fIsDouble = fIsDouble;
|
|
|
|
_RedrawCursor();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetIsConversionArea(const bool fIsConversionArea) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetIsPopupShown(const bool fIsPopupShown) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
// Functionally the same as "Hide cursor"
|
|
|
|
_fIsPopupShown = fIsPopupShown;
|
|
|
|
_RedrawCursorAlways();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetDelay(const bool fDelay) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fDelay = fDelay;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetSize(const ULONG ulSize) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_ulSize = ulSize;
|
|
|
|
_RedrawCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
|
|
|
|
{
|
|
|
|
_ulSize = ulSize;
|
|
|
|
_color = color;
|
|
|
|
_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 (_fDeferCursorRedraw)
|
|
|
|
{
|
|
|
|
_fHaveDeferredCursorRedraw = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_RedrawCursorAlways();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_parentBuffer.GetRenderTarget().TriggerRedrawCursor(&_cPosition);
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetPosition(const COORD cPosition) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
|
|
|
_cPosition.X = cPosition.X;
|
|
|
|
_cPosition.Y = cPosition.Y;
|
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetXPosition(const int NewX) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.X = gsl::narrow<SHORT>(NewX);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetYPosition(const int NewY) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.Y = gsl::narrow<SHORT>(NewY);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::IncrementXPosition(const int DeltaX) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.X += gsl::narrow<SHORT>(DeltaX);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::IncrementYPosition(const int DeltaY) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.Y += gsl::narrow<SHORT>(DeltaY);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::DecrementXPosition(const int DeltaX) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.X -= gsl::narrow<SHORT>(DeltaX);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::DecrementYPosition(const int DeltaY) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_RedrawCursor();
|
2019-08-29 21:45:16 +02:00
|
|
|
_cPosition.Y -= gsl::narrow<SHORT>(DeltaY);
|
2019-05-03 00:29:04 +02:00
|
|
|
_RedrawCursor();
|
|
|
|
ResetDelayEOLWrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Routine Description:
|
|
|
|
// - Copies properties from another cursor into this one.
|
|
|
|
// - This is primarily to copy properties that would otherwise not be specified during CreateInstance
|
|
|
|
// - NOTE: As of now, this function is specifically used to handle the ResizeWithReflow operation.
|
|
|
|
// It will need modification for other future users.
|
|
|
|
// Arguments:
|
|
|
|
// - OtherCursor - The cursor to copy properties from
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
// We shouldn't copy the position as it will be already rearranged by the resize operation.
|
|
|
|
//_cPosition = pOtherCursor->_cPosition;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
_fHasMoved = OtherCursor._fHasMoved;
|
|
|
|
_fIsVisible = OtherCursor._fIsVisible;
|
|
|
|
_fIsOn = OtherCursor._fIsOn;
|
|
|
|
_fIsDouble = OtherCursor._fIsDouble;
|
|
|
|
_fBlinkingAllowed = OtherCursor._fBlinkingAllowed;
|
|
|
|
_fDelay = OtherCursor._fDelay;
|
|
|
|
_fIsConversionArea = OtherCursor._fIsConversionArea;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
// A resize operation should invalidate the delayed end of line status, so do not copy.
|
|
|
|
//_fDelayedEolWrap = OtherCursor._fDelayedEolWrap;
|
|
|
|
//_coordDelayedAt = OtherCursor._coordDelayedAt;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
_fDeferCursorRedraw = OtherCursor._fDeferCursorRedraw;
|
|
|
|
_fHaveDeferredCursorRedraw = OtherCursor._fHaveDeferredCursorRedraw;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
// Size will be handled seperately in the resize operation.
|
|
|
|
//_ulSize = OtherCursor._ulSize;
|
2019-06-11 22:27:09 +02:00
|
|
|
_cursorType = OtherCursor._cursorType;
|
|
|
|
_color = OtherCursor._color;
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_coordDelayedAt = coordDelayedAt;
|
|
|
|
_fDelayedEolWrap = true;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::ResetDelayEOLWrap() noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2019-06-11 22:27:09 +02:00
|
|
|
_coordDelayedAt = { 0 };
|
2019-05-03 00:29:04 +02:00
|
|
|
_fDelayedEolWrap = false;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
COORD Cursor::GetDelayedAtPosition() const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _coordDelayedAt;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
bool Cursor::IsDelayedEOLWrap() const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _fDelayedEolWrap;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::StartDeferDrawing() noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_fDeferCursorRedraw = true;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::EndDeferDrawing() noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
if (_fHaveDeferredCursorRedraw)
|
|
|
|
{
|
|
|
|
_RedrawCursorAlways();
|
|
|
|
}
|
|
|
|
|
|
|
|
_fDeferCursorRedraw = FALSE;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
const CursorType Cursor::GetType() const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _cursorType;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
const bool Cursor::IsUsingColor() const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return GetColor() != INVALID_COLOR;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
const COLORREF Cursor::GetColor() const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _color;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetColor(const unsigned int color) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2019-08-29 22:19:01 +02:00
|
|
|
_color = gsl::narrow_cast<COLORREF>(color);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void Cursor::SetType(const CursorType type) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_cursorType = type;
|
|
|
|
}
|