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