1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file Selection.cxx
3*8af74909SZhong Yang ** Classes maintaining the selection.
4*8af74909SZhong Yang **/
5*8af74909SZhong Yang // Copyright 2009 by Neil Hodgson <[email protected]>
6*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
7*8af74909SZhong Yang
8*8af74909SZhong Yang #include <cstddef>
9*8af74909SZhong Yang #include <cstdlib>
10*8af74909SZhong Yang
11*8af74909SZhong Yang #include <stdexcept>
12*8af74909SZhong Yang #include <string_view>
13*8af74909SZhong Yang #include <vector>
14*8af74909SZhong Yang #include <algorithm>
15*8af74909SZhong Yang #include <memory>
16*8af74909SZhong Yang
17*8af74909SZhong Yang #include "Platform.h"
18*8af74909SZhong Yang
19*8af74909SZhong Yang #include "Scintilla.h"
20*8af74909SZhong Yang
21*8af74909SZhong Yang #include "Position.h"
22*8af74909SZhong Yang #include "Selection.h"
23*8af74909SZhong Yang
24*8af74909SZhong Yang using namespace Scintilla;
25*8af74909SZhong Yang
MoveForInsertDelete(bool insertion,Sci::Position startChange,Sci::Position length,bool moveForEqual)26*8af74909SZhong Yang void SelectionPosition::MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length, bool moveForEqual) noexcept {
27*8af74909SZhong Yang if (insertion) {
28*8af74909SZhong Yang if (position == startChange) {
29*8af74909SZhong Yang // Always consume virtual space
30*8af74909SZhong Yang const Sci::Position virtualLengthRemove = std::min(length, virtualSpace);
31*8af74909SZhong Yang virtualSpace -= virtualLengthRemove;
32*8af74909SZhong Yang position += virtualLengthRemove;
33*8af74909SZhong Yang if (moveForEqual) {
34*8af74909SZhong Yang const Sci::Position lengthAfterVirtualRemove = length - virtualLengthRemove;
35*8af74909SZhong Yang position += lengthAfterVirtualRemove;
36*8af74909SZhong Yang }
37*8af74909SZhong Yang } else if (position > startChange) {
38*8af74909SZhong Yang position += length;
39*8af74909SZhong Yang }
40*8af74909SZhong Yang } else {
41*8af74909SZhong Yang if (position == startChange) {
42*8af74909SZhong Yang virtualSpace = 0;
43*8af74909SZhong Yang }
44*8af74909SZhong Yang if (position > startChange) {
45*8af74909SZhong Yang const Sci::Position endDeletion = startChange + length;
46*8af74909SZhong Yang if (position > endDeletion) {
47*8af74909SZhong Yang position -= length;
48*8af74909SZhong Yang } else {
49*8af74909SZhong Yang position = startChange;
50*8af74909SZhong Yang virtualSpace = 0;
51*8af74909SZhong Yang }
52*8af74909SZhong Yang }
53*8af74909SZhong Yang }
54*8af74909SZhong Yang }
55*8af74909SZhong Yang
operator <(const SelectionPosition & other) const56*8af74909SZhong Yang bool SelectionPosition::operator <(const SelectionPosition &other) const noexcept {
57*8af74909SZhong Yang if (position == other.position)
58*8af74909SZhong Yang return virtualSpace < other.virtualSpace;
59*8af74909SZhong Yang else
60*8af74909SZhong Yang return position < other.position;
61*8af74909SZhong Yang }
62*8af74909SZhong Yang
operator >(const SelectionPosition & other) const63*8af74909SZhong Yang bool SelectionPosition::operator >(const SelectionPosition &other) const noexcept {
64*8af74909SZhong Yang if (position == other.position)
65*8af74909SZhong Yang return virtualSpace > other.virtualSpace;
66*8af74909SZhong Yang else
67*8af74909SZhong Yang return position > other.position;
68*8af74909SZhong Yang }
69*8af74909SZhong Yang
operator <=(const SelectionPosition & other) const70*8af74909SZhong Yang bool SelectionPosition::operator <=(const SelectionPosition &other) const noexcept {
71*8af74909SZhong Yang if (position == other.position && virtualSpace == other.virtualSpace)
72*8af74909SZhong Yang return true;
73*8af74909SZhong Yang else
74*8af74909SZhong Yang return other > *this;
75*8af74909SZhong Yang }
76*8af74909SZhong Yang
operator >=(const SelectionPosition & other) const77*8af74909SZhong Yang bool SelectionPosition::operator >=(const SelectionPosition &other) const noexcept {
78*8af74909SZhong Yang if (position == other.position && virtualSpace == other.virtualSpace)
79*8af74909SZhong Yang return true;
80*8af74909SZhong Yang else
81*8af74909SZhong Yang return *this > other;
82*8af74909SZhong Yang }
83*8af74909SZhong Yang
Length() const84*8af74909SZhong Yang Sci::Position SelectionRange::Length() const noexcept {
85*8af74909SZhong Yang if (anchor > caret) {
86*8af74909SZhong Yang return anchor.Position() - caret.Position();
87*8af74909SZhong Yang } else {
88*8af74909SZhong Yang return caret.Position() - anchor.Position();
89*8af74909SZhong Yang }
90*8af74909SZhong Yang }
91*8af74909SZhong Yang
MoveForInsertDelete(bool insertion,Sci::Position startChange,Sci::Position length)92*8af74909SZhong Yang void SelectionRange::MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length) noexcept {
93*8af74909SZhong Yang // For insertions that occur at the start of the selection move both the start
94*8af74909SZhong Yang // and end of the selection to preserve the selected length.
95*8af74909SZhong Yang // The end will automatically move since it is after the insertion, so determine
96*8af74909SZhong Yang // which position is the start and pass this into
97*8af74909SZhong Yang // SelectionPosition::MoveForInsertDelete.
98*8af74909SZhong Yang // There isn't any reason to move an empty selection so don't move it.
99*8af74909SZhong Yang const bool caretStart = caret.Position() < anchor.Position();
100*8af74909SZhong Yang const bool anchorStart = anchor.Position() < caret.Position();
101*8af74909SZhong Yang
102*8af74909SZhong Yang caret.MoveForInsertDelete(insertion, startChange, length, caretStart);
103*8af74909SZhong Yang anchor.MoveForInsertDelete(insertion, startChange, length, anchorStart);
104*8af74909SZhong Yang }
105*8af74909SZhong Yang
Contains(Sci::Position pos) const106*8af74909SZhong Yang bool SelectionRange::Contains(Sci::Position pos) const noexcept {
107*8af74909SZhong Yang if (anchor > caret)
108*8af74909SZhong Yang return (pos >= caret.Position()) && (pos <= anchor.Position());
109*8af74909SZhong Yang else
110*8af74909SZhong Yang return (pos >= anchor.Position()) && (pos <= caret.Position());
111*8af74909SZhong Yang }
112*8af74909SZhong Yang
Contains(SelectionPosition sp) const113*8af74909SZhong Yang bool SelectionRange::Contains(SelectionPosition sp) const noexcept {
114*8af74909SZhong Yang if (anchor > caret)
115*8af74909SZhong Yang return (sp >= caret) && (sp <= anchor);
116*8af74909SZhong Yang else
117*8af74909SZhong Yang return (sp >= anchor) && (sp <= caret);
118*8af74909SZhong Yang }
119*8af74909SZhong Yang
ContainsCharacter(Sci::Position posCharacter) const120*8af74909SZhong Yang bool SelectionRange::ContainsCharacter(Sci::Position posCharacter) const noexcept {
121*8af74909SZhong Yang if (anchor > caret)
122*8af74909SZhong Yang return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
123*8af74909SZhong Yang else
124*8af74909SZhong Yang return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
125*8af74909SZhong Yang }
126*8af74909SZhong Yang
Intersect(SelectionSegment check) const127*8af74909SZhong Yang SelectionSegment SelectionRange::Intersect(SelectionSegment check) const noexcept {
128*8af74909SZhong Yang const SelectionSegment inOrder(caret, anchor);
129*8af74909SZhong Yang if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
130*8af74909SZhong Yang SelectionSegment portion = check;
131*8af74909SZhong Yang if (portion.start < inOrder.start)
132*8af74909SZhong Yang portion.start = inOrder.start;
133*8af74909SZhong Yang if (portion.end > inOrder.end)
134*8af74909SZhong Yang portion.end = inOrder.end;
135*8af74909SZhong Yang if (portion.start > portion.end)
136*8af74909SZhong Yang return SelectionSegment();
137*8af74909SZhong Yang else
138*8af74909SZhong Yang return portion;
139*8af74909SZhong Yang } else {
140*8af74909SZhong Yang return SelectionSegment();
141*8af74909SZhong Yang }
142*8af74909SZhong Yang }
143*8af74909SZhong Yang
Swap()144*8af74909SZhong Yang void SelectionRange::Swap() noexcept {
145*8af74909SZhong Yang std::swap(caret, anchor);
146*8af74909SZhong Yang }
147*8af74909SZhong Yang
Trim(SelectionRange range)148*8af74909SZhong Yang bool SelectionRange::Trim(SelectionRange range) noexcept {
149*8af74909SZhong Yang const SelectionPosition startRange = range.Start();
150*8af74909SZhong Yang const SelectionPosition endRange = range.End();
151*8af74909SZhong Yang SelectionPosition start = Start();
152*8af74909SZhong Yang SelectionPosition end = End();
153*8af74909SZhong Yang PLATFORM_ASSERT(start <= end);
154*8af74909SZhong Yang PLATFORM_ASSERT(startRange <= endRange);
155*8af74909SZhong Yang if ((startRange <= end) && (endRange >= start)) {
156*8af74909SZhong Yang if ((start > startRange) && (end < endRange)) {
157*8af74909SZhong Yang // Completely covered by range -> empty at start
158*8af74909SZhong Yang end = start;
159*8af74909SZhong Yang } else if ((start < startRange) && (end > endRange)) {
160*8af74909SZhong Yang // Completely covers range -> empty at start
161*8af74909SZhong Yang end = start;
162*8af74909SZhong Yang } else if (start <= startRange) {
163*8af74909SZhong Yang // Trim end
164*8af74909SZhong Yang end = startRange;
165*8af74909SZhong Yang } else { //
166*8af74909SZhong Yang PLATFORM_ASSERT(end >= endRange);
167*8af74909SZhong Yang // Trim start
168*8af74909SZhong Yang start = endRange;
169*8af74909SZhong Yang }
170*8af74909SZhong Yang if (anchor > caret) {
171*8af74909SZhong Yang caret = start;
172*8af74909SZhong Yang anchor = end;
173*8af74909SZhong Yang } else {
174*8af74909SZhong Yang anchor = start;
175*8af74909SZhong Yang caret = end;
176*8af74909SZhong Yang }
177*8af74909SZhong Yang return Empty();
178*8af74909SZhong Yang } else {
179*8af74909SZhong Yang return false;
180*8af74909SZhong Yang }
181*8af74909SZhong Yang }
182*8af74909SZhong Yang
183*8af74909SZhong Yang // If range is all virtual collapse to start of virtual space
MinimizeVirtualSpace()184*8af74909SZhong Yang void SelectionRange::MinimizeVirtualSpace() noexcept {
185*8af74909SZhong Yang if (caret.Position() == anchor.Position()) {
186*8af74909SZhong Yang Sci::Position virtualSpace = caret.VirtualSpace();
187*8af74909SZhong Yang if (virtualSpace > anchor.VirtualSpace())
188*8af74909SZhong Yang virtualSpace = anchor.VirtualSpace();
189*8af74909SZhong Yang caret.SetVirtualSpace(virtualSpace);
190*8af74909SZhong Yang anchor.SetVirtualSpace(virtualSpace);
191*8af74909SZhong Yang }
192*8af74909SZhong Yang }
193*8af74909SZhong Yang
Selection()194*8af74909SZhong Yang Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
195*8af74909SZhong Yang AddSelection(SelectionRange(SelectionPosition(0)));
196*8af74909SZhong Yang }
197*8af74909SZhong Yang
~Selection()198*8af74909SZhong Yang Selection::~Selection() {
199*8af74909SZhong Yang }
200*8af74909SZhong Yang
IsRectangular() const201*8af74909SZhong Yang bool Selection::IsRectangular() const noexcept {
202*8af74909SZhong Yang return (selType == selRectangle) || (selType == selThin);
203*8af74909SZhong Yang }
204*8af74909SZhong Yang
MainCaret() const205*8af74909SZhong Yang Sci::Position Selection::MainCaret() const noexcept {
206*8af74909SZhong Yang return ranges[mainRange].caret.Position();
207*8af74909SZhong Yang }
208*8af74909SZhong Yang
MainAnchor() const209*8af74909SZhong Yang Sci::Position Selection::MainAnchor() const noexcept {
210*8af74909SZhong Yang return ranges[mainRange].anchor.Position();
211*8af74909SZhong Yang }
212*8af74909SZhong Yang
Rectangular()213*8af74909SZhong Yang SelectionRange &Selection::Rectangular() noexcept {
214*8af74909SZhong Yang return rangeRectangular;
215*8af74909SZhong Yang }
216*8af74909SZhong Yang
Limits() const217*8af74909SZhong Yang SelectionSegment Selection::Limits() const noexcept {
218*8af74909SZhong Yang if (ranges.empty()) {
219*8af74909SZhong Yang return SelectionSegment();
220*8af74909SZhong Yang } else {
221*8af74909SZhong Yang SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
222*8af74909SZhong Yang for (size_t i=1; i<ranges.size(); i++) {
223*8af74909SZhong Yang sr.Extend(ranges[i].anchor);
224*8af74909SZhong Yang sr.Extend(ranges[i].caret);
225*8af74909SZhong Yang }
226*8af74909SZhong Yang return sr;
227*8af74909SZhong Yang }
228*8af74909SZhong Yang }
229*8af74909SZhong Yang
LimitsForRectangularElseMain() const230*8af74909SZhong Yang SelectionSegment Selection::LimitsForRectangularElseMain() const {
231*8af74909SZhong Yang if (IsRectangular()) {
232*8af74909SZhong Yang return Limits();
233*8af74909SZhong Yang } else {
234*8af74909SZhong Yang return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
235*8af74909SZhong Yang }
236*8af74909SZhong Yang }
237*8af74909SZhong Yang
Count() const238*8af74909SZhong Yang size_t Selection::Count() const noexcept {
239*8af74909SZhong Yang return ranges.size();
240*8af74909SZhong Yang }
241*8af74909SZhong Yang
Main() const242*8af74909SZhong Yang size_t Selection::Main() const noexcept {
243*8af74909SZhong Yang return mainRange;
244*8af74909SZhong Yang }
245*8af74909SZhong Yang
SetMain(size_t r)246*8af74909SZhong Yang void Selection::SetMain(size_t r) noexcept {
247*8af74909SZhong Yang PLATFORM_ASSERT(r < ranges.size());
248*8af74909SZhong Yang mainRange = r;
249*8af74909SZhong Yang }
250*8af74909SZhong Yang
Range(size_t r)251*8af74909SZhong Yang SelectionRange &Selection::Range(size_t r) noexcept {
252*8af74909SZhong Yang return ranges[r];
253*8af74909SZhong Yang }
254*8af74909SZhong Yang
Range(size_t r) const255*8af74909SZhong Yang const SelectionRange &Selection::Range(size_t r) const noexcept {
256*8af74909SZhong Yang return ranges[r];
257*8af74909SZhong Yang }
258*8af74909SZhong Yang
RangeMain()259*8af74909SZhong Yang SelectionRange &Selection::RangeMain() noexcept {
260*8af74909SZhong Yang return ranges[mainRange];
261*8af74909SZhong Yang }
262*8af74909SZhong Yang
RangeMain() const263*8af74909SZhong Yang const SelectionRange &Selection::RangeMain() const noexcept {
264*8af74909SZhong Yang return ranges[mainRange];
265*8af74909SZhong Yang }
266*8af74909SZhong Yang
Start() const267*8af74909SZhong Yang SelectionPosition Selection::Start() const noexcept {
268*8af74909SZhong Yang if (IsRectangular()) {
269*8af74909SZhong Yang return rangeRectangular.Start();
270*8af74909SZhong Yang } else {
271*8af74909SZhong Yang return ranges[mainRange].Start();
272*8af74909SZhong Yang }
273*8af74909SZhong Yang }
274*8af74909SZhong Yang
MoveExtends() const275*8af74909SZhong Yang bool Selection::MoveExtends() const noexcept {
276*8af74909SZhong Yang return moveExtends;
277*8af74909SZhong Yang }
278*8af74909SZhong Yang
SetMoveExtends(bool moveExtends_)279*8af74909SZhong Yang void Selection::SetMoveExtends(bool moveExtends_) noexcept {
280*8af74909SZhong Yang moveExtends = moveExtends_;
281*8af74909SZhong Yang }
282*8af74909SZhong Yang
Empty() const283*8af74909SZhong Yang bool Selection::Empty() const noexcept {
284*8af74909SZhong Yang for (const SelectionRange &range : ranges) {
285*8af74909SZhong Yang if (!range.Empty())
286*8af74909SZhong Yang return false;
287*8af74909SZhong Yang }
288*8af74909SZhong Yang return true;
289*8af74909SZhong Yang }
290*8af74909SZhong Yang
Last() const291*8af74909SZhong Yang SelectionPosition Selection::Last() const noexcept {
292*8af74909SZhong Yang SelectionPosition lastPosition;
293*8af74909SZhong Yang for (const SelectionRange &range : ranges) {
294*8af74909SZhong Yang if (lastPosition < range.caret)
295*8af74909SZhong Yang lastPosition = range.caret;
296*8af74909SZhong Yang if (lastPosition < range.anchor)
297*8af74909SZhong Yang lastPosition = range.anchor;
298*8af74909SZhong Yang }
299*8af74909SZhong Yang return lastPosition;
300*8af74909SZhong Yang }
301*8af74909SZhong Yang
Length() const302*8af74909SZhong Yang Sci::Position Selection::Length() const noexcept {
303*8af74909SZhong Yang Sci::Position len = 0;
304*8af74909SZhong Yang for (const SelectionRange &range : ranges) {
305*8af74909SZhong Yang len += range.Length();
306*8af74909SZhong Yang }
307*8af74909SZhong Yang return len;
308*8af74909SZhong Yang }
309*8af74909SZhong Yang
MovePositions(bool insertion,Sci::Position startChange,Sci::Position length)310*8af74909SZhong Yang void Selection::MovePositions(bool insertion, Sci::Position startChange, Sci::Position length) noexcept {
311*8af74909SZhong Yang for (SelectionRange &range : ranges) {
312*8af74909SZhong Yang range.MoveForInsertDelete(insertion, startChange, length);
313*8af74909SZhong Yang }
314*8af74909SZhong Yang if (selType == selRectangle) {
315*8af74909SZhong Yang rangeRectangular.MoveForInsertDelete(insertion, startChange, length);
316*8af74909SZhong Yang }
317*8af74909SZhong Yang }
318*8af74909SZhong Yang
TrimSelection(SelectionRange range)319*8af74909SZhong Yang void Selection::TrimSelection(SelectionRange range) noexcept {
320*8af74909SZhong Yang for (size_t i=0; i<ranges.size();) {
321*8af74909SZhong Yang if ((i != mainRange) && (ranges[i].Trim(range))) {
322*8af74909SZhong Yang // Trimmed to empty so remove
323*8af74909SZhong Yang for (size_t j=i; j<ranges.size()-1; j++) {
324*8af74909SZhong Yang ranges[j] = ranges[j+1];
325*8af74909SZhong Yang if (j == mainRange-1)
326*8af74909SZhong Yang mainRange--;
327*8af74909SZhong Yang }
328*8af74909SZhong Yang ranges.pop_back();
329*8af74909SZhong Yang } else {
330*8af74909SZhong Yang i++;
331*8af74909SZhong Yang }
332*8af74909SZhong Yang }
333*8af74909SZhong Yang }
334*8af74909SZhong Yang
TrimOtherSelections(size_t r,SelectionRange range)335*8af74909SZhong Yang void Selection::TrimOtherSelections(size_t r, SelectionRange range) noexcept {
336*8af74909SZhong Yang for (size_t i = 0; i<ranges.size(); ++i) {
337*8af74909SZhong Yang if (i != r) {
338*8af74909SZhong Yang ranges[i].Trim(range);
339*8af74909SZhong Yang }
340*8af74909SZhong Yang }
341*8af74909SZhong Yang }
342*8af74909SZhong Yang
SetSelection(SelectionRange range)343*8af74909SZhong Yang void Selection::SetSelection(SelectionRange range) {
344*8af74909SZhong Yang ranges.clear();
345*8af74909SZhong Yang ranges.push_back(range);
346*8af74909SZhong Yang mainRange = ranges.size() - 1;
347*8af74909SZhong Yang }
348*8af74909SZhong Yang
AddSelection(SelectionRange range)349*8af74909SZhong Yang void Selection::AddSelection(SelectionRange range) {
350*8af74909SZhong Yang TrimSelection(range);
351*8af74909SZhong Yang ranges.push_back(range);
352*8af74909SZhong Yang mainRange = ranges.size() - 1;
353*8af74909SZhong Yang }
354*8af74909SZhong Yang
AddSelectionWithoutTrim(SelectionRange range)355*8af74909SZhong Yang void Selection::AddSelectionWithoutTrim(SelectionRange range) {
356*8af74909SZhong Yang ranges.push_back(range);
357*8af74909SZhong Yang mainRange = ranges.size() - 1;
358*8af74909SZhong Yang }
359*8af74909SZhong Yang
DropSelection(size_t r)360*8af74909SZhong Yang void Selection::DropSelection(size_t r) {
361*8af74909SZhong Yang if ((ranges.size() > 1) && (r < ranges.size())) {
362*8af74909SZhong Yang size_t mainNew = mainRange;
363*8af74909SZhong Yang if (mainNew >= r) {
364*8af74909SZhong Yang if (mainNew == 0) {
365*8af74909SZhong Yang mainNew = ranges.size() - 2;
366*8af74909SZhong Yang } else {
367*8af74909SZhong Yang mainNew--;
368*8af74909SZhong Yang }
369*8af74909SZhong Yang }
370*8af74909SZhong Yang ranges.erase(ranges.begin() + r);
371*8af74909SZhong Yang mainRange = mainNew;
372*8af74909SZhong Yang }
373*8af74909SZhong Yang }
374*8af74909SZhong Yang
DropAdditionalRanges()375*8af74909SZhong Yang void Selection::DropAdditionalRanges() {
376*8af74909SZhong Yang SetSelection(RangeMain());
377*8af74909SZhong Yang }
378*8af74909SZhong Yang
TentativeSelection(SelectionRange range)379*8af74909SZhong Yang void Selection::TentativeSelection(SelectionRange range) {
380*8af74909SZhong Yang if (!tentativeMain) {
381*8af74909SZhong Yang rangesSaved = ranges;
382*8af74909SZhong Yang }
383*8af74909SZhong Yang ranges = rangesSaved;
384*8af74909SZhong Yang AddSelection(range);
385*8af74909SZhong Yang TrimSelection(ranges[mainRange]);
386*8af74909SZhong Yang tentativeMain = true;
387*8af74909SZhong Yang }
388*8af74909SZhong Yang
CommitTentative()389*8af74909SZhong Yang void Selection::CommitTentative() noexcept {
390*8af74909SZhong Yang rangesSaved.clear();
391*8af74909SZhong Yang tentativeMain = false;
392*8af74909SZhong Yang }
393*8af74909SZhong Yang
CharacterInSelection(Sci::Position posCharacter) const394*8af74909SZhong Yang int Selection::CharacterInSelection(Sci::Position posCharacter) const noexcept {
395*8af74909SZhong Yang for (size_t i=0; i<ranges.size(); i++) {
396*8af74909SZhong Yang if (ranges[i].ContainsCharacter(posCharacter))
397*8af74909SZhong Yang return i == mainRange ? 1 : 2;
398*8af74909SZhong Yang }
399*8af74909SZhong Yang return 0;
400*8af74909SZhong Yang }
401*8af74909SZhong Yang
InSelectionForEOL(Sci::Position pos) const402*8af74909SZhong Yang int Selection::InSelectionForEOL(Sci::Position pos) const noexcept {
403*8af74909SZhong Yang for (size_t i=0; i<ranges.size(); i++) {
404*8af74909SZhong Yang if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
405*8af74909SZhong Yang return i == mainRange ? 1 : 2;
406*8af74909SZhong Yang }
407*8af74909SZhong Yang return 0;
408*8af74909SZhong Yang }
409*8af74909SZhong Yang
VirtualSpaceFor(Sci::Position pos) const410*8af74909SZhong Yang Sci::Position Selection::VirtualSpaceFor(Sci::Position pos) const noexcept {
411*8af74909SZhong Yang Sci::Position virtualSpace = 0;
412*8af74909SZhong Yang for (const SelectionRange &range : ranges) {
413*8af74909SZhong Yang if ((range.caret.Position() == pos) && (virtualSpace < range.caret.VirtualSpace()))
414*8af74909SZhong Yang virtualSpace = range.caret.VirtualSpace();
415*8af74909SZhong Yang if ((range.anchor.Position() == pos) && (virtualSpace < range.anchor.VirtualSpace()))
416*8af74909SZhong Yang virtualSpace = range.anchor.VirtualSpace();
417*8af74909SZhong Yang }
418*8af74909SZhong Yang return virtualSpace;
419*8af74909SZhong Yang }
420*8af74909SZhong Yang
Clear()421*8af74909SZhong Yang void Selection::Clear() {
422*8af74909SZhong Yang ranges.clear();
423*8af74909SZhong Yang ranges.emplace_back();
424*8af74909SZhong Yang mainRange = ranges.size() - 1;
425*8af74909SZhong Yang selType = selStream;
426*8af74909SZhong Yang moveExtends = false;
427*8af74909SZhong Yang ranges[mainRange].Reset();
428*8af74909SZhong Yang rangeRectangular.Reset();
429*8af74909SZhong Yang }
430*8af74909SZhong Yang
RemoveDuplicates()431*8af74909SZhong Yang void Selection::RemoveDuplicates() {
432*8af74909SZhong Yang for (size_t i=0; i<ranges.size()-1; i++) {
433*8af74909SZhong Yang if (ranges[i].Empty()) {
434*8af74909SZhong Yang size_t j=i+1;
435*8af74909SZhong Yang while (j<ranges.size()) {
436*8af74909SZhong Yang if (ranges[i] == ranges[j]) {
437*8af74909SZhong Yang ranges.erase(ranges.begin() + j);
438*8af74909SZhong Yang if (mainRange >= j)
439*8af74909SZhong Yang mainRange--;
440*8af74909SZhong Yang } else {
441*8af74909SZhong Yang j++;
442*8af74909SZhong Yang }
443*8af74909SZhong Yang }
444*8af74909SZhong Yang }
445*8af74909SZhong Yang }
446*8af74909SZhong Yang }
447*8af74909SZhong Yang
RotateMain()448*8af74909SZhong Yang void Selection::RotateMain() noexcept {
449*8af74909SZhong Yang mainRange = (mainRange + 1) % ranges.size();
450*8af74909SZhong Yang }
451*8af74909SZhong Yang
452