1313// - ulSize - The height of the cursor within this buffer
1414Cursor::Cursor (const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
1515 _parentBuffer{ parentBuffer },
16- _fIsVisible (true ),
17- _fIsOn(true ),
18- _fIsDouble(false ),
19- _fBlinkingAllowed(true ),
20- _fDelay(false ),
21- _fIsConversionArea(false ),
22- _fDelayedEolWrap(false ),
23- _fDeferCursorRedraw(false ),
24- _fHaveDeferredCursorRedraw(false ),
25- _ulSize(ulSize),
26- _cursorType(CursorType::Legacy)
16+ _ulSize (ulSize)
2717{
2818}
2919
30- Cursor::~Cursor () = default ;
31-
3220til::point Cursor::GetPosition () const noexcept
3321{
3422 return _cPosition;
3523}
3624
37- bool Cursor::IsVisible () const noexcept
25+ uint64_t Cursor::GetLastMutationId () const noexcept
3826{
39- return _fIsVisible ;
27+ return _mutationId ;
4028}
4129
42- bool Cursor::IsOn () const noexcept
30+ bool Cursor::IsVisible () const noexcept
4331{
44- return _fIsOn ;
32+ return _isVisible ;
4533}
4634
47- bool Cursor::IsBlinkingAllowed () const noexcept
35+ bool Cursor::IsBlinking () const noexcept
4836{
49- return _fBlinkingAllowed ;
37+ return _isBlinking ;
5038}
5139
5240bool Cursor::IsDouble () const noexcept
5341{
5442 return _fIsDouble;
5543}
5644
57- bool Cursor::IsConversionArea () const noexcept
58- {
59- return _fIsConversionArea;
60- }
61-
62- bool Cursor::GetDelay () const noexcept
63- {
64- return _fDelay;
65- }
66-
6745ULONG Cursor::GetSize () const noexcept
6846{
6947 return _ulSize;
7048}
7149
72- void Cursor::SetIsVisible (const bool fIsVisible ) noexcept
73- {
74- _fIsVisible = fIsVisible ;
75- _RedrawCursor ();
76- }
77-
78- void Cursor::SetIsOn (const bool fIsOn ) noexcept
50+ void Cursor::SetIsVisible (bool enable)
7951{
80- _fIsOn = fIsOn ;
81- _RedrawCursorAlways ();
52+ if (_isVisible != enable)
53+ {
54+ _isVisible = enable;
55+ _redrawIfVisible ();
56+ }
8257}
8358
84- void Cursor::SetBlinkingAllowed ( const bool fBlinkingAllowed ) noexcept
59+ void Cursor::SetIsBlinking ( bool enable)
8560{
86- _fBlinkingAllowed = fBlinkingAllowed ;
87- // GH#2642 - From what we've gathered from other terminals, when blinking is
88- // disabled, the cursor should remain On always, and have the visibility
89- // controlled by the IsVisible property. So when you do a printf "\e[?12l"
90- // to disable blinking, the cursor stays stuck On. At this point, only the
91- // cursor visibility property controls whether the user can see it or not.
92- // (Yes, the cursor can be On and NOT Visible)
93- _fIsOn = true ;
94- _RedrawCursorAlways ();
61+ if (_isBlinking != enable)
62+ {
63+ _isBlinking = enable;
64+ _redrawIfVisible ();
65+ }
9566}
9667
9768void Cursor::SetIsDouble (const bool fIsDouble ) noexcept
9869{
99- _fIsDouble = fIsDouble ;
100- _RedrawCursor ();
101- }
102-
103- void Cursor::SetIsConversionArea (const bool fIsConversionArea ) noexcept
104- {
105- // Functionally the same as "Hide cursor"
106- // Never called with TRUE, it's only used in the creation of a
107- // ConversionAreaInfo, and never changed after that.
108- _fIsConversionArea = fIsConversionArea ;
109- _RedrawCursorAlways ();
110- }
111-
112- void Cursor::SetDelay (const bool fDelay ) noexcept
113- {
114- _fDelay = fDelay ;
70+ if (_fIsDouble != fIsDouble )
71+ {
72+ _fIsDouble = fIsDouble ;
73+ _redrawIfVisible ();
74+ }
11575}
11676
11777void Cursor::SetSize (const ULONG ulSize) noexcept
11878{
119- _ulSize = ulSize;
120- _RedrawCursor ();
79+ if (_ulSize != ulSize)
80+ {
81+ _ulSize = ulSize;
82+ _redrawIfVisible ();
83+ }
12184}
12285
12386void Cursor::SetStyle (const ULONG ulSize, const CursorType type) noexcept
12487{
125- _ulSize = ulSize;
126- _cursorType = type;
127-
128- _RedrawCursor ();
129- }
130-
131- // Routine Description:
132- // - Sends a redraw message to the renderer only if the cursor is currently on.
133- // - NOTE: For use with most methods in this class.
134- // Arguments:
135- // - <none>
136- // Return Value:
137- // - <none>
138- void Cursor::_RedrawCursor () noexcept
139- {
140- // Only trigger the redraw if we're on.
141- // Don't draw the cursor if this was triggered from a conversion area.
142- // (Conversion areas have cursors to mark the insertion point internally, but the user's actual cursor is the one on the primary screen buffer.)
143- if (IsOn () && !IsConversionArea ())
88+ if (_ulSize != ulSize || _cursorType != type)
14489 {
145- if (_fDeferCursorRedraw)
146- {
147- _fHaveDeferredCursorRedraw = true ;
148- }
149- else
150- {
151- _RedrawCursorAlways ();
152- }
90+ _ulSize = ulSize;
91+ _cursorType = type;
92+ _redrawIfVisible ();
15393 }
15494}
15595
156- // Routine Description:
157- // - Sends a redraw message to the renderer no matter what.
158- // - NOTE: For use with the method that turns the cursor on and off to force a refresh
159- // and clear the ON cursor from the screen. Not for use with other methods.
160- // They should use the other method so refreshes are suppressed while the cursor is off.
161- // Arguments:
162- // - <none>
163- // Return Value:
164- // - <none>
165- void Cursor::_RedrawCursorAlways () noexcept
166- {
167- _parentBuffer.NotifyPaintFrame ();
168- }
169-
17096void Cursor::SetPosition (const til::point cPosition) noexcept
17197{
172- _RedrawCursor ();
173- _cPosition = cPosition;
174- _RedrawCursor ();
98+ // The VT code assumes that moving the cursor implicitly resets the delayed EOL wrap,
99+ // so we call ResetDelayEOLWrap() independent of _cPosition ! = cPosition.
100+ // You can see the effect of this with "`e[1;9999Ha`e[1;9999Hb", which should print just "b".
175101 ResetDelayEOLWrap ();
102+ if (_cPosition != cPosition)
103+ {
104+ _cPosition = cPosition;
105+ _redrawIfVisible ();
106+ }
176107}
177108
178109void Cursor::SetXPosition (const til::CoordType NewX) noexcept
179110{
180- _RedrawCursor ();
181- _cPosition.x = NewX;
182- _RedrawCursor ();
183111 ResetDelayEOLWrap ();
112+ if (_cPosition.x != NewX)
113+ {
114+ _cPosition.x = NewX;
115+ _redrawIfVisible ();
116+ }
184117}
185118
186119void Cursor::SetYPosition (const til::CoordType NewY) noexcept
187120{
188- _RedrawCursor ();
189- _cPosition.y = NewY;
190- _RedrawCursor ();
191121 ResetDelayEOLWrap ();
122+ if (_cPosition.y != NewY)
123+ {
124+ _cPosition.y = NewY;
125+ _redrawIfVisible ();
126+ }
192127}
193128
194129void Cursor::IncrementXPosition (const til::CoordType DeltaX) noexcept
195130{
196- _RedrawCursor ();
197- _cPosition.x += DeltaX;
198- _RedrawCursor ();
199131 ResetDelayEOLWrap ();
132+ if (DeltaX != 0 )
133+ {
134+ _cPosition.x = _cPosition.x + DeltaX;
135+ _redrawIfVisible ();
136+ }
200137}
201138
202139void Cursor::IncrementYPosition (const til::CoordType DeltaY) noexcept
203140{
204- _RedrawCursor ();
205- _cPosition.y += DeltaY;
206- _RedrawCursor ();
207141 ResetDelayEOLWrap ();
142+ if (DeltaY != 0 )
143+ {
144+ _cPosition.y = _cPosition.y + DeltaY;
145+ _redrawIfVisible ();
146+ }
208147}
209148
210149void Cursor::DecrementXPosition (const til::CoordType DeltaX) noexcept
211150{
212- _RedrawCursor ();
213- _cPosition.x -= DeltaX;
214- _RedrawCursor ();
215151 ResetDelayEOLWrap ();
152+ if (DeltaX != 0 )
153+ {
154+ _cPosition.x = _cPosition.x - DeltaX;
155+ _redrawIfVisible ();
156+ }
216157}
217158
218159void Cursor::DecrementYPosition (const til::CoordType DeltaY) noexcept
219160{
220- _RedrawCursor ();
221- _cPosition.y -= DeltaY;
222- _RedrawCursor ();
223161 ResetDelayEOLWrap ();
162+ if (DeltaY != 0 )
163+ {
164+ _cPosition.y = _cPosition.y - DeltaY;
165+ _redrawIfVisible ();
166+ }
224167}
225168
226169// /////////////////////////////////////////////////////////////////////////////
@@ -233,78 +176,53 @@ void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
233176// - OtherCursor - The cursor to copy properties from
234177// Return Value:
235178// - <none>
236- void Cursor::CopyProperties (const Cursor& OtherCursor ) noexcept
179+ void Cursor::CopyProperties (const Cursor& other ) noexcept
237180{
238- // We shouldn't copy the position as it will be already rearranged by the resize operation.
239- // _cPosition = pOtherCursor->_cPosition;
240-
241- _fIsVisible = OtherCursor._fIsVisible ;
242- _fIsOn = OtherCursor._fIsOn ;
243- _fIsDouble = OtherCursor._fIsDouble ;
244- _fBlinkingAllowed = OtherCursor._fBlinkingAllowed ;
245- _fDelay = OtherCursor._fDelay ;
246- _fIsConversionArea = OtherCursor._fIsConversionArea ;
247-
248- // A resize operation should invalidate the delayed end of line status, so do not copy.
249- // _fDelayedEolWrap = OtherCursor._fDelayedEolWrap;
250- // _coordDelayedAt = OtherCursor._coordDelayedAt;
251-
252- _fDeferCursorRedraw = OtherCursor._fDeferCursorRedraw ;
253- _fHaveDeferredCursorRedraw = OtherCursor._fHaveDeferredCursorRedraw ;
254-
255- // Size will be handled separately in the resize operation.
256- // _ulSize = OtherCursor._ulSize;
257- _cursorType = OtherCursor._cursorType ;
181+ _cPosition = other._cPosition ;
182+ _coordDelayedAt = other._coordDelayedAt ;
183+ _ulSize = other._ulSize ;
184+ _cursorType = other._cursorType ;
185+ _isVisible = other._isVisible ;
186+ _isBlinking = other._isBlinking ;
187+ _fIsDouble = other._fIsDouble ;
258188}
259189
260190void Cursor::DelayEOLWrap () noexcept
261191{
262192 _coordDelayedAt = _cPosition;
263- _fDelayedEolWrap = true ;
264193}
265194
266195void Cursor::ResetDelayEOLWrap () noexcept
267196{
268- _coordDelayedAt = {};
269- _fDelayedEolWrap = false ;
197+ _coordDelayedAt.reset ();
270198}
271199
272- til::point Cursor::GetDelayedAtPosition () const noexcept
200+ const std::optional< til::point>& Cursor::GetDelayEOLWrap () const noexcept
273201{
274202 return _coordDelayedAt;
275203}
276204
277- bool Cursor::IsDelayedEOLWrap () const noexcept
205+ CursorType Cursor::GetType () const noexcept
278206{
279- return _fDelayedEolWrap;
280- }
281-
282- void Cursor::StartDeferDrawing () noexcept
283- {
284- _fDeferCursorRedraw = true ;
207+ return _cursorType;
285208}
286209
287- bool Cursor::IsDeferDrawing ( ) noexcept
210+ void Cursor::SetType ( const CursorType type ) noexcept
288211{
289- return _fDeferCursorRedraw ;
212+ _cursorType = type ;
290213}
291214
292- void Cursor::EndDeferDrawing () noexcept
215+ void Cursor::_redrawIfVisible () noexcept
293216{
294- if (_fHaveDeferredCursorRedraw)
217+ _mutationId++;
218+ if (_isVisible)
295219 {
296- _RedrawCursorAlways ();
220+ _parentBuffer. NotifyPaintFrame ();
297221 }
298-
299- _fDeferCursorRedraw = FALSE ;
300222}
301223
302- const CursorType Cursor::GetType () const noexcept
224+ void Cursor::_redraw () noexcept
303225{
304- return _cursorType;
305- }
306-
307- void Cursor::SetType (const CursorType type) noexcept
308- {
309- _cursorType = type;
226+ _mutationId++;
227+ _parentBuffer.NotifyPaintFrame ();
310228}
0 commit comments