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