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