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 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;
GetLineEndTypes()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