// Scintilla source code edit control /** @file Document.h ** Text document that handles notifications, DBCS, styling, words and end of line. **/ // Copyright 1998-2011 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef DOCUMENT_H #define DOCUMENT_H #ifdef SCI_NAMESPACE namespace Scintilla { #endif /** * A Position is a position within a document between two characters or at the beginning or end. * Sometimes used as a character index where it identifies the character after the position. */ typedef int Position; const Position invalidPosition = -1; /** * The range class represents a range of text in a document. * The two values are not sorted as one end may be more significant than the other * as is the case for the selection where the end position is the position of the caret. * If either position is invalidPosition then the range is invalid and most operations will fail. */ class Range { public: Position start; Position end; Range(Position pos=0) : start(pos), end(pos) { } Range(Position start_, Position end_) : start(start_), end(end_) { } bool Valid() const { return (start != invalidPosition) && (end != invalidPosition); } // Is the position within the range? bool Contains(Position pos) const { if (start < end) { return (pos >= start && pos <= end); } else { return (pos <= start && pos >= end); } } // Is the character after pos within the range? bool ContainsCharacter(Position pos) const { if (start < end) { return (pos >= start && pos < end); } else { return (pos < start && pos >= end); } } bool Contains(Range other) const { return Contains(other.start) && Contains(other.end); } bool Overlaps(Range other) const { return Contains(other.start) || Contains(other.end) || other.Contains(start) || other.Contains(end); } }; class DocWatcher; class DocModification; class Document; /** * Interface class for regular expression searching */ class RegexSearchBase { public: virtual ~RegexSearchBase() {} virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0; ///@return String with the substitutions, must remain valid until the next call or destruction virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0; }; /// Factory function for RegexSearchBase extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable); struct StyledText { size_t length; const char *text; bool multipleStyles; size_t style; const unsigned char *styles; StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { } // Return number of bytes from start to before '\n' or end of text. // Return 1 when start is outside text size_t LineLength(size_t start) const { size_t cur = start; while ((cur < length) && (text[cur] != '\n')) cur++; return cur-start; } size_t StyleAt(size_t i) const { return multipleStyles ? styles[i] : style; } }; class HighlightDelimiter { public: HighlightDelimiter() : isEnabled(false) { Clear(); } void Clear() { beginFoldBlock = -1; endFoldBlock = -1; firstChangeableLineBefore = -1; firstChangeableLineAfter = -1; } bool NeedsDrawing(int line) { return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter); } bool IsFoldBlockHighlighted(int line) { return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock; } bool IsHeadOfFoldBlock(int line) { return beginFoldBlock == line && line < endFoldBlock; } bool IsBodyOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock; } bool IsTailOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock; } int beginFoldBlock; // Begin of current fold block int endFoldBlock; // End of current fold block int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block bool isEnabled; }; class CaseFolder { public: virtual ~CaseFolder() { } virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0; }; class CaseFolderTable : public CaseFolder { protected: char mapping[256]; public: CaseFolderTable(); virtual ~CaseFolderTable(); virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed); void SetTranslation(char ch, char chTranslation); void StandardASCII(); }; class Document; class LexInterface { protected: Document *pdoc; ILexer *instance; bool performingStyle; ///< Prevent reentrance public: LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) { } virtual ~LexInterface() { } void Colourise(int start, int end); bool UseContainerLexing() const { return instance == 0; } }; /** */ class Document : PerLine, public IDocument { public: /** Used to pair watcher pointer with user data. */ class WatcherWithUserData { public: DocWatcher *watcher; void *userData; WatcherWithUserData() { watcher = 0; userData = 0; } }; enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation }; private: int refCount; CellBuffer cb; CharClassify charClass; char stylingMask; int endStyled; int styleClock; int enteredModification; int enteredStyling; int enteredReadOnlyCount; WatcherWithUserData *watchers; int lenWatchers; // ldSize is not real data - it is for dimensions and loops enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; PerLine *perLineData[ldSize]; bool matchesValid; RegexSearchBase *regex; public: LexInterface *pli; int stylingBits; int stylingBitsMask; int eolMode; /// Can also be SC_CP_UTF8 to enable UTF-8 mode int dbcsCodePage; int tabInChars; int indentInChars; int actualIndentInChars; bool useTabs; bool tabIndents; bool backspaceUnindents; DecorationList decorations; Document(); virtual ~Document(); int AddRef(); int Release(); virtual void Init(); virtual void InsertLine(int line); virtual void RemoveLine(int line); int SCI_METHOD Version() const { return dvOriginal; } void SCI_METHOD SetErrorStatus(int status); int SCI_METHOD LineFromPosition(int pos) const; int ClampPositionIntoDocument(int pos); bool IsCrLf(int pos); int LenChar(int pos); bool InGoodUTF8(int pos, int &start, int &end) const; int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); int NextPosition(int pos, int moveDir) const; bool NextCharacter(int &pos, int moveDir); // Returns true if pos changed int SCI_METHOD CodePage() const; bool SCI_METHOD IsDBCSLeadByte(char ch) const; int SafeSegment(const char *text, int length, int lengthSegment); // Gateways to modifying document void ModifiedAt(int pos); void CheckReadOnly(); bool DeleteChars(int pos, int len); bool InsertString(int position, const char *s, int insertLength); int Undo(); int Redo(); bool CanUndo() { return cb.CanUndo(); } bool CanRedo() { return cb.CanRedo(); } void DeleteUndoHistory() { cb.DeleteUndoHistory(); } bool SetUndoCollection(bool collectUndo) { return cb.SetUndoCollection(collectUndo); } bool IsCollectingUndo() { return cb.IsCollectingUndo(); } void BeginUndoAction() { cb.BeginUndoAction(); } void EndUndoAction() { cb.EndUndoAction(); } void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); } void SetSavePoint(); bool IsSavePoint() { return cb.IsSavePoint(); } const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); } int SCI_METHOD GetLineIndentation(int line); void SetLineIndentation(int line, int indent); int GetLineIndentPosition(int line) const; int GetColumn(int position); int FiHTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="Document.h" Content-Disposition: inline; filename="Document.h" Content-Disposition: inline; filename="Document.h" Content-Length: 15271 Content-Length: 15271 Content-Length: 15271 Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Date: Mon, 22 Dec 2025 20:39:52 UTC ETag: "00d23a45d11bfa0220604a8ea9d9b6cf21712b64" ETag: "00d23a45d11bfa0220604a8ea9d9b6cf21712b64" ETag: "00d23a45d11bfa0220604a8ea9d9b6cf21712b64" Expires: Thu, 20 Dec 2035 20:39:52 GMT Expires: Thu, 20 Dec 2035 20:39:53 GMT Expires: Thu, 20 Dec 2035 20:39:53 GMT Last-Modified: Mon, 22 Dec 2025 20:39:52 GMT Last-Modified: Mon, 22 Dec 2025 20:39:53 GMT Last-Modified: Mon, 22 Dec 2025 20:39:53 GMT Server: OpenBSD httpd Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff // Scintilla source code edit control /** @file Document.h ** Text document that handles notifications, DBCS, styling, words and end of line. **/ // Copyright 1998-2011 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef DOCUMENT_H #define DOCUMENT_H #ifdef SCI_NAMESPACE namespace Scintilla { #endif /** * A Position is a position within a document between two characters or at the beginning or end. * Sometimes used as a character index where it identifies the character after the position. */ typedef int Position; const Position invalidPosition = -1; /** * The range class represents a range of text in a document. * The two values are not sorted as one end may be more significant than the other * as is the case for the selection where the end position is the position of the caret. * If either position is invalidPosition then the range is invalid and most operations will fail. */ class Range { public: Position start; Position end; Range(Position pos=0) : start(pos), end(pos) { } Range(Position start_, Position end_) : start(start_), end(end_) { } bool Valid() const { return (start != invalidPosition) && (end != invalidPosition); } // Is the position within the range? bool Contains(Position pos) const { if (start < end) { return (pos >= start && pos <= end); } else { return (pos <= start && pos >= end); } } // Is the character after pos within the range? bool ContainsCharacter(Position pos) const { if (start < end) { return (pos >= start && pos < end); } else { return (pos < start && pos >= end); } } bool Contains(Range other) const { return Contains(other.start) && Contains(other.end); } bool Overlaps(Range other) const { return Contains(other.start) || Contains(other.end) || other.Contains(start) || other.Contains(end); } }; class DocWatcher; class DocModification; class Document; /** * Interface class for regular expression searching */ class RegexSearchBase { public: virtual ~RegexSearchBase() {} virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0; ///@return String with the substitutions, must remain valid until the next call or destruction virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0; }; /// Factory function for RegexSearchBase extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable); struct StyledText { size_t length; const char *text; bool multipleStyles; size_t style; const unsigned char *styles; StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { } // Return number of bytes from start to before '\n' or end of text. // Return 1 when start is outside text size_t LineLength(size_t start) const { size_t cur = start; while ((cur < length) && (text[cur] != '\n')) cur++; return cur-start; } size_t StyleAt(size_t i) const { return multipleStyles ? styles[i] : style; } }; class HighlightDelimiter { public: HighlightDelimiter() : isEnabled(false) { Clear(); } void Clear() { beginFoldBlock = -1; endFoldBlock = -1; firstChangeableLineBefore = -1; firstChangeableLineAfter = -1; } bool NeedsDrawing(int line) { return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter); } bool IsFoldBlockHighlighted(int line) { return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock; } bool IsHeadOfFoldBlock(int line) { return beginFoldBlock == line && line < endFoldBlock; } bool IsBodyOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock; } bool IsTailOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock; } int beginFoldBlock; // Begin of current fold block int endFoldBlock; // End of current fold block int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block bool isEnabled; }; class CaseFolder { public: virtual ~CaseFolder() { } virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0; }; class CaseFolderTable : public CaseFolder { protected: char mapping[256]; public: CaseFolderTable(); virtual ~CaseFolderTable(); virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed); void SetTranslation(char ch, char chTranslation); void StandardASCII(); }; class Document; class LexInterface { protected: Document *pdoc; ILexer *instance; bool performingStyle; ///< Prevent reentrance public: LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) { } virtual ~LexInterface() { } void Colourise(int start, int end); bool UseContainerLexing() const { return instance == 0; } }; /** */ class Document : PerLine, public IDocument { public: /** Used to pair watcher pointer with user data. */ class WatcherWithUserData { public: DocWatcher *watcher; void *userData; WatcherWithUserData() { watcher = 0; userData = 0; } }; enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation }; private: int refCount; CellBuffer cb; CharClassify charClass; char stylingMask; int endStyled; int styleClock; int enteredModification; int enteredStyling; int enteredReadOnlyCount; WatcherWithUserData *watchers; int lenWatchers; // ldSize is not real data - it is for