1 // Scintilla source code edit control 2 /** @file CellBuffer.h 3 ** Manages the text of the document. 4 **/ 5 // Copyright 1998-2004 by Neil Hodgson <[email protected]> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #ifndef CELLBUFFER_H 9 #define CELLBUFFER_H 10 11 namespace Scintilla { 12 13 // Interface to per-line data that wants to see each line insertion and deletion 14 class PerLine { 15 public: 16 virtual ~PerLine() {} 17 virtual void Init()=0; 18 virtual void InsertLine(Sci::Line line)=0; 19 virtual void InsertLines(Sci::Line line, Sci::Line lines) = 0; 20 virtual void RemoveLine(Sci::Line line)=0; 21 }; 22 23 /** 24 * The line vector contains information about each of the lines in a cell buffer. 25 */ 26 class ILineVector; 27 28 enum actionType { insertAction, removeAction, startAction, containerAction }; 29 30 /** 31 * Actions are used to store all the information required to perform one undo/redo step. 32 */ 33 class Action { 34 public: 35 actionType at; 36 Sci::Position position; 37 std::unique_ptr<char[]> data; 38 Sci::Position lenData; 39 bool mayCoalesce; 40 41 Action() noexcept; 42 // Deleted so Action objects can not be copied. 43 Action(const Action &other) = delete; 44 Action &operator=(const Action &other) = delete; 45 Action &operator=(const Action &&other) = delete; 46 // Move constructor allows vector to be resized without reallocating. 47 Action(Action &&other) noexcept = default; 48 ~Action(); 49 void Create(actionType at_, Sci::Position position_=0, const char *data_=nullptr, Sci::Position lenData_=0, bool mayCoalesce_=true); 50 void Clear() noexcept; 51 }; 52 53 /** 54 * 55 */ 56 class UndoHistory { 57 std::vector<Action> actions; 58 int maxAction; 59 int currentAction; 60 int undoSequenceDepth; 61 int savePoint; 62 int tentativePoint; 63 64 void EnsureUndoRoom(); 65 66 public: 67 UndoHistory(); 68 // Deleted so UndoHistory objects can not be copied. 69 UndoHistory(const UndoHistory &) = delete; 70 UndoHistory(UndoHistory &&) = delete; 71 void operator=(const UndoHistory &) = delete; 72 void operator=(UndoHistory &&) = delete; 73 ~UndoHistory(); 74 75 const char *AppendAction(actionType at, Sci::Position position, const char *data, Sci::Position lengthData, bool &startSequence, bool mayCoalesce=true); 76 77 void BeginUndoAction(); 78 void EndUndoAction(); 79 void DropUndoSequence(); 80 void DeleteUndoHistory(); 81 82 /// The save point is a marker in the undo stack where the container has stated that 83 /// the buffer was saved. Undo and redo can move over the save point. 84 void SetSavePoint() noexcept; 85 bool IsSavePoint() const noexcept; 86 87 // Tentative actions are used for input composition so that it can be undone cleanly 88 void TentativeStart(); 89 void TentativeCommit(); 90 bool TentativeActive() const noexcept; 91 int TentativeSteps() noexcept; 92 93 /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is 94 /// called that many times. Similarly for redo. 95 bool CanUndo() const noexcept; 96 int StartUndo(); 97 const Action &GetUndoStep() const; 98 void CompletedUndoStep(); 99 bool CanRedo() const noexcept; 100 int StartRedo(); 101 const Action &GetRedoStep() const; 102 void CompletedRedoStep(); 103 }; 104 105 /** 106 * Holder for an expandable array of characters that supports undo and line markers. 107 * Based on article "Data Structures in a Bit-Mapped Text Editor" 108 * by Wilfred J. Hansen, Byte January 1987, page 183. 109 */ 110 class CellBuffer { 111 private: 112 bool hasStyles; 113 bool largeDocument; 114 SplitVector<char> substance; 115 SplitVector<char> style; 116 bool readOnly; 117 bool utf8Substance; 118 int utf8LineEnds; 119 120 bool collectingUndo; 121 UndoHistory uh; 122 123 std::unique_ptr<ILineVector> plv; 124 125 bool UTF8LineEndOverlaps(Sci::Position position) const noexcept; 126 bool UTF8IsCharacterBoundary(Sci::Position position) const; 127 void ResetLineEnds(); 128 void RecalculateIndexLineStarts(Sci::Line lineFirst, Sci::Line lineLast); 129 bool MaintainingLineCharacterIndex() const noexcept; 130 /// Actions without undo 131 void BasicInsertString(Sci::Position position, const char *s, Sci::Position insertLength); 132 void BasicDeleteChars(Sci::Position position, Sci::Position deleteLength); 133 134 public: 135 136 CellBuffer(bool hasStyles_, bool largeDocument_); 137 // Deleted so CellBuffer objects can not be copied. 138 CellBuffer(const CellBuffer &) = delete; 139 CellBuffer(CellBuffer &&) = delete; 140 void operator=(const CellBuffer &) = delete; 141 void operator=(CellBuffer &&) = delete; 142 ~CellBuffer(); 143 144 /// Retrieving positions outside the range of the buffer works and returns 0 145 char CharAt(Sci::Position position) const noexcept; 146 unsigned char UCharAt(Sci::Position position) const noexcept; 147 void GetCharRange(char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const; 148 char StyleAt(Sci::Position position) const noexcept; 149 void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const; 150 const char *BufferPointer(); 151 const char *RangePointer(Sci::Position position, Sci::Position rangeLength) noexcept; 152 Sci::Position GapPosition() const noexcept; 153 154 Sci::Position Length() const noexcept; 155 void Allocate(Sci::Position newSize); 156 void SetUTF8Substance(bool utf8Substance_) noexcept; 157 int GetLineEndTypes() const noexcept { return utf8LineEnds; } 158 void SetLineEndTypes(int utf8LineEnds_); 159 bool ContainsLineEnd(const char *s, Sci::Position length) const noexcept; 160 void SetPerLine(PerLine *pl) noexcept; 161 int LineCharacterIndex() const noexcept; 162 void AllocateLineCharacterIndex(int lineCharacterIndex); 163 void ReleaseLineCharacterIndex(int lineCharacterIndex); 164 Sci::Line Lines() const noexcept; 165 Sci::Position LineStart(Sci::Line line) const noexcept; 166 Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept; 167 Sci::Line LineFromPosition(Sci::Position pos) const noexcept; 168 Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept; 169 void InsertLine(Sci::Line line, Sci::Position position, bool lineStart); 170 void RemoveLine(Sci::Line line); 171 const char *InsertString(Sci::Position position, const char *s, Sci::Position insertLength, bool &startSequence); 172 173 /// Setting styles for positions outside the range of the buffer is safe and has no effect. 174 /// @return true if the style of a character is changed. 175 bool SetStyleAt(Sci::Position position, char styleValue) noexcept; 176 bool SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) noexcept; 177 178 const char *DeleteChars(Sci::Position position, Sci::Position deleteLength, bool &startSequence); 179 180 bool IsReadOnly() const noexcept; 181 void SetReadOnly(bool set) noexcept; 182 bool IsLarge() const noexcept; 183 bool HasStyles() const noexcept; 184 185 /// The save point is a marker in the undo stack where the container has stated that 186 /// the buffer was saved. Undo and redo can move over the save point. 187 void SetSavePoint(); 188 bool IsSavePoint() const noexcept; 189 190 void TentativeStart(); 191 void TentativeCommit(); 192 bool TentativeActive() const noexcept; 193 int TentativeSteps() noexcept; 194 195 bool SetUndoCollection(bool collectUndo); 196 bool IsCollectingUndo() const noexcept; 197 void BeginUndoAction(); 198 void EndUndoAction(); 199 void AddUndoAction(Sci::Position token, bool mayCoalesce); 200 void DeleteUndoHistory(); 201 202 /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is 203 /// called that many times. Similarly for redo. 204 bool CanUndo() const noexcept; 205 int StartUndo(); 206 const Action &GetUndoStep() const; 207 void PerformUndoStep(); 208 bool CanRedo() const noexcept; 209 int StartRedo(); 210 const Action &GetRedoStep() const; 211 void PerformRedoStep(); 212 }; 213 214 } 215 216 #endif 217