1 // Scintilla source code edit control 2 /** @file Selection.h 3 ** Classes maintaining the selection. 4 **/ 5 // Copyright 2009 by Neil Hodgson <[email protected]> 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