Fix typos
[TortoiseGit.git] / ext / scintilla / src / Document.h
blobda3736cc6c6daeb661cb7c3da31569fa4ab41945
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.
8 #ifndef DOCUMENT_H
9 #define DOCUMENT_H
11 namespace Scintilla::Internal {
13 class DocWatcher;
14 class DocModification;
15 class Document;
16 class LineMarkers;
17 class LineLevels;
18 class LineState;
19 class LineAnnotation;
21 enum class EncodingFamily { eightBit, unicode, dbcs };
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.
29 class Range {
30 public:
31 Sci::Position start;
32 Sci::Position end;
34 explicit Range(Sci::Position pos=0) noexcept :
35 start(pos), end(pos) {
37 Range(Sci::Position start_, Sci::Position end_) noexcept :
38 start(start_), end(end_) {
41 bool operator==(const Range &other) const noexcept {
42 return (start == other.start) && (end == other.end);
45 bool Valid() const noexcept {
46 return (start != Sci::invalidPosition) && (end != Sci::invalidPosition);
49 [[nodiscard]] bool Empty() const noexcept {
50 return start == end;
53 [[nodiscard]] Sci::Position Length() const noexcept {
54 return (start <= end) ? (end - start) : (start - end);
57 Sci::Position First() const noexcept {
58 return (start <= end) ? start : end;
61 Sci::Position Last() const noexcept {
62 return (start > end) ? start : end;
65 // Is the position within the range?
66 bool Contains(Sci::Position pos) const noexcept {
67 if (start < end) {
68 return (pos >= start && pos <= end);
69 } else {
70 return (pos <= start && pos >= end);
74 // Is the character after pos within the range?
75 bool ContainsCharacter(Sci::Position pos) const noexcept {
76 if (start < end) {
77 return (pos >= start && pos < end);
78 } else {
79 return (pos < start && pos >= end);
83 bool Contains(Range other) const noexcept {
84 return Contains(other.start) && Contains(other.end);
87 bool Overlaps(Range other) const noexcept {
88 return
89 Contains(other.start) ||
90 Contains(other.end) ||
91 other.Contains(start) ||
92 other.Contains(end);
96 /**
97 * Interface class for regular expression searching
99 class RegexSearchBase {
100 public:
101 virtual ~RegexSearchBase() = default;
103 virtual Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
104 bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) = 0;
106 ///@return String with the substitutions, must remain valid until the next call or destruction
107 virtual const char *SubstituteByPosition(Document *doc, const char *text, Sci::Position *length) = 0;
110 /// Factory function for RegexSearchBase
111 extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);
113 struct StyledText {
114 size_t length;
115 const char *text;
116 bool multipleStyles;
117 size_t style;
118 const unsigned char *styles;
119 StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) noexcept :
120 length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
122 // Return number of bytes from start to before '\n' or end of text.
123 // Return 1 when start is outside text
124 size_t LineLength(size_t start) const noexcept {
125 size_t cur = start;
126 while ((cur < length) && (text[cur] != '\n'))
127 cur++;
128 return cur-start;
130 size_t StyleAt(size_t i) const noexcept {
131 return multipleStyles ? styles[i] : style;
135 class HighlightDelimiter {
136 public:
137 HighlightDelimiter() noexcept : isEnabled(false) {
138 Clear();
141 void Clear() noexcept {
142 beginFoldBlock = -1;
143 endFoldBlock = -1;
144 firstChangeableLineBefore = -1;
145 firstChangeableLineAfter = -1;
148 bool NeedsDrawing(Sci::Line line) const noexcept {
149 return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
152 bool IsFoldBlockHighlighted(Sci::Line line) const noexcept {
153 return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
156 bool IsHeadOfFoldBlock(Sci::Line line) const noexcept {
157 return beginFoldBlock == line && line < endFoldBlock;
160 bool IsBodyOfFoldBlock(Sci::Line line) const noexcept {
161 return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
164 bool IsTailOfFoldBlock(Sci::Line line) const noexcept {
165 return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
168 Sci::Line beginFoldBlock; // Begin of current fold block
169 Sci::Line endFoldBlock; // End of current fold block
170 Sci::Line firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block
171 Sci::Line firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block
172 bool isEnabled;
175 struct LexerReleaser {
176 // Called by unique_ptr to destroy/free the Resource
177 void operator()(Scintilla::ILexer5 *pLexer) noexcept {
178 if (pLexer) {
179 try {
180 pLexer->Release();
181 } catch (...) {
182 // ILexer5::Release must not throw, ignore if it does.
188 using LexerInstance = std::unique_ptr<Scintilla::ILexer5, LexerReleaser>;
190 // LexInterface defines the interface to ILexer used in Document.
191 // The LexState subclass is actually created and that is used within ScintillaBase
192 // to provide more methods that are exposed through Scintilla's external API.
193 class LexInterface {
194 protected:
195 Document *pdoc;
196 LexerInstance instance;
197 bool performingStyle; ///< Prevent reentrance
198 public:
199 explicit LexInterface(Document *pdoc_) noexcept;
200 // Deleted so LexInterface objects can not be copied.
201 LexInterface(const LexInterface &) = delete;
202 LexInterface(LexInterface &&) = delete;
203 LexInterface &operator=(const LexInterface &) = delete;
204 LexInterface &operator=(LexInterface &&) = delete;
205 virtual ~LexInterface() noexcept;
206 void SetInstance(ILexer5 *instance_) noexcept;
207 void Colourise(Sci::Position start, Sci::Position end);
208 virtual Scintilla::LineEndType LineEndTypesSupported();
209 bool UseContainerLexing() const noexcept;
212 struct RegexError : public std::runtime_error {
213 RegexError() : std::runtime_error("regex failure") {}
217 * The ActionDuration class stores the average time taken for some action such as styling or
218 * wrapping a line. It is used to decide how many repetitions of that action can be performed
219 * on idle to maximize efficiency without affecting application responsiveness.
220 * The duration changes if the time for the action changes. For example, if a simple lexer is
221 * changed to a complex lexer. Changes are damped and clamped to avoid short periods of easy
222 * or difficult processing moving the value too far leading to inefficiency or poor user
223 * experience.
226 class ActionDuration {
227 double duration;
228 const double minDuration;
229 const double maxDuration;
230 public:
231 ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept;
232 void AddSample(size_t numberActions, double durationOfActions) noexcept;
233 double Duration() const noexcept;
234 size_t ActionsInAllowedTime(double secondsAllowed) const noexcept;
238 * A whole character (code point) with a value and width in bytes.
239 * For UTF-8, the value is the code point value.
240 * For DBCS, its jamming the lead and trail bytes together.
241 * For 8 bit encodings, is just the byte value.
243 struct CharacterExtracted {
244 unsigned int character;
245 unsigned int widthBytes;
247 CharacterExtracted(unsigned int character_, unsigned int widthBytes_) noexcept :
248 character(character_), widthBytes(widthBytes_) {
251 // For UTF-8:
252 CharacterExtracted(const unsigned char *charBytes, size_t widthCharBytes) noexcept;
254 // For DBCS characters turn 2 bytes into an int
255 static CharacterExtracted DBCS(unsigned char lead, unsigned char trail) noexcept {
256 return CharacterExtracted((lead << 8) | trail, 2);
262 class Document : PerLine, public Scintilla::IDocument, public Scintilla::ILoader, public Scintilla::IDocumentEditable {
264 public:
265 /** Used to pair watcher pointer with user data. */
266 struct WatcherWithUserData {
267 DocWatcher *watcher;
268 void *userData;
269 WatcherWithUserData(DocWatcher *watcher_=nullptr, void *userData_=nullptr) noexcept :
270 watcher(watcher_), userData(userData_) {
272 bool operator==(const WatcherWithUserData &other) const noexcept {
273 return (watcher == other.watcher) && (userData == other.userData);
277 private:
278 int refCount;
279 CellBuffer cb;
280 CharClassify charClass;
281 CharacterCategoryMap charMap;
282 std::unique_ptr<CaseFolder> pcf;
283 Sci::Position endStyled;
284 int styleClock;
285 int enteredModification;
286 int enteredStyling;
287 int enteredReadOnlyCount;
289 bool insertionSet;
290 std::string insertion;
292 std::vector<WatcherWithUserData> watchers;
294 // ldSize is not real data - it is for dimensions and loops
295 enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldEOLAnnotation, ldSize };
296 std::unique_ptr<PerLine> perLineData[ldSize];
297 LineMarkers *Markers() const noexcept;
298 LineLevels *Levels() const noexcept;
299 LineState *States() const noexcept;
300 LineAnnotation *Margins() const noexcept;
301 LineAnnotation *Annotations() const noexcept;
302 LineAnnotation *EOLAnnotations() const noexcept;
304 bool matchesValid;
305 std::unique_ptr<RegexSearchBase> regex;
306 std::unique_ptr<LexInterface> pli;
308 public:
310 Scintilla::EndOfLine eolMode;
311 /// Can also be SC_CP_UTF8 to enable UTF-8 mode
312 int dbcsCodePage;
313 Scintilla::LineEndType lineEndBitSet;
314 int tabInChars;
315 int indentInChars;
316 int actualIndentInChars;
317 bool useTabs;
318 bool tabIndents;
319 bool backspaceUnindents;
320 ActionDuration durationStyleOneByte;
322 std::unique_ptr<IDecorationList> decorations;
324 Document(Scintilla::DocumentOption options);
325 // Deleted so Document objects can not be copied.
326 Document(const Document &) = delete;
327 Document(Document &&) = delete;
328 void operator=(const Document &) = delete;
329 Document &operator=(Document &&) = delete;
330 ~Document() override;
332 int SCI_METHOD AddRef() noexcept override;
333 int SCI_METHOD Release() override;
335 // From PerLine
336 void Init() override;
337 void InsertLine(Sci::Line line) override;
338 void InsertLines(Sci::Line line, Sci::Line lines) override;
339 void RemoveLine(Sci::Line line) override;
341 Scintilla::LineEndType LineEndTypesSupported() const;
342 bool SetDBCSCodePage(int dbcsCodePage_);
343 Scintilla::LineEndType GetLineEndTypesAllowed() const noexcept { return cb.GetLineEndTypes(); }
344 bool SetLineEndTypesAllowed(Scintilla::LineEndType lineEndBitSet_);
345 Scintilla::LineEndType GetLineEndTypesActive() const noexcept { return cb.GetLineEndTypes(); }
347 int SCI_METHOD Version() const override {
348 return Scintilla::dvRelease4;
350 int SCI_METHOD DEVersion() const noexcept override;
352 void SCI_METHOD SetErrorStatus(int status) override;
354 Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const override;
355 Sci::Line SciLineFromPosition(Sci::Position pos) const noexcept; // Avoids casting LineFromPosition
356 Sci::Position ClampPositionIntoDocument(Sci::Position pos) const noexcept;
357 bool ContainsLineEnd(const char *s, Sci::Position length) const noexcept { return cb.ContainsLineEnd(s, length); }
358 bool IsCrLf(Sci::Position pos) const noexcept;
359 int LenChar(Sci::Position pos) const noexcept;
360 bool InGoodUTF8(Sci::Position pos, Sci::Position &start, Sci::Position &end) const noexcept;
361 Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const noexcept;
362 Sci::Position NextPosition(Sci::Position pos, int moveDir) const noexcept;
363 bool NextCharacter(Sci::Position &pos, int moveDir) const noexcept; // Returns true if pos changed
364 CharacterExtracted CharacterAfter(Sci::Position position) const noexcept;
365 CharacterExtracted CharacterBefore(Sci::Position position) const noexcept;
366 Sci_Position SCI_METHOD GetRelativePosition(Sci_Position positionStart, Sci_Position characterOffset) const override;
367 Sci::Position GetRelativePositionUTF16(Sci::Position positionStart, Sci::Position characterOffset) const noexcept;
368 int SCI_METHOD GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const override;
369 int SCI_METHOD CodePage() const override;
370 bool SCI_METHOD IsDBCSLeadByte(char ch) const override;
371 bool IsDBCSLeadByteNoExcept(char ch) const noexcept;
372 bool IsDBCSTrailByteNoExcept(char ch) const noexcept;
373 int DBCSDrawBytes(std::string_view text) const noexcept;
374 bool IsDBCSDualByteAt(Sci::Position pos) const noexcept;
375 size_t SafeSegment(std::string_view text) const noexcept;
376 EncodingFamily CodePageFamily() const noexcept;
378 // Gateways to modifying document
379 void ModifiedAt(Sci::Position pos) noexcept;
380 void CheckReadOnly();
381 void TrimReplacement(std::string_view &text, Range &range) const noexcept;
382 bool DeleteChars(Sci::Position pos, Sci::Position len);
383 Sci::Position InsertString(Sci::Position position, const char *s, Sci::Position insertLength);
384 Sci::Position InsertString(Sci::Position position, std::string_view sv);
385 void ChangeInsertion(const char *s, Sci::Position length);
386 int SCI_METHOD AddData(const char *data, Sci_Position length) override;
387 IDocumentEditable *AsDocumentEditable() noexcept;
388 void *SCI_METHOD ConvertToDocument() override;
389 Sci::Position Undo();
390 Sci::Position Redo();
391 bool CanUndo() const noexcept { return cb.CanUndo(); }
392 bool CanRedo() const noexcept { return cb.CanRedo(); }
393 void DeleteUndoHistory() noexcept { cb.DeleteUndoHistory(); }
394 bool SetUndoCollection(bool collectUndo) noexcept {
395 return cb.SetUndoCollection(collectUndo);
397 bool IsCollectingUndo() const noexcept { return cb.IsCollectingUndo(); }
398 void BeginUndoAction(bool coalesceWithPrior=false) noexcept { cb.BeginUndoAction(coalesceWithPrior); }
399 void EndUndoAction() noexcept { cb.EndUndoAction(); }
400 void AddUndoAction(Sci::Position token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
401 void SetSavePoint();
402 bool IsSavePoint() const noexcept { return cb.IsSavePoint(); }
404 void TentativeStart() noexcept { cb.TentativeStart(); }
405 void TentativeCommit() noexcept { cb.TentativeCommit(); }
406 void TentativeUndo();
407 bool TentativeActive() const noexcept { return cb.TentativeActive(); }
409 int UndoActions() const noexcept;
410 void SetUndoSavePoint(int action) noexcept;
411 int UndoSavePoint() const noexcept;
412 void SetUndoDetach(int action) noexcept;
413 int UndoDetach() const noexcept;
414 void SetUndoTentative(int action) noexcept;
415 int UndoTentative() const noexcept;
416 void SetUndoCurrent(int action);
417 int UndoCurrent() const noexcept;
418 int UndoActionType(int action) const noexcept;
419 Sci::Position UndoActionPosition(int action) const noexcept;
420 std::string_view UndoActionText(int action) const noexcept;
421 void PushUndoActionType(int type, Sci::Position position);
422 void ChangeLastUndoActionText(size_t length, const char *text);
424 void ChangeHistorySet(bool set) { cb.ChangeHistorySet(set); }
425 [[nodiscard]] int EditionAt(Sci::Position pos) const noexcept { return cb.EditionAt(pos); }
426 [[nodiscard]] Sci::Position EditionEndRun(Sci::Position pos) const noexcept { return cb.EditionEndRun(pos); }
427 [[nodiscard]] unsigned int EditionDeletesAt(Sci::Position pos) const noexcept { return cb.EditionDeletesAt(pos); }
428 [[nodiscard]] Sci::Position EditionNextDelete(Sci::Position pos) const noexcept { return cb.EditionNextDelete(pos); }
430 const char *SCI_METHOD BufferPointer() override { return cb.BufferPointer(); }
431 const char *RangePointer(Sci::Position position, Sci::Position rangeLength) noexcept { return cb.RangePointer(position, rangeLength); }
432 Sci::Position GapPosition() const noexcept { return cb.GapPosition(); }
434 int SCI_METHOD GetLineIndentation(Sci_Position line) override;
435 Sci::Position SetLineIndentation(Sci::Line line, Sci::Position indent);
436 Sci::Position GetLineIndentPosition(Sci::Line line) const;
437 Sci::Position GetColumn(Sci::Position pos) const;
438 Sci::Position CountCharacters(Sci::Position startPos, Sci::Position endPos) const noexcept;
439 Sci::Position CountUTF16(Sci::Position startPos, Sci::Position endPos) const noexcept;
440 Sci::Position FindColumn(Sci::Line line, Sci::Position column);
441 void Indent(bool forwards, Sci::Line lineBottom, Sci::Line lineTop);
442 static std::string TransformLineEnds(const char *s, size_t len, Scintilla::EndOfLine eolModeWanted);
443 void ConvertLineEnds(Scintilla::EndOfLine eolModeSet);
444 std::string_view EOLString() const noexcept;
445 void SetReadOnly(bool set) noexcept { cb.SetReadOnly(set); }
446 bool IsReadOnly() const noexcept { return cb.IsReadOnly(); }
447 bool IsLarge() const noexcept { return cb.IsLarge(); }
448 Scintilla::DocumentOption Options() const noexcept;
450 void DelChar(Sci::Position pos);
451 void DelCharBack(Sci::Position pos);
453 char CharAt(Sci::Position position) const noexcept { return cb.CharAt(position); }
454 void SCI_METHOD GetCharRange(char *buffer, Sci_Position position, Sci_Position lengthRetrieve) const override {
455 cb.GetCharRange(buffer, position, lengthRetrieve);
457 char SCI_METHOD StyleAt(Sci_Position position) const override { return cb.StyleAt(position); }
458 char StyleAtNoExcept(Sci_Position position) const noexcept { return cb.StyleAt(position); }
459 int StyleIndexAt(Sci_Position position) const noexcept { return static_cast<unsigned char>(cb.StyleAt(position)); }
460 void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
461 cb.GetStyleRange(buffer, position, lengthRetrieve);
463 int GetMark(Sci::Line line, bool includeChangeHistory) const;
464 Sci::Line MarkerNext(Sci::Line lineStart, int mask) const noexcept;
465 int AddMark(Sci::Line line, int markerNum);
466 void AddMarkSet(Sci::Line line, int valueSet);
467 void DeleteMark(Sci::Line line, int markerNum);
468 void DeleteMarkFromHandle(int markerHandle);
469 void DeleteAllMarks(int markerNum);
470 Sci::Line LineFromHandle(int markerHandle) const noexcept;
471 int MarkerNumberFromLine(Sci::Line line, int which) const noexcept;
472 int MarkerHandleFromLine(Sci::Line line, int which) const noexcept;
473 Sci_Position SCI_METHOD LineStart(Sci_Position line) const override;
474 [[nodiscard]] Range LineRange(Sci::Line line) const noexcept;
475 bool IsLineStartPosition(Sci::Position position) const noexcept;
476 Sci_Position SCI_METHOD LineEnd(Sci_Position line) const override;
477 Sci::Position LineStartPosition(Sci::Position position) const noexcept;
478 Sci::Position LineEndPosition(Sci::Position position) const noexcept;
479 bool IsLineEndPosition(Sci::Position position) const noexcept;
480 bool IsPositionInLineEnd(Sci::Position position) const noexcept;
481 Sci::Position VCHomePosition(Sci::Position position) const;
482 Sci::Position IndexLineStart(Sci::Line line, Scintilla::LineCharacterIndexType lineCharacterIndex) const noexcept;
483 Sci::Line LineFromPositionIndex(Sci::Position pos, Scintilla::LineCharacterIndexType lineCharacterIndex) const noexcept;
484 Sci::Line LineFromPositionAfter(Sci::Line line, Sci::Position length) const noexcept;
486 int SCI_METHOD SetLevel(Sci_Position line, int level) override;
487 int SCI_METHOD GetLevel(Sci_Position line) const override;
488 Scintilla::FoldLevel GetFoldLevel(Sci_Position line) const noexcept;
489 void ClearLevels();
490 Sci::Line GetLastChild(Sci::Line lineParent, std::optional<Scintilla::FoldLevel> level = {}, Sci::Line lastLine = -1);
491 Sci::Line GetFoldParent(Sci::Line line) const noexcept;
492 void GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, Sci::Line line, Sci::Line lastLine);
494 Sci::Position ExtendWordSelect(Sci::Position pos, int delta, bool onlyWordCharacters=false) const;
495 Sci::Position NextWordStart(Sci::Position pos, int delta) const;
496 Sci::Position NextWordEnd(Sci::Position pos, int delta) const;
497 Sci_Position SCI_METHOD Length() const override { return cb.Length(); }
498 Sci::Position LengthNoExcept() const noexcept { return cb.Length(); }
499 void Allocate(Sci::Position newSize) { cb.Allocate(newSize); }
501 CharacterExtracted ExtractCharacter(Sci::Position position) const noexcept;
503 bool IsWordStartAt(Sci::Position pos) const;
504 bool IsWordEndAt(Sci::Position pos) const;
505 bool IsWordAt(Sci::Position start, Sci::Position end) const;
507 bool MatchesWordOptions(bool word, bool wordStart, Sci::Position pos, Sci::Position length) const;
508 bool HasCaseFolder() const noexcept;
509 void SetCaseFolder(std::unique_ptr<CaseFolder> pcf_) noexcept;
510 Sci::Position FindText(Sci::Position minPos, Sci::Position maxPos, const char *search, Scintilla::FindOption flags, Sci::Position *length);
511 const char *SubstituteByPosition(const char *text, Sci::Position *length);
512 Scintilla::LineCharacterIndexType LineCharacterIndex() const noexcept;
513 void AllocateLineCharacterIndex(Scintilla::LineCharacterIndexType lineCharacterIndex);
514 void ReleaseLineCharacterIndex(Scintilla::LineCharacterIndexType lineCharacterIndex);
515 Sci::Line LinesTotal() const noexcept;
516 void AllocateLines(Sci::Line lines);
518 void SetDefaultCharClasses(bool includeWordClass);
519 void SetCharClasses(const unsigned char *chars, CharacterClass newCharClass);
520 int GetCharsOfClass(CharacterClass characterClass, unsigned char *buffer) const;
521 void SetCharacterCategoryOptimization(int countCharacters);
522 int CharacterCategoryOptimization() const noexcept;
523 void SCI_METHOD StartStyling(Sci_Position position) override;
524 bool SCI_METHOD SetStyleFor(Sci_Position length, char style) override;
525 bool SCI_METHOD SetStyles(Sci_Position length, const char *styles) override;
526 Sci::Position GetEndStyled() const noexcept { return endStyled; }
527 void EnsureStyledTo(Sci::Position pos);
528 void StyleToAdjustingLineDuration(Sci::Position pos);
529 int GetStyleClock() const noexcept { return styleClock; }
530 void IncrementStyleClock() noexcept;
531 void SCI_METHOD DecorationSetCurrentIndicator(int indicator) override;
532 void SCI_METHOD DecorationFillRange(Sci_Position position, int value, Sci_Position fillLength) override;
533 LexInterface *GetLexInterface() const noexcept;
534 void SetLexInterface(std::unique_ptr<LexInterface> pLexInterface) noexcept;
536 int SCI_METHOD SetLineState(Sci_Position line, int state) override;
537 int SCI_METHOD GetLineState(Sci_Position line) const override;
538 Sci::Line GetMaxLineState() const noexcept;
539 void SCI_METHOD ChangeLexerState(Sci_Position start, Sci_Position end) override;
541 StyledText MarginStyledText(Sci::Line line) const noexcept;
542 void MarginSetStyle(Sci::Line line, int style);
543 void MarginSetStyles(Sci::Line line, const unsigned char *styles);
544 void MarginSetText(Sci::Line line, const char *text);
545 void MarginClearAll();
547 StyledText AnnotationStyledText(Sci::Line line) const noexcept;
548 void AnnotationSetText(Sci::Line line, const char *text);
549 void AnnotationSetStyle(Sci::Line line, int style);
550 void AnnotationSetStyles(Sci::Line line, const unsigned char *styles);
551 int AnnotationLines(Sci::Line line) const noexcept;
552 void AnnotationClearAll();
554 StyledText EOLAnnotationStyledText(Sci::Line line) const noexcept;
555 void EOLAnnotationSetStyle(Sci::Line line, int style);
556 void EOLAnnotationSetText(Sci::Line line, const char *text);
557 void EOLAnnotationClearAll();
559 bool AddWatcher(DocWatcher *watcher, void *userData);
560 bool RemoveWatcher(DocWatcher *watcher, void *userData) noexcept;
562 CharacterClass WordCharacterClass(unsigned int ch) const;
563 bool IsWordPartSeparator(unsigned int ch) const;
564 Sci::Position WordPartLeft(Sci::Position pos) const;
565 Sci::Position WordPartRight(Sci::Position pos) const;
566 Sci::Position ExtendStyleRange(Sci::Position pos, int delta, bool singleLine) noexcept;
567 bool IsWhiteLine(Sci::Line line) const;
568 Sci::Position ParaUp(Sci::Position pos) const;
569 Sci::Position ParaDown(Sci::Position pos) const;
570 int IndentSize() const noexcept { return actualIndentInChars; }
571 Sci::Position BraceMatch(Sci::Position position, Sci::Position maxReStyle, Sci::Position startPos, bool useStartPos) noexcept;
573 private:
574 void NotifyModifyAttempt();
575 void NotifySavePoint(bool atSavePoint);
576 void NotifyModified(DocModification mh);
579 class UndoGroup {
580 Document *pdoc;
581 bool groupNeeded;
582 public:
583 UndoGroup(Document *pdoc_, bool groupNeeded_=true) noexcept :
584 pdoc(pdoc_), groupNeeded(groupNeeded_) {
585 if (groupNeeded) {
586 pdoc->BeginUndoAction();
589 // Deleted so UndoGroup objects can not be copied.
590 UndoGroup(const UndoGroup &) = delete;
591 UndoGroup(UndoGroup &&) = delete;
592 void operator=(const UndoGroup &) = delete;
593 UndoGroup &operator=(UndoGroup &&) = delete;
594 ~UndoGroup() {
595 if (groupNeeded) {
596 // EndUndoAction can throw as it allocates but throw in destructor is fatal.
597 // To fix this UndoHistory should allocate any memory needed by EndUndoAction
598 // beforehand or change EndUndoAction to not require allocation.
599 pdoc->EndUndoAction();
602 bool Needed() const noexcept {
603 return groupNeeded;
609 * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
610 * scope of the change.
611 * If the DocWatcher is a document view then this can be used to optimise screen updating.
613 class DocModification {
614 public:
615 Scintilla::ModificationFlags modificationType;
616 Sci::Position position;
617 Sci::Position length;
618 Sci::Line linesAdded; /**< Negative if lines deleted. */
619 const char *text; /**< Only valid for changes to text, not for changes to style. */
620 Sci::Line line;
621 Scintilla::FoldLevel foldLevelNow;
622 Scintilla::FoldLevel foldLevelPrev;
623 Sci::Line annotationLinesAdded;
624 Sci::Position token;
626 DocModification(Scintilla::ModificationFlags modificationType_, Sci::Position position_=0, Sci::Position length_=0,
627 Sci::Line linesAdded_=0, const char *text_=nullptr, Sci::Line line_=0) noexcept :
628 modificationType(modificationType_),
629 position(position_),
630 length(length_),
631 linesAdded(linesAdded_),
632 text(text_),
633 line(line_),
634 foldLevelNow(Scintilla::FoldLevel::None),
635 foldLevelPrev(Scintilla::FoldLevel::None),
636 annotationLinesAdded(0),
637 token(0) {}
639 DocModification(Scintilla::ModificationFlags modificationType_, const Action &act, Sci::Line linesAdded_=0) noexcept :
640 modificationType(modificationType_),
641 position(act.position),
642 length(act.lenData),
643 linesAdded(linesAdded_),
644 text(act.data),
645 line(0),
646 foldLevelNow(Scintilla::FoldLevel::None),
647 foldLevelPrev(Scintilla::FoldLevel::None),
648 annotationLinesAdded(0),
649 token(0) {}
653 * A class that wants to receive notifications from a Document must be derived from DocWatcher
654 * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
656 class DocWatcher {
657 public:
658 virtual ~DocWatcher() {}
660 virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
661 virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
662 virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
663 virtual void NotifyDeleted(Document *doc, void *userData) noexcept = 0;
664 virtual void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) = 0;
665 virtual void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) = 0;
670 #endif