xref: /MusicPlayer2/scintilla/src/Document.h (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file Document.h
3*8af74909SZhong Yang  ** Text document that handles notifications, DBCS, styling, words and end of line.
4*8af74909SZhong Yang  **/
5*8af74909SZhong Yang // Copyright 1998-2011 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 DOCUMENT_H
9*8af74909SZhong Yang #define DOCUMENT_H
10*8af74909SZhong Yang 
11*8af74909SZhong Yang namespace Scintilla {
12*8af74909SZhong Yang 
13*8af74909SZhong Yang class DocWatcher;
14*8af74909SZhong Yang class DocModification;
15*8af74909SZhong Yang class Document;
16*8af74909SZhong Yang class LineMarkers;
17*8af74909SZhong Yang class LineLevels;
18*8af74909SZhong Yang class LineState;
19*8af74909SZhong Yang class LineAnnotation;
20*8af74909SZhong Yang 
21*8af74909SZhong Yang enum class EncodingFamily { eightBit, unicode, dbcs };
22*8af74909SZhong Yang 
23*8af74909SZhong Yang /**
24*8af74909SZhong Yang  * The range class represents a range of text in a document.
25*8af74909SZhong Yang  * The two values are not sorted as one end may be more significant than the other
26*8af74909SZhong Yang  * as is the case for the selection where the end position is the position of the caret.
27*8af74909SZhong Yang  * If either position is invalidPosition then the range is invalid and most operations will fail.
28*8af74909SZhong Yang  */
29*8af74909SZhong Yang class Range {
30*8af74909SZhong Yang public:
31*8af74909SZhong Yang 	Sci::Position start;
32*8af74909SZhong Yang 	Sci::Position end;
33*8af74909SZhong Yang 
34*8af74909SZhong Yang 	explicit Range(Sci::Position pos=0) noexcept :
start(pos)35*8af74909SZhong Yang 		start(pos), end(pos) {
36*8af74909SZhong Yang 	}
Range(Sci::Position start_,Sci::Position end_)37*8af74909SZhong Yang 	Range(Sci::Position start_, Sci::Position end_) noexcept :
38*8af74909SZhong Yang 		start(start_), end(end_) {
39*8af74909SZhong Yang 	}
40*8af74909SZhong Yang 
41*8af74909SZhong Yang 	bool operator==(const Range &other) const noexcept {
42*8af74909SZhong Yang 		return (start == other.start) && (end == other.end);
43*8af74909SZhong Yang 	}
44*8af74909SZhong Yang 
Valid()45*8af74909SZhong Yang 	bool Valid() const noexcept {
46*8af74909SZhong Yang 		return (start != Sci::invalidPosition) && (end != Sci::invalidPosition);
47*8af74909SZhong Yang 	}
48*8af74909SZhong Yang 
First()49*8af74909SZhong Yang 	Sci::Position First() const noexcept {
50*8af74909SZhong Yang 		return (start <= end) ? start : end;
51*8af74909SZhong Yang 	}
52*8af74909SZhong Yang 
Last()53*8af74909SZhong Yang 	Sci::Position Last() const noexcept {
54*8af74909SZhong Yang 		return (start > end) ? start : end;
55*8af74909SZhong Yang 	}
56*8af74909SZhong Yang 
57*8af74909SZhong Yang 	// Is the position within the range?
Contains(Sci::Position pos)58*8af74909SZhong Yang 	bool Contains(Sci::Position pos) const noexcept {
59*8af74909SZhong Yang 		if (start < end) {
60*8af74909SZhong Yang 			return (pos >= start && pos <= end);
61*8af74909SZhong Yang 		} else {
62*8af74909SZhong Yang 			return (pos <= start && pos >= end);
63*8af74909SZhong Yang 		}
64*8af74909SZhong Yang 	}
65*8af74909SZhong Yang 
66*8af74909SZhong Yang 	// Is the character after pos within the range?
ContainsCharacter(Sci::Position pos)67*8af74909SZhong Yang 	bool ContainsCharacter(Sci::Position pos) const noexcept {
68*8af74909SZhong Yang 		if (start < end) {
69*8af74909SZhong Yang 			return (pos >= start && pos < end);
70*8af74909SZhong Yang 		} else {
71*8af74909SZhong Yang 			return (pos < start && pos >= end);
72*8af74909SZhong Yang 		}
73*8af74909SZhong Yang 	}
74*8af74909SZhong Yang 
Contains(Range other)75*8af74909SZhong Yang 	bool Contains(Range other) const noexcept {
76*8af74909SZhong Yang 		return Contains(other.start) && Contains(other.end);
77*8af74909SZhong Yang 	}
78*8af74909SZhong Yang 
Overlaps(Range other)79*8af74909SZhong Yang 	bool Overlaps(Range other) const noexcept {
80*8af74909SZhong Yang 		return
81*8af74909SZhong Yang 		Contains(other.start) ||
82*8af74909SZhong Yang 		Contains(other.end) ||
83*8af74909SZhong Yang 		other.Contains(start) ||
84*8af74909SZhong Yang 		other.Contains(end);
85*8af74909SZhong Yang 	}
86*8af74909SZhong Yang };
87*8af74909SZhong Yang 
88*8af74909SZhong Yang /**
89*8af74909SZhong Yang  * Interface class for regular expression searching
90*8af74909SZhong Yang  */
91*8af74909SZhong Yang class RegexSearchBase {
92*8af74909SZhong Yang public:
~RegexSearchBase()93*8af74909SZhong Yang 	virtual ~RegexSearchBase() {}
94*8af74909SZhong Yang 
95*8af74909SZhong Yang 	virtual Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
96*8af74909SZhong Yang                         bool caseSensitive, bool word, bool wordStart, int flags, Sci::Position *length) = 0;
97*8af74909SZhong Yang 
98*8af74909SZhong Yang 	///@return String with the substitutions, must remain valid until the next call or destruction
99*8af74909SZhong Yang 	virtual const char *SubstituteByPosition(Document *doc, const char *text, Sci::Position *length) = 0;
100*8af74909SZhong Yang };
101*8af74909SZhong Yang 
102*8af74909SZhong Yang /// Factory function for RegexSearchBase
103*8af74909SZhong Yang extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);
104*8af74909SZhong Yang 
105*8af74909SZhong Yang struct StyledText {
106*8af74909SZhong Yang 	size_t length;
107*8af74909SZhong Yang 	const char *text;
108*8af74909SZhong Yang 	bool multipleStyles;
109*8af74909SZhong Yang 	size_t style;
110*8af74909SZhong Yang 	const unsigned char *styles;
StyledTextStyledText111*8af74909SZhong Yang 	StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) noexcept :
112*8af74909SZhong Yang 		length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
113*8af74909SZhong Yang 	}
114*8af74909SZhong Yang 	// Return number of bytes from start to before '\n' or end of text.
115*8af74909SZhong Yang 	// Return 1 when start is outside text
LineLengthStyledText116*8af74909SZhong Yang 	size_t LineLength(size_t start) const noexcept {
117*8af74909SZhong Yang 		size_t cur = start;
118*8af74909SZhong Yang 		while ((cur < length) && (text[cur] != '\n'))
119*8af74909SZhong Yang 			cur++;
120*8af74909SZhong Yang 		return cur-start;
121*8af74909SZhong Yang 	}
StyleAtStyledText122*8af74909SZhong Yang 	size_t StyleAt(size_t i) const noexcept {
123*8af74909SZhong Yang 		return multipleStyles ? styles[i] : style;
124*8af74909SZhong Yang 	}
125*8af74909SZhong Yang };
126*8af74909SZhong Yang 
127*8af74909SZhong Yang class HighlightDelimiter {
128*8af74909SZhong Yang public:
HighlightDelimiter()129*8af74909SZhong Yang 	HighlightDelimiter() noexcept : isEnabled(false) {
130*8af74909SZhong Yang 		Clear();
131*8af74909SZhong Yang 	}
132*8af74909SZhong Yang 
Clear()133*8af74909SZhong Yang 	void Clear() noexcept {
134*8af74909SZhong Yang 		beginFoldBlock = -1;
135*8af74909SZhong Yang 		endFoldBlock = -1;
136*8af74909SZhong Yang 		firstChangeableLineBefore = -1;
137*8af74909SZhong Yang 		firstChangeableLineAfter = -1;
138*8af74909SZhong Yang 	}
139*8af74909SZhong Yang 
NeedsDrawing(Sci::Line line)140*8af74909SZhong Yang 	bool NeedsDrawing(Sci::Line line) const noexcept {
141*8af74909SZhong Yang 		return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
142*8af74909SZhong Yang 	}
143*8af74909SZhong Yang 
IsFoldBlockHighlighted(Sci::Line line)144*8af74909SZhong Yang 	bool IsFoldBlockHighlighted(Sci::Line line) const noexcept {
145*8af74909SZhong Yang 		return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
146*8af74909SZhong Yang 	}
147*8af74909SZhong Yang 
IsHeadOfFoldBlock(Sci::Line line)148*8af74909SZhong Yang 	bool IsHeadOfFoldBlock(Sci::Line line) const noexcept {
149*8af74909SZhong Yang 		return beginFoldBlock == line && line < endFoldBlock;
150*8af74909SZhong Yang 	}
151*8af74909SZhong Yang 
IsBodyOfFoldBlock(Sci::Line line)152*8af74909SZhong Yang 	bool IsBodyOfFoldBlock(Sci::Line line) const noexcept {
153*8af74909SZhong Yang 		return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
154*8af74909SZhong Yang 	}
155*8af74909SZhong Yang 
IsTailOfFoldBlock(Sci::Line line)156*8af74909SZhong Yang 	bool IsTailOfFoldBlock(Sci::Line line) const noexcept {
157*8af74909SZhong Yang 		return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
158*8af74909SZhong Yang 	}
159*8af74909SZhong Yang 
160*8af74909SZhong Yang 	Sci::Line beginFoldBlock;	// Begin of current fold block
161*8af74909SZhong Yang 	Sci::Line endFoldBlock;	// End of current fold block
162*8af74909SZhong Yang 	Sci::Line firstChangeableLineBefore;	// First line that triggers repaint before starting line that determined current fold block
163*8af74909SZhong Yang 	Sci::Line firstChangeableLineAfter;	// First line that triggers repaint after starting line that determined current fold block
164*8af74909SZhong Yang 	bool isEnabled;
165*8af74909SZhong Yang };
166*8af74909SZhong Yang 
LevelNumber(int level)167*8af74909SZhong Yang constexpr int LevelNumber(int level) noexcept {
168*8af74909SZhong Yang 	return level & SC_FOLDLEVELNUMBERMASK;
169*8af74909SZhong Yang }
170*8af74909SZhong Yang 
171*8af74909SZhong Yang class LexInterface {
172*8af74909SZhong Yang protected:
173*8af74909SZhong Yang 	Document *pdoc;
174*8af74909SZhong Yang 	ILexer5 *instance;
175*8af74909SZhong Yang 	bool performingStyle;	///< Prevent reentrance
176*8af74909SZhong Yang public:
LexInterface(Document * pdoc_)177*8af74909SZhong Yang 	explicit LexInterface(Document *pdoc_) noexcept : pdoc(pdoc_), instance(nullptr), performingStyle(false) {
178*8af74909SZhong Yang 	}
~LexInterface()179*8af74909SZhong Yang 	virtual ~LexInterface() {
180*8af74909SZhong Yang 	}
181*8af74909SZhong Yang 	void Colourise(Sci::Position start, Sci::Position end);
182*8af74909SZhong Yang 	virtual int LineEndTypesSupported();
UseContainerLexing()183*8af74909SZhong Yang 	bool UseContainerLexing() const noexcept {
184*8af74909SZhong Yang 		return instance == nullptr;
185*8af74909SZhong Yang 	}
186*8af74909SZhong Yang };
187*8af74909SZhong Yang 
188*8af74909SZhong Yang struct RegexError : public std::runtime_error {
RegexErrorRegexError189*8af74909SZhong Yang 	RegexError() : std::runtime_error("regex failure") {}
190*8af74909SZhong Yang };
191*8af74909SZhong Yang 
192*8af74909SZhong Yang /**
193*8af74909SZhong Yang  * The ActionDuration class stores the average time taken for some action such as styling or
194*8af74909SZhong Yang  * wrapping a line. It is used to decide how many repetitions of that action can be performed
195*8af74909SZhong Yang  * on idle to maximize efficiency without affecting application responsiveness.
196*8af74909SZhong Yang  * The duration changes if the time for the action changes. For example, if a simple lexer is
197*8af74909SZhong Yang  * changed to a complex lexer. Changes are damped and clamped to avoid short periods of easy
198*8af74909SZhong Yang  * or difficult processing moving the value too far leading to inefficiency or poor user
199*8af74909SZhong Yang  * experience.
200*8af74909SZhong Yang  */
201*8af74909SZhong Yang 
202*8af74909SZhong Yang class ActionDuration {
203*8af74909SZhong Yang 	double duration;
204*8af74909SZhong Yang 	const double minDuration;
205*8af74909SZhong Yang 	const double maxDuration;
206*8af74909SZhong Yang public:
207*8af74909SZhong Yang 	ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept;
208*8af74909SZhong Yang 	void AddSample(size_t numberActions, double durationOfActions) noexcept;
209*8af74909SZhong Yang 	double Duration() const noexcept;
210*8af74909SZhong Yang };
211*8af74909SZhong Yang 
212*8af74909SZhong Yang /**
213*8af74909SZhong Yang  */
214*8af74909SZhong Yang class Document : PerLine, public IDocument, public ILoader {
215*8af74909SZhong Yang 
216*8af74909SZhong Yang public:
217*8af74909SZhong Yang 	/** Used to pair watcher pointer with user data. */
218*8af74909SZhong Yang 	struct WatcherWithUserData {
219*8af74909SZhong Yang 		DocWatcher *watcher;
220*8af74909SZhong Yang 		void *userData;
221*8af74909SZhong Yang 		WatcherWithUserData(DocWatcher *watcher_=nullptr, void *userData_=nullptr) noexcept :
watcherWatcherWithUserData222*8af74909SZhong Yang 			watcher(watcher_), userData(userData_) {
223*8af74909SZhong Yang 		}
224*8af74909SZhong Yang 		bool operator==(const WatcherWithUserData &other) const noexcept {
225*8af74909SZhong Yang 			return (watcher == other.watcher) && (userData == other.userData);
226*8af74909SZhong Yang 		}
227*8af74909SZhong Yang 	};
228*8af74909SZhong Yang 
229*8af74909SZhong Yang private:
230*8af74909SZhong Yang 	int refCount;
231*8af74909SZhong Yang 	CellBuffer cb;
232*8af74909SZhong Yang 	CharClassify charClass;
233*8af74909SZhong Yang 	CharacterCategoryMap charMap;
234*8af74909SZhong Yang 	std::unique_ptr<CaseFolder> pcf;
235*8af74909SZhong Yang 	Sci::Position endStyled;
236*8af74909SZhong Yang 	int styleClock;
237*8af74909SZhong Yang 	int enteredModification;
238*8af74909SZhong Yang 	int enteredStyling;
239*8af74909SZhong Yang 	int enteredReadOnlyCount;
240*8af74909SZhong Yang 
241*8af74909SZhong Yang 	bool insertionSet;
242*8af74909SZhong Yang 	std::string insertion;
243*8af74909SZhong Yang 
244*8af74909SZhong Yang 	std::vector<WatcherWithUserData> watchers;
245*8af74909SZhong Yang 
246*8af74909SZhong Yang 	// ldSize is not real data - it is for dimensions and loops
247*8af74909SZhong Yang 	enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldEOLAnnotation, ldSize };
248*8af74909SZhong Yang 	std::unique_ptr<PerLine> perLineData[ldSize];
249*8af74909SZhong Yang 	LineMarkers *Markers() const noexcept;
250*8af74909SZhong Yang 	LineLevels *Levels() const noexcept;
251*8af74909SZhong Yang 	LineState *States() const noexcept;
252*8af74909SZhong Yang 	LineAnnotation *Margins() const noexcept;
253*8af74909SZhong Yang 	LineAnnotation *Annotations() const noexcept;
254*8af74909SZhong Yang 	LineAnnotation *EOLAnnotations() const noexcept;
255*8af74909SZhong Yang 
256*8af74909SZhong Yang 	bool matchesValid;
257*8af74909SZhong Yang 	std::unique_ptr<RegexSearchBase> regex;
258*8af74909SZhong Yang 	std::unique_ptr<LexInterface> pli;
259*8af74909SZhong Yang 
260*8af74909SZhong Yang public:
261*8af74909SZhong Yang 
262*8af74909SZhong Yang 	struct CharacterExtracted {
263*8af74909SZhong Yang 		unsigned int character;
264*8af74909SZhong Yang 		unsigned int widthBytes;
CharacterExtractedCharacterExtracted265*8af74909SZhong Yang 		CharacterExtracted(unsigned int character_, unsigned int widthBytes_) noexcept :
266*8af74909SZhong Yang 			character(character_), widthBytes(widthBytes_) {
267*8af74909SZhong Yang 		}
268*8af74909SZhong Yang 		// For DBCS characters turn 2 bytes into an int
DBCSCharacterExtracted269*8af74909SZhong Yang 		static CharacterExtracted DBCS(unsigned char lead, unsigned char trail) noexcept {
270*8af74909SZhong Yang 			return CharacterExtracted((lead << 8) | trail, 2);
271*8af74909SZhong Yang 		}
272*8af74909SZhong Yang 	};
273*8af74909SZhong Yang 
274*8af74909SZhong Yang 	int eolMode;
275*8af74909SZhong Yang 	/// Can also be SC_CP_UTF8 to enable UTF-8 mode
276*8af74909SZhong Yang 	int dbcsCodePage;
277*8af74909SZhong Yang 	int lineEndBitSet;
278*8af74909SZhong Yang 	int tabInChars;
279*8af74909SZhong Yang 	int indentInChars;
280*8af74909SZhong Yang 	int actualIndentInChars;
281*8af74909SZhong Yang 	bool useTabs;
282*8af74909SZhong Yang 	bool tabIndents;
283*8af74909SZhong Yang 	bool backspaceUnindents;
284*8af74909SZhong Yang 	ActionDuration durationStyleOneLine;
285*8af74909SZhong Yang 
286*8af74909SZhong Yang 	std::unique_ptr<IDecorationList> decorations;
287*8af74909SZhong Yang 
288*8af74909SZhong Yang 	Document(int options);
289*8af74909SZhong Yang 	// Deleted so Document objects can not be copied.
290*8af74909SZhong Yang 	Document(const Document &) = delete;
291*8af74909SZhong Yang 	Document(Document &&) = delete;
292*8af74909SZhong Yang 	void operator=(const Document &) = delete;
293*8af74909SZhong Yang 	Document &operator=(Document &&) = delete;
294*8af74909SZhong Yang 	~Document() override;
295*8af74909SZhong Yang 
296*8af74909SZhong Yang 	int AddRef();
297*8af74909SZhong Yang 	int SCI_METHOD Release() override;
298*8af74909SZhong Yang 
299*8af74909SZhong Yang 	// From PerLine
300*8af74909SZhong Yang 	void Init() override;
301*8af74909SZhong Yang 	void InsertLine(Sci::Line line) override;
302*8af74909SZhong Yang 	void InsertLines(Sci::Line line, Sci::Line lines) override;
303*8af74909SZhong Yang 	void RemoveLine(Sci::Line line) override;
304*8af74909SZhong Yang 
305*8af74909SZhong Yang 	int LineEndTypesSupported() const;
306*8af74909SZhong Yang 	bool SetDBCSCodePage(int dbcsCodePage_);
GetLineEndTypesAllowed()307*8af74909SZhong Yang 	int GetLineEndTypesAllowed() const noexcept { return cb.GetLineEndTypes(); }
308*8af74909SZhong Yang 	bool SetLineEndTypesAllowed(int lineEndBitSet_);
GetLineEndTypesActive()309*8af74909SZhong Yang 	int GetLineEndTypesActive() const noexcept { return cb.GetLineEndTypes(); }
310*8af74909SZhong Yang 
Version()311*8af74909SZhong Yang 	int SCI_METHOD Version() const override {
312*8af74909SZhong Yang 		return dvRelease4;
313*8af74909SZhong Yang 	}
314*8af74909SZhong Yang 
315*8af74909SZhong Yang 	void SCI_METHOD SetErrorStatus(int status) override;
316*8af74909SZhong Yang 
317*8af74909SZhong Yang 	Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const override;
318*8af74909SZhong Yang 	Sci::Line SciLineFromPosition(Sci::Position pos) const noexcept;	// Avoids casting LineFromPosition
319*8af74909SZhong Yang 	Sci::Position ClampPositionIntoDocument(Sci::Position pos) const noexcept;
ContainsLineEnd(const char * s,Sci::Position length)320*8af74909SZhong Yang 	bool ContainsLineEnd(const char *s, Sci::Position length) const noexcept { return cb.ContainsLineEnd(s, length); }
321*8af74909SZhong Yang 	bool IsCrLf(Sci::Position pos) const noexcept;
322*8af74909SZhong Yang 	int LenChar(Sci::Position pos) const noexcept;
323*8af74909SZhong Yang 	bool InGoodUTF8(Sci::Position pos, Sci::Position &start, Sci::Position &end) const noexcept;
324*8af74909SZhong Yang 	Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const noexcept;
325*8af74909SZhong Yang 	Sci::Position NextPosition(Sci::Position pos, int moveDir) const noexcept;
326*8af74909SZhong Yang 	bool NextCharacter(Sci::Position &pos, int moveDir) const noexcept;	// Returns true if pos changed
327*8af74909SZhong Yang 	Document::CharacterExtracted CharacterAfter(Sci::Position position) const noexcept;
328*8af74909SZhong Yang 	Document::CharacterExtracted CharacterBefore(Sci::Position position) const noexcept;
329*8af74909SZhong Yang 	Sci_Position SCI_METHOD GetRelativePosition(Sci_Position positionStart, Sci_Position characterOffset) const override;
330*8af74909SZhong Yang 	Sci::Position GetRelativePositionUTF16(Sci::Position positionStart, Sci::Position characterOffset) const noexcept;
331*8af74909SZhong Yang 	int SCI_METHOD GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const override;
332*8af74909SZhong Yang 	int SCI_METHOD CodePage() const override;
333*8af74909SZhong Yang 	bool SCI_METHOD IsDBCSLeadByte(char ch) const override;
334*8af74909SZhong Yang 	bool IsDBCSLeadByteNoExcept(char ch) const noexcept;
335*8af74909SZhong Yang 	bool IsDBCSLeadByteInvalid(char ch) const noexcept;
336*8af74909SZhong Yang 	bool IsDBCSTrailByteInvalid(char ch) const noexcept;
337*8af74909SZhong Yang 	int DBCSDrawBytes(std::string_view text) const noexcept;
338*8af74909SZhong Yang 	int SafeSegment(const char *text, int length, int lengthSegment) const noexcept;
339*8af74909SZhong Yang 	EncodingFamily CodePageFamily() const noexcept;
340*8af74909SZhong Yang 
341*8af74909SZhong Yang 	// Gateways to modifying document
342*8af74909SZhong Yang 	void ModifiedAt(Sci::Position pos) noexcept;
343*8af74909SZhong Yang 	void CheckReadOnly();
344*8af74909SZhong Yang 	bool DeleteChars(Sci::Position pos, Sci::Position len);
345*8af74909SZhong Yang 	Sci::Position InsertString(Sci::Position position, const char *s, Sci::Position insertLength);
346*8af74909SZhong Yang 	void ChangeInsertion(const char *s, Sci::Position length);
347*8af74909SZhong Yang 	int SCI_METHOD AddData(const char *data, Sci_Position length) override;
348*8af74909SZhong Yang 	void * SCI_METHOD ConvertToDocument() override;
349*8af74909SZhong Yang 	Sci::Position Undo();
350*8af74909SZhong Yang 	Sci::Position Redo();
CanUndo()351*8af74909SZhong Yang 	bool CanUndo() const noexcept { return cb.CanUndo(); }
CanRedo()352*8af74909SZhong Yang 	bool CanRedo() const noexcept { return cb.CanRedo(); }
DeleteUndoHistory()353*8af74909SZhong Yang 	void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
SetUndoCollection(bool collectUndo)354*8af74909SZhong Yang 	bool SetUndoCollection(bool collectUndo) {
355*8af74909SZhong Yang 		return cb.SetUndoCollection(collectUndo);
356*8af74909SZhong Yang 	}
IsCollectingUndo()357*8af74909SZhong Yang 	bool IsCollectingUndo() const noexcept { return cb.IsCollectingUndo(); }
BeginUndoAction()358*8af74909SZhong Yang 	void BeginUndoAction() { cb.BeginUndoAction(); }
EndUndoAction()359*8af74909SZhong Yang 	void EndUndoAction() { cb.EndUndoAction(); }
AddUndoAction(Sci::Position token,bool mayCoalesce)360*8af74909SZhong Yang 	void AddUndoAction(Sci::Position token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
361*8af74909SZhong Yang 	void SetSavePoint();
IsSavePoint()362*8af74909SZhong Yang 	bool IsSavePoint() const noexcept { return cb.IsSavePoint(); }
363*8af74909SZhong Yang 
TentativeStart()364*8af74909SZhong Yang 	void TentativeStart() { cb.TentativeStart(); }
TentativeCommit()365*8af74909SZhong Yang 	void TentativeCommit() { cb.TentativeCommit(); }
366*8af74909SZhong Yang 	void TentativeUndo();
TentativeActive()367*8af74909SZhong Yang 	bool TentativeActive() const noexcept { return cb.TentativeActive(); }
368*8af74909SZhong Yang 
BufferPointer()369*8af74909SZhong Yang 	const char * SCI_METHOD BufferPointer() override { return cb.BufferPointer(); }
RangePointer(Sci::Position position,Sci::Position rangeLength)370*8af74909SZhong Yang 	const char *RangePointer(Sci::Position position, Sci::Position rangeLength) noexcept { return cb.RangePointer(position, rangeLength); }
GapPosition()371*8af74909SZhong Yang 	Sci::Position GapPosition() const noexcept { return cb.GapPosition(); }
372*8af74909SZhong Yang 
373*8af74909SZhong Yang 	int SCI_METHOD GetLineIndentation(Sci_Position line) override;
374*8af74909SZhong Yang 	Sci::Position SetLineIndentation(Sci::Line line, Sci::Position indent);
375*8af74909SZhong Yang 	Sci::Position GetLineIndentPosition(Sci::Line line) const;
376*8af74909SZhong Yang 	Sci::Position GetColumn(Sci::Position pos);
377*8af74909SZhong Yang 	Sci::Position CountCharacters(Sci::Position startPos, Sci::Position endPos) const noexcept;
378*8af74909SZhong Yang 	Sci::Position CountUTF16(Sci::Position startPos, Sci::Position endPos) const noexcept;
379*8af74909SZhong Yang 	Sci::Position FindColumn(Sci::Line line, Sci::Position column);
380*8af74909SZhong Yang 	void Indent(bool forwards, Sci::Line lineBottom, Sci::Line lineTop);
381*8af74909SZhong Yang 	static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted);
382*8af74909SZhong Yang 	void ConvertLineEnds(int eolModeSet);
SetReadOnly(bool set)383*8af74909SZhong Yang 	void SetReadOnly(bool set) { cb.SetReadOnly(set); }
IsReadOnly()384*8af74909SZhong Yang 	bool IsReadOnly() const noexcept { return cb.IsReadOnly(); }
IsLarge()385*8af74909SZhong Yang 	bool IsLarge() const noexcept { return cb.IsLarge(); }
386*8af74909SZhong Yang 	int Options() const noexcept;
387*8af74909SZhong Yang 
388*8af74909SZhong Yang 	void DelChar(Sci::Position pos);
389*8af74909SZhong Yang 	void DelCharBack(Sci::Position pos);
390*8af74909SZhong Yang 
CharAt(Sci::Position position)391*8af74909SZhong Yang 	char CharAt(Sci::Position position) const noexcept { return cb.CharAt(position); }
GetCharRange(char * buffer,Sci_Position position,Sci_Position lengthRetrieve)392*8af74909SZhong Yang 	void SCI_METHOD GetCharRange(char *buffer, Sci_Position position, Sci_Position lengthRetrieve) const override {
393*8af74909SZhong Yang 		cb.GetCharRange(buffer, position, lengthRetrieve);
394*8af74909SZhong Yang 	}
StyleAt(Sci_Position position)395*8af74909SZhong Yang 	char SCI_METHOD StyleAt(Sci_Position position) const override { return cb.StyleAt(position); }
StyleIndexAt(Sci_Position position)396*8af74909SZhong Yang 	int StyleIndexAt(Sci_Position position) const noexcept { return static_cast<unsigned char>(cb.StyleAt(position)); }
GetStyleRange(unsigned char * buffer,Sci::Position position,Sci::Position lengthRetrieve)397*8af74909SZhong Yang 	void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
398*8af74909SZhong Yang 		cb.GetStyleRange(buffer, position, lengthRetrieve);
399*8af74909SZhong Yang 	}
400*8af74909SZhong Yang 	int GetMark(Sci::Line line) const noexcept;
401*8af74909SZhong Yang 	Sci::Line MarkerNext(Sci::Line lineStart, int mask) const noexcept;
402*8af74909SZhong Yang 	int AddMark(Sci::Line line, int markerNum);
403*8af74909SZhong Yang 	void AddMarkSet(Sci::Line line, int valueSet);
404*8af74909SZhong Yang 	void DeleteMark(Sci::Line line, int markerNum);
405*8af74909SZhong Yang 	void DeleteMarkFromHandle(int markerHandle);
406*8af74909SZhong Yang 	void DeleteAllMarks(int markerNum);
407*8af74909SZhong Yang 	Sci::Line LineFromHandle(int markerHandle) const noexcept;
408*8af74909SZhong Yang 	int MarkerNumberFromLine(Sci::Line line, int which) const noexcept;
409*8af74909SZhong Yang 	int MarkerHandleFromLine(Sci::Line line, int which) const noexcept;
410*8af74909SZhong Yang 	Sci_Position SCI_METHOD LineStart(Sci_Position line) const override;
411*8af74909SZhong Yang 	bool IsLineStartPosition(Sci::Position position) const;
412*8af74909SZhong Yang 	Sci_Position SCI_METHOD LineEnd(Sci_Position line) const override;
413*8af74909SZhong Yang 	Sci::Position LineEndPosition(Sci::Position position) const;
414*8af74909SZhong Yang 	bool IsLineEndPosition(Sci::Position position) const;
415*8af74909SZhong Yang 	bool IsPositionInLineEnd(Sci::Position position) const;
416*8af74909SZhong Yang 	Sci::Position VCHomePosition(Sci::Position position) const;
417*8af74909SZhong Yang 	Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept;
418*8af74909SZhong Yang 	Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept;
419*8af74909SZhong Yang 
420*8af74909SZhong Yang 	int SCI_METHOD SetLevel(Sci_Position line, int level) override;
421*8af74909SZhong Yang 	int SCI_METHOD GetLevel(Sci_Position line) const override;
422*8af74909SZhong Yang 	void ClearLevels();
423*8af74909SZhong Yang 	Sci::Line GetLastChild(Sci::Line lineParent, int level=-1, Sci::Line lastLine=-1);
424*8af74909SZhong Yang 	Sci::Line GetFoldParent(Sci::Line line) const;
425*8af74909SZhong Yang 	void GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, Sci::Line line, Sci::Line lastLine);
426*8af74909SZhong Yang 
427*8af74909SZhong Yang 	Sci::Position ExtendWordSelect(Sci::Position pos, int delta, bool onlyWordCharacters=false) const;
428*8af74909SZhong Yang 	Sci::Position NextWordStart(Sci::Position pos, int delta) const;
429*8af74909SZhong Yang 	Sci::Position NextWordEnd(Sci::Position pos, int delta) const;
Length()430*8af74909SZhong Yang 	Sci_Position SCI_METHOD Length() const override { return cb.Length(); }
LengthNoExcept()431*8af74909SZhong Yang 	Sci::Position LengthNoExcept() const noexcept { return cb.Length(); }
Allocate(Sci::Position newSize)432*8af74909SZhong Yang 	void Allocate(Sci::Position newSize) { cb.Allocate(newSize); }
433*8af74909SZhong Yang 
434*8af74909SZhong Yang 	CharacterExtracted ExtractCharacter(Sci::Position position) const noexcept;
435*8af74909SZhong Yang 
436*8af74909SZhong Yang 	bool IsWordStartAt(Sci::Position pos) const;
437*8af74909SZhong Yang 	bool IsWordEndAt(Sci::Position pos) const;
438*8af74909SZhong Yang 	bool IsWordAt(Sci::Position start, Sci::Position end) const;
439*8af74909SZhong Yang 
440*8af74909SZhong Yang 	bool MatchesWordOptions(bool word, bool wordStart, Sci::Position pos, Sci::Position length) const;
441*8af74909SZhong Yang 	bool HasCaseFolder() const noexcept;
442*8af74909SZhong Yang 	void SetCaseFolder(CaseFolder *pcf_) noexcept;
443*8af74909SZhong Yang 	Sci::Position FindText(Sci::Position minPos, Sci::Position maxPos, const char *search, int flags, Sci::Position *length);
444*8af74909SZhong Yang 	const char *SubstituteByPosition(const char *text, Sci::Position *length);
445*8af74909SZhong Yang 	int LineCharacterIndex() const noexcept;
446*8af74909SZhong Yang 	void AllocateLineCharacterIndex(int lineCharacterIndex);
447*8af74909SZhong Yang 	void ReleaseLineCharacterIndex(int lineCharacterIndex);
448*8af74909SZhong Yang 	Sci::Line LinesTotal() const noexcept;
449*8af74909SZhong Yang 
450*8af74909SZhong Yang 	void SetDefaultCharClasses(bool includeWordClass);
451*8af74909SZhong Yang 	void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
452*8af74909SZhong Yang 	int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) const;
453*8af74909SZhong Yang 	void SetCharacterCategoryOptimization(int countCharacters);
454*8af74909SZhong Yang 	int CharacterCategoryOptimization() const noexcept;
455*8af74909SZhong Yang 	void SCI_METHOD StartStyling(Sci_Position position) override;
456*8af74909SZhong Yang 	bool SCI_METHOD SetStyleFor(Sci_Position length, char style) override;
457*8af74909SZhong Yang 	bool SCI_METHOD SetStyles(Sci_Position length, const char *styles) override;
GetEndStyled()458*8af74909SZhong Yang 	Sci::Position GetEndStyled() const noexcept { return endStyled; }
459*8af74909SZhong Yang 	void EnsureStyledTo(Sci::Position pos);
460*8af74909SZhong Yang 	void StyleToAdjustingLineDuration(Sci::Position pos);
461*8af74909SZhong Yang 	void LexerChanged();
GetStyleClock()462*8af74909SZhong Yang 	int GetStyleClock() const noexcept { return styleClock; }
463*8af74909SZhong Yang 	void IncrementStyleClock() noexcept;
464*8af74909SZhong Yang 	void SCI_METHOD DecorationSetCurrentIndicator(int indicator) override;
465*8af74909SZhong Yang 	void SCI_METHOD DecorationFillRange(Sci_Position position, int value, Sci_Position fillLength) override;
466*8af74909SZhong Yang 	LexInterface *GetLexInterface() const noexcept;
467*8af74909SZhong Yang 	void SetLexInterface(std::unique_ptr<LexInterface> pLexInterface) noexcept;
468*8af74909SZhong Yang 
469*8af74909SZhong Yang 	int SCI_METHOD SetLineState(Sci_Position line, int state) override;
470*8af74909SZhong Yang 	int SCI_METHOD GetLineState(Sci_Position line) const override;
471*8af74909SZhong Yang 	Sci::Line GetMaxLineState() const noexcept;
472*8af74909SZhong Yang 	void SCI_METHOD ChangeLexerState(Sci_Position start, Sci_Position end) override;
473*8af74909SZhong Yang 
474*8af74909SZhong Yang 	StyledText MarginStyledText(Sci::Line line) const noexcept;
475*8af74909SZhong Yang 	void MarginSetStyle(Sci::Line line, int style);
476*8af74909SZhong Yang 	void MarginSetStyles(Sci::Line line, const unsigned char *styles);
477*8af74909SZhong Yang 	void MarginSetText(Sci::Line line, const char *text);
478*8af74909SZhong Yang 	void MarginClearAll();
479*8af74909SZhong Yang 
480*8af74909SZhong Yang 	StyledText AnnotationStyledText(Sci::Line line) const noexcept;
481*8af74909SZhong Yang 	void AnnotationSetText(Sci::Line line, const char *text);
482*8af74909SZhong Yang 	void AnnotationSetStyle(Sci::Line line, int style);
483*8af74909SZhong Yang 	void AnnotationSetStyles(Sci::Line line, const unsigned char *styles);
484*8af74909SZhong Yang 	int AnnotationLines(Sci::Line line) const noexcept;
485*8af74909SZhong Yang 	void AnnotationClearAll();
486*8af74909SZhong Yang 
487*8af74909SZhong Yang 	StyledText EOLAnnotationStyledText(Sci::Line line) const noexcept;
488*8af74909SZhong Yang 	void EOLAnnotationSetStyle(Sci::Line line, int style);
489*8af74909SZhong Yang 	void EOLAnnotationSetText(Sci::Line line, const char *text);
490*8af74909SZhong Yang 	void EOLAnnotationClearAll();
491*8af74909SZhong Yang 
492*8af74909SZhong Yang 	bool AddWatcher(DocWatcher *watcher, void *userData);
493*8af74909SZhong Yang 	bool RemoveWatcher(DocWatcher *watcher, void *userData);
494*8af74909SZhong Yang 
495*8af74909SZhong Yang 	CharClassify::cc WordCharacterClass(unsigned int ch) const;
496*8af74909SZhong Yang 	bool IsWordPartSeparator(unsigned int ch) const;
497*8af74909SZhong Yang 	Sci::Position WordPartLeft(Sci::Position pos) const;
498*8af74909SZhong Yang 	Sci::Position WordPartRight(Sci::Position pos) const;
499*8af74909SZhong Yang 	Sci::Position ExtendStyleRange(Sci::Position pos, int delta, bool singleLine) noexcept;
500*8af74909SZhong Yang 	bool IsWhiteLine(Sci::Line line) const;
501*8af74909SZhong Yang 	Sci::Position ParaUp(Sci::Position pos) const;
502*8af74909SZhong Yang 	Sci::Position ParaDown(Sci::Position pos) const;
IndentSize()503*8af74909SZhong Yang 	int IndentSize() const noexcept { return actualIndentInChars; }
504*8af74909SZhong Yang 	Sci::Position BraceMatch(Sci::Position position, Sci::Position maxReStyle, Sci::Position startPos, bool useStartPos) noexcept;
505*8af74909SZhong Yang 
506*8af74909SZhong Yang private:
507*8af74909SZhong Yang 	void NotifyModifyAttempt();
508*8af74909SZhong Yang 	void NotifySavePoint(bool atSavePoint);
509*8af74909SZhong Yang 	void NotifyModified(DocModification mh);
510*8af74909SZhong Yang };
511*8af74909SZhong Yang 
512*8af74909SZhong Yang class UndoGroup {
513*8af74909SZhong Yang 	Document *pdoc;
514*8af74909SZhong Yang 	bool groupNeeded;
515*8af74909SZhong Yang public:
516*8af74909SZhong Yang 	UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
pdoc(pdoc_)517*8af74909SZhong Yang 		pdoc(pdoc_), groupNeeded(groupNeeded_) {
518*8af74909SZhong Yang 		if (groupNeeded) {
519*8af74909SZhong Yang 			pdoc->BeginUndoAction();
520*8af74909SZhong Yang 		}
521*8af74909SZhong Yang 	}
522*8af74909SZhong Yang 	// Deleted so UndoGroup objects can not be copied.
523*8af74909SZhong Yang 	UndoGroup(const UndoGroup &) = delete;
524*8af74909SZhong Yang 	UndoGroup(UndoGroup &&) = delete;
525*8af74909SZhong Yang 	void operator=(const UndoGroup &) = delete;
526*8af74909SZhong Yang 	UndoGroup &operator=(UndoGroup &&) = delete;
~UndoGroup()527*8af74909SZhong Yang 	~UndoGroup() {
528*8af74909SZhong Yang 		if (groupNeeded) {
529*8af74909SZhong Yang 			pdoc->EndUndoAction();
530*8af74909SZhong Yang 		}
531*8af74909SZhong Yang 	}
Needed()532*8af74909SZhong Yang 	bool Needed() const noexcept {
533*8af74909SZhong Yang 		return groupNeeded;
534*8af74909SZhong Yang 	}
535*8af74909SZhong Yang };
536*8af74909SZhong Yang 
537*8af74909SZhong Yang 
538*8af74909SZhong Yang /**
539*8af74909SZhong Yang  * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
540*8af74909SZhong Yang  * scope of the change.
541*8af74909SZhong Yang  * If the DocWatcher is a document view then this can be used to optimise screen updating.
542*8af74909SZhong Yang  */
543*8af74909SZhong Yang class DocModification {
544*8af74909SZhong Yang public:
545*8af74909SZhong Yang 	int modificationType;
546*8af74909SZhong Yang 	Sci::Position position;
547*8af74909SZhong Yang 	Sci::Position length;
548*8af74909SZhong Yang 	Sci::Line linesAdded;	/**< Negative if lines deleted. */
549*8af74909SZhong Yang 	const char *text;	/**< Only valid for changes to text, not for changes to style. */
550*8af74909SZhong Yang 	Sci::Line line;
551*8af74909SZhong Yang 	int foldLevelNow;
552*8af74909SZhong Yang 	int foldLevelPrev;
553*8af74909SZhong Yang 	Sci::Line annotationLinesAdded;
554*8af74909SZhong Yang 	Sci::Position token;
555*8af74909SZhong Yang 
556*8af74909SZhong Yang 	DocModification(int modificationType_, Sci::Position position_=0, Sci::Position length_=0,
557*8af74909SZhong Yang 		Sci::Line linesAdded_=0, const char *text_=nullptr, Sci::Line line_=0) noexcept :
modificationType(modificationType_)558*8af74909SZhong Yang 		modificationType(modificationType_),
559*8af74909SZhong Yang 		position(position_),
560*8af74909SZhong Yang 		length(length_),
561*8af74909SZhong Yang 		linesAdded(linesAdded_),
562*8af74909SZhong Yang 		text(text_),
563*8af74909SZhong Yang 		line(line_),
564*8af74909SZhong Yang 		foldLevelNow(0),
565*8af74909SZhong Yang 		foldLevelPrev(0),
566*8af74909SZhong Yang 		annotationLinesAdded(0),
567*8af74909SZhong Yang 		token(0) {}
568*8af74909SZhong Yang 
569*8af74909SZhong Yang 	DocModification(int modificationType_, const Action &act, Sci::Line linesAdded_=0) noexcept :
modificationType(modificationType_)570*8af74909SZhong Yang 		modificationType(modificationType_),
571*8af74909SZhong Yang 		position(act.position),
572*8af74909SZhong Yang 		length(act.lenData),
573*8af74909SZhong Yang 		linesAdded(linesAdded_),
574*8af74909SZhong Yang 		text(act.data.get()),
575*8af74909SZhong Yang 		line(0),
576*8af74909SZhong Yang 		foldLevelNow(0),
577*8af74909SZhong Yang 		foldLevelPrev(0),
578*8af74909SZhong Yang 		annotationLinesAdded(0),
579*8af74909SZhong Yang 		token(0) {}
580*8af74909SZhong Yang };
581*8af74909SZhong Yang 
582*8af74909SZhong Yang /**
583*8af74909SZhong Yang  * A class that wants to receive notifications from a Document must be derived from DocWatcher
584*8af74909SZhong Yang  * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
585*8af74909SZhong Yang  */
586*8af74909SZhong Yang class DocWatcher {
587*8af74909SZhong Yang public:
~DocWatcher()588*8af74909SZhong Yang 	virtual ~DocWatcher() {}
589*8af74909SZhong Yang 
590*8af74909SZhong Yang 	virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
591*8af74909SZhong Yang 	virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
592*8af74909SZhong Yang 	virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
593*8af74909SZhong Yang 	virtual void NotifyDeleted(Document *doc, void *userData) noexcept = 0;
594*8af74909SZhong Yang 	virtual void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) = 0;
595*8af74909SZhong Yang 	virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
596*8af74909SZhong Yang 	virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;
597*8af74909SZhong Yang };
598*8af74909SZhong Yang 
599*8af74909SZhong Yang }
600*8af74909SZhong Yang 
601*8af74909SZhong Yang #endif
602