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