@@ -57,7 +57,7 @@ std::vector<til::inclusive_rect> Terminal::_GetSelectionRects() const noexcept
5757
5858 try
5959 {
60- return _activeBuffer ().GetTextRects (_selection->start , _selection->end , _blockSelection , false );
60+ return _activeBuffer ().GetTextRects (_selection->start , _selection->end , _selection-> blockSelection , false );
6161 }
6262 CATCH_LOG ();
6363 return result;
@@ -78,7 +78,7 @@ std::vector<til::point_span> Terminal::_GetSelectionSpans() const noexcept
7878
7979 try
8080 {
81- return _activeBuffer ().GetTextSpans (_selection->start , _selection->end , _blockSelection , false );
81+ return _activeBuffer ().GetTextSpans (_selection->start , _selection->end , _selection-> blockSelection , false );
8282 }
8383 CATCH_LOG ();
8484 return result;
@@ -158,13 +158,13 @@ const Terminal::SelectionEndpoint Terminal::SelectionEndpointTarget() const noex
158158const bool Terminal::IsSelectionActive () const noexcept
159159{
160160 _assertLocked ();
161- return _selection. has_value () ;
161+ return _selection-> active ;
162162}
163163
164164const bool Terminal::IsBlockSelection () const noexcept
165165{
166166 _assertLocked ();
167- return _blockSelection ;
167+ return _selection-> blockSelection ;
168168}
169169
170170// Method Description:
@@ -175,15 +175,18 @@ const bool Terminal::IsBlockSelection() const noexcept
175175void Terminal::MultiClickSelection (const til::point viewportPos, SelectionExpansion expansionMode)
176176{
177177 // set the selection pivot to expand the selection using SetSelectionEnd()
178- _selection = SelectionAnchors{};
179- _selection->pivot = _ConvertToBufferCell (viewportPos);
178+ auto selection{ _selection.write () };
179+ wil::hide_name _selection;
180+
181+ selection->pivot = _ConvertToBufferCell (viewportPos);
182+ selection->active = true ;
180183
181184 _multiClickSelectionMode = expansionMode;
182185 SetSelectionEnd (viewportPos);
183186
184187 // we need to set the _selectionPivot again
185188 // for future shift+clicks
186- _selection ->pivot = _selection ->start ;
189+ selection ->pivot = selection ->start ;
187190}
188191
189192// Method Description:
@@ -194,13 +197,21 @@ void Terminal::SetSelectionAnchor(const til::point viewportPos)
194197{
195198 _assertLocked ();
196199
197- _selection = SelectionAnchors{};
198- _selection->pivot = _ConvertToBufferCell (viewportPos);
200+ auto selection{ _selection.write () };
201+ wil::hide_name _selection;
202+
203+ selection->pivot = _ConvertToBufferCell (viewportPos);
204+ selection->active = true ;
199205
200206 _multiClickSelectionMode = SelectionExpansion::Char;
201207 SetSelectionEnd (viewportPos);
202208
203- _selection->start = _selection->pivot ;
209+ selection->start = selection->pivot ;
210+ }
211+
212+ void Terminal::SetSelectionEnd (const til::point viewportPos, std::optional<SelectionExpansion> newExpansionMode)
213+ {
214+ _SetSelectionEnd (_selection.write (), viewportPos, newExpansionMode);
204215}
205216
206217// Method Description:
@@ -209,9 +220,10 @@ void Terminal::SetSelectionAnchor(const til::point viewportPos)
209220// Arguments:
210221// - viewportPos: the (x,y) coordinate on the visible viewport
211222// - newExpansionMode: overwrites the _multiClickSelectionMode for this function call. Used for ShiftClick
212- void Terminal::SetSelectionEnd ( const til::point viewportPos, std::optional<SelectionExpansion> newExpansionMode)
223+ void Terminal::_SetSelectionEnd (SelectionInfo* selection, const til::point viewportPos, std::optional<SelectionExpansion> newExpansionMode)
213224{
214- if (!IsSelectionActive ())
225+ wil::hide_name _selection;
226+ if (!selection->active )
215227 {
216228 // capture a log for spurious endpoint sets without an active selection
217229 LOG_HR (E_ILLEGAL_STATE_CHANGE);
@@ -231,17 +243,17 @@ void Terminal::SetSelectionEnd(const til::point viewportPos, std::optional<Selec
231243 if (newExpansionMode.has_value ())
232244 {
233245 // shift-click operations only expand the target side
234- auto & anchorToExpand = targetStart ? _selection ->start : _selection ->end ;
246+ auto & anchorToExpand = targetStart ? selection ->start : selection ->end ;
235247 anchorToExpand = targetStart ? expandedAnchors.first : expandedAnchors.second ;
236248
237249 // the other anchor should then become the pivot (we don't expand it)
238- auto & anchorToPivot = targetStart ? _selection ->end : _selection ->start ;
239- anchorToPivot = _selection ->pivot ;
250+ auto & anchorToPivot = targetStart ? selection ->end : selection ->start ;
251+ anchorToPivot = selection ->pivot ;
240252 }
241253 else
242254 {
243255 // expand both anchors
244- std::tie (_selection ->start , _selection ->end ) = expandedAnchors;
256+ std::tie (selection ->start , selection ->end ) = expandedAnchors;
245257 }
246258 _selectionMode = SelectionInteractionMode::Mouse;
247259 _selectionIsTargetingUrl = false ;
@@ -307,7 +319,7 @@ std::pair<til::point, til::point> Terminal::_ExpandSelectionAnchors(std::pair<ti
307319// - isEnabled: new value for _blockSelection
308320void Terminal::SetBlockSelection (const bool isEnabled) noexcept
309321{
310- _blockSelection = isEnabled;
322+ _selection. write ()-> blockSelection = isEnabled;
311323}
312324
313325Terminal::SelectionInteractionMode Terminal::SelectionMode () const noexcept
@@ -331,11 +343,13 @@ void Terminal::ToggleMarkMode()
331343 {
332344 // No selection --> start one at the cursor
333345 const auto cursorPos{ _activeBuffer ().GetCursor ().GetPosition () };
334- _selection = SelectionAnchors{};
335- _selection->start = cursorPos;
336- _selection->end = cursorPos;
337- _selection->pivot = cursorPos;
338- _blockSelection = false ;
346+ *_selection.write () = SelectionInfo{
347+ .start = cursorPos,
348+ .end = cursorPos,
349+ .pivot = cursorPos,
350+ .blockSelection = false ,
351+ .active = true ,
352+ };
339353 WI_SetAllFlags (_selectionEndpoint, SelectionEndpoint::Start | SelectionEndpoint::End);
340354 }
341355 else if (WI_AreAllFlagsClear (_selectionEndpoint, SelectionEndpoint::Start | SelectionEndpoint::End))
@@ -365,13 +379,13 @@ void Terminal::SwitchSelectionEndpoint() noexcept
365379 {
366380 // moving end --> now we're moving start
367381 _selectionEndpoint = SelectionEndpoint::Start;
368- _selection->pivot = _selection->end ;
382+ _selection. write () ->pivot = _selection->end ;
369383 }
370384 else if (WI_IsFlagSet (_selectionEndpoint, SelectionEndpoint::Start))
371385 {
372386 // moving start --> now we're moving end
373387 _selectionEndpoint = SelectionEndpoint::End;
374- _selection->pivot = _selection->start ;
388+ _selection. write () ->pivot = _selection->start ;
375389 }
376390 }
377391}
@@ -381,9 +395,11 @@ void Terminal::ExpandSelectionToWord()
381395 if (IsSelectionActive ())
382396 {
383397 const auto & buffer = _activeBuffer ();
384- _selection->start = buffer.GetWordStart (_selection->start , _wordDelimiters);
385- _selection->pivot = _selection->start ;
386- _selection->end = buffer.GetWordEnd (_selection->end , _wordDelimiters);
398+ auto selection{ _selection.write () };
399+ wil::hide_name _selection;
400+ selection->start = buffer.GetWordStart (selection->start , _wordDelimiters);
401+ selection->pivot = selection->start ;
402+ selection->end = buffer.GetWordEnd (selection->end , _wordDelimiters);
387403
388404 // if we're targeting both endpoints, instead just target "end"
389405 if (WI_IsFlagSet (_selectionEndpoint, SelectionEndpoint::Start) && WI_IsFlagSet (_selectionEndpoint, SelectionEndpoint::End))
@@ -528,12 +544,16 @@ void Terminal::SelectHyperlink(const SearchDirection dir)
528544 }
529545
530546 // 2. Select the hyperlink
531- _selection->start = result->first ;
532- _selection->pivot = result->first ;
533- _selection->end = result->second ;
534- bufferSize.DecrementInBounds (_selection->end );
535- _selectionIsTargetingUrl = true ;
536- _selectionEndpoint = SelectionEndpoint::End;
547+ {
548+ auto selection{ _selection.write () };
549+ wil::hide_name _selection;
550+ selection->start = result->first ;
551+ selection->pivot = result->first ;
552+ selection->end = result->second ;
553+ bufferSize.DecrementInBounds (selection->end );
554+ _selectionIsTargetingUrl = true ;
555+ _selectionEndpoint = SelectionEndpoint::End;
556+ }
537557
538558 // 3. Scroll to the selected area (if necessary)
539559 _ScrollToPoint (_selection->end );
@@ -646,19 +666,23 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
646666 // 3. Actually modify the selection state
647667 _selectionIsTargetingUrl = false ;
648668 _selectionMode = std::max (_selectionMode, SelectionInteractionMode::Keyboard);
669+
670+ auto selection{ _selection.write () };
671+ wil::hide_name _selection;
672+
649673 if (shouldMoveBothEndpoints)
650674 {
651675 // [Mark Mode] + shift unpressed --> move all three (i.e. just use arrow keys)
652- _selection ->start = targetPos;
653- _selection ->end = targetPos;
654- _selection ->pivot = targetPos;
676+ selection ->start = targetPos;
677+ selection ->end = targetPos;
678+ selection ->pivot = targetPos;
655679 }
656680 else
657681 {
658682 // [Mark Mode] + shift --> updating a standard selection
659683 // This is also standard quick-edit modification
660684 bool targetStart = false ;
661- std::tie (_selection ->start , _selection ->end ) = _PivotSelection (targetPos, targetStart);
685+ std::tie (selection ->start , selection ->end ) = _PivotSelection (targetPos, targetStart);
662686
663687 // IMPORTANT! Pivoting the selection here might have changed which endpoint we're targeting.
664688 // So let's set the targeted endpoint again.
@@ -673,10 +697,15 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
673697void Terminal::SelectAll ()
674698{
675699 const auto bufferSize{ _activeBuffer ().GetSize () };
676- _selection = SelectionAnchors{};
677- _selection->start = bufferSize.Origin ();
678- _selection->end = { bufferSize.RightInclusive (), _GetMutableViewport ().BottomInclusive () };
679- _selection->pivot = _selection->end ;
700+ const til::point end{ bufferSize.RightInclusive (), _GetMutableViewport ().BottomInclusive () };
701+ *_selection.write () = SelectionInfo{
702+ .start = bufferSize.Origin (),
703+ .end = end,
704+ .pivot = end,
705+ .blockSelection = false ,
706+ .active = true ,
707+ };
708+
680709 _selectionMode = SelectionInteractionMode::Keyboard;
681710 _selectionIsTargetingUrl = false ;
682711 _ScrollToPoint (_selection->start );
@@ -824,7 +853,7 @@ void Terminal::_MoveByBuffer(SelectionDirection direction, til::point& pos) noex
824853void Terminal::ClearSelection ()
825854{
826855 _assertLocked ();
827- _selection = std:: nullopt ;
856+ _selection. write ()-> active = false ;
828857 _selectionMode = SelectionInteractionMode::None;
829858 _selectionIsTargetingUrl = false ;
830859 _selectionEndpoint = static_cast <SelectionEndpoint>(0 );
@@ -858,7 +887,7 @@ Terminal::TextCopyData Terminal::RetrieveSelectedTextFromBuffer(const bool singl
858887
859888 const auto & textBuffer = _activeBuffer ();
860889
861- const auto req = TextBuffer::CopyRequest::FromConfig (textBuffer, _selection->start , _selection->end , singleLine, _blockSelection , _trimBlockSelection);
890+ const auto req = TextBuffer::CopyRequest::FromConfig (textBuffer, _selection->start , _selection->end , singleLine, _selection-> blockSelection , _trimBlockSelection);
862891 data.plainText = textBuffer.GetPlainText (req);
863892
864893 if (html || rtf)
0 commit comments