1 // Scintilla source code edit control
2 /** @file Selection.h
3  ** Classes maintaining the selection.
4  **/
5 // Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7 
8 #ifndef SELECTION_H
9 #define SELECTION_H
10 
11 namespace Scintilla {
12 
13 class SelectionPosition {
14 	Sci::Position position;
15 	Sci::Position virtualSpace;
16 public:
position(position_)17 	explicit SelectionPosition(Sci::Position position_=INVALID_POSITION, Sci::Position virtualSpace_=0) noexcept : position(position_), virtualSpace(virtualSpace_) {
18 		PLATFORM_ASSERT(virtualSpace < 800000);
19 		if (virtualSpace < 0)
20 			virtualSpace = 0;
21 	}
Reset()22 	void Reset() noexcept {
23 		position = 0;
24 		virtualSpace = 0;
25 	}
26 	void MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length, bool moveForEqual) noexcept;
27 	bool operator ==(const SelectionPosition &other) const noexcept {
28 		return position == other.position && virtualSpace == other.virtualSpace;
29 	}
30 	bool operator <(const SelectionPosition &other) const noexcept;
31 	bool operator >(const SelectionPosition &other) const noexcept;
32 	bool operator <=(const SelectionPosition &other) const noexcept;
33 	bool operator >=(const SelectionPosition &other) const noexcept;
Position()34 	Sci::Position Position() const noexcept {
35 		return position;
36 	}
SetPosition(Sci::Position position_)37 	void SetPosition(Sci::Position position_) noexcept {
38 		position = position_;
39 		virtualSpace = 0;
40 	}
VirtualSpace()41 	Sci::Position VirtualSpace() const noexcept {
42 		return virtualSpace;
43 	}
SetVirtualSpace(Sci::Position virtualSpace_)44 	void SetVirtualSpace(Sci::Position virtualSpace_) noexcept {
45 		PLATFORM_ASSERT(virtualSpace_ < 800000);
46 		if (virtualSpace_ >= 0)
47 			virtualSpace = virtualSpace_;
48 	}
Add(Sci::Position increment)49 	void Add(Sci::Position increment) noexcept {
50 		position = position + increment;
51 	}
IsValid()52 	bool IsValid() const noexcept {
53 		return position >= 0;
54 	}
55 };
56 
57 // Ordered range to make drawing simpler
58 struct SelectionSegment {
59 	SelectionPosition start;
60 	SelectionPosition end;
SelectionSegmentSelectionSegment61 	SelectionSegment() noexcept : start(), end() {
62 	}
SelectionSegmentSelectionSegment63 	SelectionSegment(SelectionPosition a, SelectionPosition b) noexcept {
64 		if (a < b) {
65 			start = a;
66 			end = b;
67 		} else {
68 			start = b;
69 			end = a;
70 		}
71 	}
EmptySelectionSegment72 	bool Empty() const noexcept {
73 		return start == end;
74 	}
LengthSelectionSegment75 	Sci::Position Length() const noexcept {
76 		return end.Position() - start.Position();
77 	}
ExtendSelectionSegment78 	void Extend(SelectionPosition p) noexcept {
79 		if (start > p)
80 			start = p;
81 		if (end < p)
82 			end = p;
83 	}
84 };
85 
86 struct SelectionRange {
87 	SelectionPosition caret;
88 	SelectionPosition anchor;
89 
SelectionRangeSelectionRange90 	SelectionRange() noexcept : caret(), anchor() {
91 	}
SelectionRangeSelectionRange92 	explicit SelectionRange(SelectionPosition single) noexcept : caret(single), anchor(single) {
93 	}
SelectionRangeSelectionRange94 	explicit SelectionRange(Sci::Position single) noexcept : caret(single), anchor(single) {
95 	}
SelectionRangeSelectionRange96 	SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) noexcept : caret(caret_), anchor(anchor_) {
97 	}
SelectionRangeSelectionRange98 	SelectionRange(Sci::Position caret_, Sci::Position anchor_) noexcept : caret(caret_), anchor(anchor_) {
99 	}
EmptySelectionRange100 	bool Empty() const noexcept {
101 		return anchor == caret;
102 	}
103 	Sci::Position Length() const noexcept;
104 	// Sci::Position Width() const;	// Like Length but takes virtual space into account
105 	bool operator ==(const SelectionRange &other) const noexcept {
106 		return caret == other.caret && anchor == other.anchor;
107 	}
108 	bool operator <(const SelectionRange &other) const noexcept {
109 		return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor));
110 	}
ResetSelectionRange111 	void Reset() noexcept {
112 		anchor.Reset();
113 		caret.Reset();
114 	}
ClearVirtualSpaceSelectionRange115 	void ClearVirtualSpace() noexcept {
116 		anchor.SetVirtualSpace(0);
117 		caret.SetVirtualSpace(0);
118 	}
119 	void MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length) noexcept;
120 	bool Contains(Sci::Position pos) const noexcept;
121 	bool Contains(SelectionPosition sp) const noexcept;
122 	bool ContainsCharacter(Sci::Position posCharacter) const noexcept;
123 	SelectionSegment Intersect(SelectionSegment check) const noexcept;
StartSelectionRange124 	SelectionPosition Start() const noexcept {
125 		return (anchor < caret) ? anchor : caret;
126 	}
EndSelectionRange127 	SelectionPosition End() const noexcept {
128 		return (anchor < caret) ? caret : anchor;
129 	}
130 	void Swap() noexcept;
131 	bool Trim(SelectionRange range) noexcept;
132 	// If range is all virtual collapse to start of virtual space
133 	void MinimizeVirtualSpace() noexcept;
134 };
135 
136 class Selection {
137 	std::vector<SelectionRange> ranges;
138 	std::vector<SelectionRange> rangesSaved;
139 	SelectionRange rangeRectangular;
140 	size_t mainRange;
141 	bool moveExtends;
142 	bool tentativeMain;
143 public:
144 	enum selTypes { noSel, selStream, selRectangle, selLines, selThin };
145 	selTypes selType;
146 
147 	Selection();
148 	~Selection();
149 	bool IsRectangular() const noexcept;
150 	Sci::Position MainCaret() const noexcept;
151 	Sci::Position MainAnchor() const noexcept;
152 	SelectionRange &Rectangular() noexcept;
153 	SelectionSegment Limits() const noexcept;
154 	// This is for when you want to move the caret in response to a
155 	// user direction command - for rectangular selections, use the range
156 	// that covers all selected text otherwise return the main selection.
157 	SelectionSegment LimitsForRectangularElseMain() const;
158 	size_t Count() const noexcept;
159 	size_t Main() const noexcept;
160 	void SetMain(size_t r) noexcept;
161 	SelectionRange &Range(size_t r) noexcept;
162 	const SelectionRange &Range(size_t r) const noexcept;
163 	SelectionRange &RangeMain() noexcept;
164 	const SelectionRange &RangeMain() const noexcept;
165 	SelectionPosition Start() const noexcept;
166 	bool MoveExtends() const noexcept;
167 	void SetMoveExtends(bool moveExtends_) noexcept;
168 	bool Empty() const noexcept;
169 	SelectionPosition Last() const noexcept;
170 	Sci::Position Length() const noexcept;
171 	void MovePositions(bool insertion, Sci::Position startChange, Sci::Position length) noexcept;
172 	void TrimSelection(SelectionRange range) noexcept;
173 	void TrimOtherSelections(size_t r, SelectionRange range) noexcept;
174 	void SetSelection(SelectionRange range);
175 	void AddSelection(SelectionRange range);
176 	void AddSelectionWithoutTrim(SelectionRange range);
177 	void DropSelection(size_t r);
178 	void DropAdditionalRanges();
179 	void TentativeSelection(SelectionRange range);
180 	void CommitTentative() noexcept;
181 	int CharacterInSelection(Sci::Position posCharacter) const noexcept;
182 	int InSelectionForEOL(Sci::Position pos) const noexcept;
183 	Sci::Position VirtualSpaceFor(Sci::Position pos) const noexcept;
184 	void Clear();
185 	void RemoveDuplicates();
186 	void RotateMain() noexcept;
Tentative()187 	bool Tentative() const noexcept { return tentativeMain; }
RangesCopy()188 	std::vector<SelectionRange> RangesCopy() const {
189 		return ranges;
190 	}
191 };
192 
193 }
194 
195 #endif
196