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 #ifdef SCI_NAMESPACE
12 namespace Scintilla {
13 #endif
14 
15 class SelectionPosition {
16 	int position;
17 	int virtualSpace;
18 public:
position(position_)19 	explicit SelectionPosition(int position_=INVALID_POSITION, int virtualSpace_=0) : position(position_), virtualSpace(virtualSpace_) {
20 		PLATFORM_ASSERT(virtualSpace < 800000);
21 		if (virtualSpace < 0)
22 			virtualSpace = 0;
23 	}
Reset()24 	void Reset() {
25 		position = 0;
26 		virtualSpace = 0;
27 	}
28 	void MoveForInsertDelete(bool insertion, int startChange, int length);
29 	bool operator ==(const SelectionPosition &other) const {
30 		return position == other.position && virtualSpace == other.virtualSpace;
31 	}
32 	bool operator <(const SelectionPosition &other) const;
33 	bool operator >(const SelectionPosition &other) const;
34 	bool operator <=(const SelectionPosition &other) const;
35 	bool operator >=(const SelectionPosition &other) const;
Position()36 	int Position() const {
37 		return position;
38 	}
SetPosition(int position_)39 	void SetPosition(int position_) {
40 		position = position_;
41 		virtualSpace = 0;
42 	}
VirtualSpace()43 	int VirtualSpace() const {
44 		return virtualSpace;
45 	}
SetVirtualSpace(int virtualSpace_)46 	void SetVirtualSpace(int virtualSpace_) {
47 		PLATFORM_ASSERT(virtualSpace_ < 800000);
48 		if (virtualSpace_ >= 0)
49 			virtualSpace = virtualSpace_;
50 	}
Add(int increment)51 	void Add(int increment) {
52 		position = position + increment;
53 	}
IsValid()54 	bool IsValid() const {
55 		return position >= 0;
56 	}
57 };
58 
59 // Ordered range to make drawing simpler
60 struct SelectionSegment {
61 	SelectionPosition start;
62 	SelectionPosition end;
SelectionSegmentSelectionSegment63 	SelectionSegment() : start(), end() {
64 	}
SelectionSegmentSelectionSegment65 	SelectionSegment(SelectionPosition a, SelectionPosition b) {
66 		if (a < b) {
67 			start = a;
68 			end = b;
69 		} else {
70 			start = b;
71 			end = a;
72 		}
73 	}
EmptySelectionSegment74 	bool Empty() const {
75 		return start == end;
76 	}
ExtendSelectionSegment77 	void Extend(SelectionPosition p) {
78 		if (start > p)
79 			start = p;
80 		if (end < p)
81 			end = p;
82 	}
83 };
84 
85 struct SelectionRange {
86 	SelectionPosition caret;
87 	SelectionPosition anchor;
88 
SelectionRangeSelectionRange89 	SelectionRange() : caret(), anchor() {
90 	}
SelectionRangeSelectionRange91 	SelectionRange(SelectionPosition single) : caret(single), anchor(single) {
92 	}
SelectionRangeSelectionRange93 	SelectionRange(int single) : caret(single), anchor(single) {
94 	}
SelectionRangeSelectionRange95 	SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) {
96 	}
SelectionRangeSelectionRange97 	SelectionRange(int caret_, int anchor_) : caret(caret_), anchor(anchor_) {
98 	}
EmptySelectionRange99 	bool Empty() const {
100 		return anchor == caret;
101 	}
102 	int Length() const;
103 	// int Width() const;	// Like Length but takes virtual space into account
104 	bool operator ==(const SelectionRange &other) const {
105 		return caret == other.caret && anchor == other.anchor;
106 	}
107 	bool operator <(const SelectionRange &other) const {
108 		return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor));
109 	}
ResetSelectionRange110 	void Reset() {
111 		anchor.Reset();
112 		caret.Reset();
113 	}
ClearVirtualSpaceSelectionRange114 	void ClearVirtualSpace() {
115 		anchor.SetVirtualSpace(0);
116 		caret.SetVirtualSpace(0);
117 	}
118 	bool Contains(int pos) const;
119 	bool Contains(SelectionPosition sp) const;
120 	bool ContainsCharacter(int posCharacter) const;
121 	SelectionSegment Intersect(SelectionSegment check) const;
StartSelectionRange122 	SelectionPosition Start() const {
123 		return (anchor < caret) ? anchor : caret;
124 	}
EndSelectionRange125 	SelectionPosition End() const {
126 		return (anchor < caret) ? caret : anchor;
127 	}
128 	bool Trim(SelectionRange range);
129 	// If range is all virtual collapse to start of virtual space
130 	void MinimizeVirtualSpace();
131 };
132 
133 class Selection {
134 	std::vector<SelectionRange> ranges;
135 	std::vector<SelectionRange> rangesSaved;
136 	SelectionRange rangeRectangular;
137 	size_t mainRange;
138 	bool moveExtends;
139 	bool tentativeMain;
140 public:
141 	enum selTypes { noSel, selStream, selRectangle, selLines, selThin };
142 	selTypes selType;
143 
144 	Selection();
145 	~Selection();
146 	bool IsRectangular() const;
147 	int MainCaret() const;
148 	int MainAnchor() const;
149 	SelectionRange &Rectangular();
150 	SelectionSegment Limits() const;
151 	// This is for when you want to move the caret in response to a
152 	// user direction command - for rectangular selections, use the range
153 	// that covers all selected text otherwise return the main selection.
154 	SelectionSegment LimitsForRectangularElseMain() const;
155 	size_t Count() const;
156 	size_t Main() const;
157 	void SetMain(size_t r);
158 	SelectionRange &Range(size_t r);
159 	SelectionRange &RangeMain();
160 	bool MoveExtends() const;
161 	void SetMoveExtends(bool moveExtends_);
162 	bool Empty() const;
163 	SelectionPosition Last() const;
164 	int Length() const;
165 	void MovePositions(bool insertion, int startChange, int length);
166 	void TrimSelection(SelectionRange range);
167 	void SetSelection(SelectionRange range);
168 	void AddSelection(SelectionRange range);
169 	void AddSelectionWithoutTrim(SelectionRange range);
170 	void TentativeSelection(SelectionRange range);
171 	void CommitTentative();
172 	int CharacterInSelection(int posCharacter) const;
173 	int InSelectionForEOL(int pos) const;
174 	int VirtualSpaceFor(int pos) const;
175 	void Clear();
176 	void RemoveDuplicates();
177 	void RotateMain();
Tentative()178 	bool Tentative() const { return tentativeMain; }
RangesCopy()179 	std::vector<SelectionRange> RangesCopy() const {
180 		return ranges;
181 	}
182 };
183 
184 #ifdef SCI_NAMESPACE
185 }
186 #endif
187 
188 #endif
189