You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
9.2 KiB
305 lines
9.2 KiB
// Scintilla source code edit control |
|
/** @file Document.h |
|
** Text document that handles notifications, DBCS, styling, words and end of line. |
|
**/ |
|
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> |
|
// The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
#ifndef DOCUMENT_H |
|
#define DOCUMENT_H |
|
|
|
/** |
|
* 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 RESearch; |
|
|
|
/** |
|
*/ |
|
class Document { |
|
|
|
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 enteredCount; |
|
int enteredReadOnlyCount; |
|
|
|
WatcherWithUserData *watchers; |
|
int lenWatchers; |
|
|
|
bool matchesValid; |
|
RESearch *pre; |
|
char *substituted; |
|
|
|
public: |
|
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; |
|
|
|
Document(); |
|
virtual ~Document(); |
|
|
|
int AddRef(); |
|
int Release(); |
|
|
|
int LineFromPosition(int pos); |
|
int ClampPositionIntoDocument(int pos); |
|
bool IsCrLf(int pos); |
|
int LenChar(int pos); |
|
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); |
|
|
|
// Gateways to modifying document |
|
void ModifiedAt(int pos); |
|
bool DeleteChars(int pos, int len); |
|
bool InsertStyledString(int position, 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 SetSavePoint(); |
|
bool IsSavePoint() { return cb.IsSavePoint(); } |
|
|
|
int GetLineIndentation(int line); |
|
void SetLineIndentation(int line, int indent); |
|
int GetLineIndentPosition(int line); |
|
int GetColumn(int position); |
|
int FindColumn(int line, int column); |
|
void Indent(bool forwards, int lineBottom, int lineTop); |
|
static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode); |
|
void ConvertLineEnds(int eolModeSet); |
|
void SetReadOnly(bool set) { cb.SetReadOnly(set); } |
|
bool IsReadOnly() { return cb.IsReadOnly(); } |
|
|
|
bool InsertChar(int pos, char ch); |
|
bool InsertString(int position, const char *s); |
|
bool InsertString(int position, const char *s, size_t insertLength); |
|
void ChangeChar(int pos, char ch); |
|
void DelChar(int pos); |
|
void DelCharBack(int pos); |
|
|
|
char CharAt(int position) { return cb.CharAt(position); } |
|
void GetCharRange(char *buffer, int position, int lengthRetrieve) { |
|
cb.GetCharRange(buffer, position, lengthRetrieve); |
|
} |
|
char StyleAt(int position) { return cb.StyleAt(position); } |
|
int GetMark(int line) { return cb.GetMark(line); } |
|
int AddMark(int line, int markerNum); |
|
void AddMarkSet(int line, int valueSet); |
|
void DeleteMark(int line, int markerNum); |
|
void DeleteMarkFromHandle(int markerHandle); |
|
void DeleteAllMarks(int markerNum); |
|
int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); } |
|
int LineStart(int line); |
|
int LineEnd(int line); |
|
int LineEndPosition(int position); |
|
int VCHomePosition(int position); |
|
|
|
int SetLevel(int line, int level); |
|
int GetLevel(int line) { return cb.GetLevel(line); } |
|
void ClearLevels() { cb.ClearLevels(); } |
|
int GetLastChild(int lineParent, int level=-1); |
|
int GetFoldParent(int line); |
|
|
|
void Indent(bool forwards); |
|
int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false); |
|
int NextWordStart(int pos, int delta); |
|
int NextWordEnd(int pos, int delta); |
|
int Length() { return cb.Length(); } |
|
void Allocate(int newSize) { cb.Allocate(newSize*2); } |
|
long FindText(int minPos, int maxPos, const char *s, |
|
bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix, int *length); |
|
long FindText(int iMessage, unsigned long wParam, long lParam); |
|
const char *SubstituteByPosition(const char *text, int *length); |
|
int LinesTotal(); |
|
|
|
void ChangeCase(Range r, bool makeUpperCase); |
|
|
|
void SetDefaultCharClasses(bool includeWordClass); |
|
void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass); |
|
void SetStylingBits(int bits); |
|
void StartStyling(int position, char mask); |
|
bool SetStyleFor(int length, char style); |
|
bool SetStyles(int length, char *styles); |
|
int GetEndStyled() { return endStyled; } |
|
bool EnsureStyledTo(int pos); |
|
int GetStyleClock() { return styleClock; } |
|
void IncrementStyleClock(); |
|
|
|
int SetLineState(int line, int state) { return cb.SetLineState(line, state); } |
|
int GetLineState(int line) { return cb.GetLineState(line); } |
|
int GetMaxLineState() { return cb.GetMaxLineState(); } |
|
|
|
bool AddWatcher(DocWatcher *watcher, void *userData); |
|
bool RemoveWatcher(DocWatcher *watcher, void *userData); |
|
const WatcherWithUserData *GetWatchers() const { return watchers; } |
|
int GetLenWatchers() const { return lenWatchers; } |
|
|
|
bool IsWordPartSeparator(char ch); |
|
int WordPartLeft(int pos); |
|
int WordPartRight(int pos); |
|
int ExtendStyleRange(int pos, int delta, bool singleLine = false); |
|
bool IsWhiteLine(int line); |
|
int ParaUp(int pos); |
|
int ParaDown(int pos); |
|
int IndentSize() { return actualIndentInChars; } |
|
int BraceMatch(int position, int maxReStyle); |
|
|
|
private: |
|
void CheckReadOnly(); |
|
|
|
CharClassify::cc WordCharClass(unsigned char ch); |
|
bool IsWordStartAt(int pos); |
|
bool IsWordEndAt(int pos); |
|
bool IsWordAt(int start, int end); |
|
|
|
void NotifyModifyAttempt(); |
|
void NotifySavePoint(bool atSavePoint); |
|
void NotifyModified(DocModification mh); |
|
}; |
|
|
|
/** |
|
* To optimise processing of document modifications by DocWatchers, a hint is passed indicating the |
|
* scope of the change. |
|
* If the DocWatcher is a document view then this can be used to optimise screen updating. |
|
*/ |
|
class DocModification { |
|
public: |
|
int modificationType; |
|
int position; |
|
int length; |
|
int linesAdded; /**< Negative if lines deleted. */ |
|
const char *text; /**< Only valid for changes to text, not for changes to style. */ |
|
int line; |
|
int foldLevelNow; |
|
int foldLevelPrev; |
|
|
|
DocModification(int modificationType_, int position_=0, int length_=0, |
|
int linesAdded_=0, const char *text_=0, int line_=0) : |
|
modificationType(modificationType_), |
|
position(position_), |
|
length(length_), |
|
linesAdded(linesAdded_), |
|
text(text_), |
|
line(line_), |
|
foldLevelNow(0), |
|
foldLevelPrev(0) {} |
|
|
|
DocModification(int modificationType_, const Action &act, int linesAdded_=0) : |
|
modificationType(modificationType_), |
|
position(act.position), |
|
length(act.lenData), |
|
linesAdded(linesAdded_), |
|
text(act.data), |
|
line(0), |
|
foldLevelNow(0), |
|
foldLevelPrev(0) {} |
|
}; |
|
|
|
/** |
|
* A class that wants to receive notifications from a Document must be derived from DocWatcher |
|
* and implement the notification methods. It can then be added to the watcher list with AddWatcher. |
|
*/ |
|
class DocWatcher { |
|
public: |
|
virtual ~DocWatcher() {} |
|
|
|
virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0; |
|
virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0; |
|
virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0; |
|
virtual void NotifyDeleted(Document *doc, void *userData) = 0; |
|
virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0; |
|
}; |
|
|
|
#endif
|
|
|