Update Tortoise.pot
[TortoiseGit.git] / ext / scintilla / src / Document.h
blob854668973dcf8b2f1f864a09fa6900e2834d5bf8
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 #ifdef SCI_NAMESPACE
12 namespace Scintilla {
13 #endif
15 enum EncodingFamily { efEightBit, efUnicode, efDBCS };
17 /**
18 * The range class represents a range of text in a document.
19 * The two values are not sorted as one end may be more significant than the other
20 * as is the case for the selection where the end position is the position of the caret.
21 * If either position is invalidPosition then the range is invalid and most operations will fail.
23 class Range {
24 public:
25 Sci::Position start;
26 Sci::Position end;
28 explicit Range(Sci::Position pos=0) :
29 start(pos), end(pos) {
31 Range(Sci::Position start_, Sci::Position end_) :
32 start(start_), end(end_) {
35 bool operator==(const Range &other) const {
36 return (start == other.start) && (end == other.end);
39 bool Valid() const {
40 return (start != Sci::invalidPosition) && (end != Sci::invalidPosition);
43 Sci::Position First() const {
44 return (start <= end) ? start : end;
47 Sci::Position Last() const {
48 return (start > end) ? start : end;
51 // Is the position within the range?
52 bool Contains(Sci::Position pos) const {
53 if (start < end) {
54 return (pos >= start && pos <= end);
55 } else {
56 return (pos <= start && pos >= end);
60 // Is the character after pos within the range?
61 bool ContainsCharacter(Sci::Position pos) const {
62 if (start < end) {
63 return (pos >= start && pos < end);
64 } else {
65 return (pos < start && pos >= end);
69 bool Contains(Range other) const {
70 return Contains(other.start) && Contains(other.end);
73 bool Overlaps(Range other) const {
74 return
75 Contains(other.start) ||
76 Contains(other.end) ||
77 other.Contains(start) ||
78 other.Contains(end);
82 class DocWatcher;
83 class DocModification;
84 class Document;
86 /**
87 * Interface class for regular expression searching
89 class RegexSearchBase {
90 public:
91 virtual ~RegexSearchBase() {}
93 virtual long FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
94 bool caseSensitive, bool word, bool wordStart, int flags, Sci::Position *length) = 0;
96 ///@return String with the substitutions, must remain valid until the next call or destruction
97 virtual const char *SubstituteByPosition(Document *doc, const char *text, Sci::Position *length) = 0;
100 /// Factory function for RegexSearchBase
101 extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);
103 struct StyledText {
104 size_t length;
105 const char *text;
106 bool multipleStyles;
107 size_t style;
108 const unsigned char *styles;
109 StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) :
110 length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
112 // Return number of bytes from start to before '\n' or end of text.
113 // Return 1 when start is outside text
114 size_t LineLength(size_t start) const {
115 size_t cur = start;
116 while ((cur < length) && (text[cur] != '\n'))
117 cur++;
118 return cur-start;
120 size_t StyleAt(size_t i) const {
121 return multipleStyles ? styles[i] : style;
125 class HighlightDelimiter {
126 public:
127 HighlightDelimiter() : isEnabled(false) {
128 Clear();
131 void Clear() {
132 beginFoldBlock = -1;
133 endFoldBlock = -1;
134 firstChangeableLineBefore = -1;
135 firstChangeableLineAfter = -1;
138 bool NeedsDrawing(Sci::Line line) const {
139 return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
142 bool IsFoldBlockHighlighted(Sci::Line line) const {
143 return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
146 bool IsHeadOfFoldBlock(Sci::Line line) const {
147 return beginFoldBlock == line && line < endFoldBlock;
150 bool IsBodyOfFoldBlock(Sci::Line line) const {
151 return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
154 bool IsTailOfFoldBlock(Sci::Line line) const {
155 return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
158 Sci::Line beginFoldBlock; // Begin of current fold block
159 Sci::Line endFoldBlock; // End of current fold block
160 Sci::Line firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block
161 Sci::Line firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block
162 bool isEnabled;
165 class Document;
166 class LineMarkers;
167 class LineLevels;
168 class LineState;
169 class LineAnnotation;
171 inline int LevelNumber(int level) {
172 return level & SC_FOLDLEVELNUMBERMASK;
175 class LexInterface {
176 protected:
177 Document *pdoc;
178 ILexer *instance;
179 bool performingStyle; ///< Prevent reentrance
180 public:
181 explicit LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) {
183 virtual ~LexInterface() {
185 void Colourise(Sci::Position start, Sci::Position end);
186 int LineEndTypesSupported();
187 bool UseContainerLexing() const {
188 return instance == 0;
192 struct RegexError : public std::runtime_error {
193 RegexError() : std::runtime_error("regex failure") {}
198 class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
200 public:
201 /** Used to pair watcher pointer with user data. */
202 struct WatcherWithUserData {
203 DocWatcher *watcher;
204 void *userData;
205 WatcherWithUserData(DocWatcher *watcher_=0, void *userData_=0) :
206 watcher(watcher_), userData(userData_) {
208 bool operator==(const WatcherWithUserData &other) const {
209 return (watcher == other.watcher) && (userData == other.userData);
213 private:
214 int refCount;
215 CellBuffer cb;
216 CharClassify charClass;
217 std::unique_ptr<CaseFolder> pcf;
218 Sci::Position endStyled;
219 int styleClock;
220 int enteredModification;
221 int enteredStyling;
222 int enteredReadOnlyCount;
224 bool insertionSet;
225 std::string insertion;
227 std::vector<WatcherWithUserData> watchers;
229 // ldSize is not real data - it is for dimensions and loops
230 enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
231 std::unique_ptr<PerLine> perLineData[ldSize];
232 LineMarkers *Markers() const;
233 LineLevels *Levels() const;
234 LineState *States() const;
235 LineAnnotation *Margins() const;
236 LineAnnotation *Annotations() const;
238 bool matchesValid;
239 std::unique_ptr<RegexSearchBase> regex;
240 std::unique_ptr<LexInterface> pli;
242 public:
244 struct CharacterExtracted {
245 unsigned int character;
246 unsigned int widthBytes;
247 CharacterExtracted(unsigned int character_, unsigned int widthBytes_) :
248 character(character_), widthBytes(widthBytes_) {
250 // For DBCS characters turn 2 bytes into an int
251 static CharacterExtracted DBCS(unsigned char lead, unsigned char trail) {
252 return CharacterExtracted((lead << 8) | trail, 2);
256 int eolMode;
257 /// Can also be SC_CP_UTF8 to enable UTF-8 mode
258 int dbcsCodePage;
259 int lineEndBitSet;
260 int tabInChars;
261 int indentInChars;
262 int actualIndentInChars;
263 bool useTabs;
264 bool tabIndents;
265 bool backspaceUnindents;
266 double durationStyleOneLine;
268 DecorationList decorations;
270 Document();
271 // Deleted so Document objects can not be copied.
272 Document(const Document &) = delete;
273 void operator=(const Document &) = delete;
274 virtual ~Document();
276 int AddRef();
277 int SCI_METHOD Release();
279 virtual void Init();
280 int LineEndTypesSupported() const;
281 bool SetDBCSCodePage(int dbcsCodePage_);
282 int GetLineEndTypesAllowed() const { return cb.GetLineEndTypes(); }
283 bool SetLineEndTypesAllowed(int lineEndBitSet_);
284 int GetLineEndTypesActive() const { return cb.GetLineEndTypes(); }
285 virtual void InsertLine(Sci::Line line);
286 virtual void RemoveLine(Sci::Line line);
288 int SCI_METHOD Version() const {
289 return dvLineEnd;
292 void SCI_METHOD SetErrorStatus(int status);
294 Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const;
295 Sci::Position ClampPositionIntoDocument(Sci::Position pos) const;
296 bool ContainsLineEnd(const char *s, Sci::Position length) const { return cb.ContainsLineEnd(s, length); }
297 bool IsCrLf(Sci::Position pos) const;
298 int LenChar(Sci::Position pos);
299 bool InGoodUTF8(Sci::Position pos, Sci::Position &start, Sci::Position &end) const;
300 Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const;
301 Sci::Position NextPosition(Sci::Position pos, int moveDir) const;
302 bool NextCharacter(Sci::Position &pos, int moveDir) const; // Returns true if pos changed
303 Document::CharacterExtracted CharacterAfter(Sci::Position position) const;
304 Document::CharacterExtracted CharacterBefore(Sci::Position position) const;
305 Sci_Position SCI_METHOD GetRelativePosition(Sci_Position positionStart, Sci_Position characterOffset) const;
306 Sci::Position GetRelativePositionUTF16(Sci::Position positionStart, Sci::Position characterOffset) const;
307 int SCI_METHOD GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const;
308 int SCI_METHOD CodePage() const;
309 bool SCI_METHOD IsDBCSLeadByte(char ch) const;
310 int SafeSegment(const char *text, int length, int lengthSegment) const;
311 EncodingFamily CodePageFamily() const;
313 // Gateways to modifying document
314 void ModifiedAt(Sci::Position pos);
315 void CheckReadOnly();
316 bool DeleteChars(Sci::Position pos, Sci::Position len);
317 Sci::Position InsertString(Sci::Position position, const char *s, Sci::Position insertLength);
318 void ChangeInsertion(const char *s, Sci::Position length);
319 int SCI_METHOD AddData(char *data, Sci_Position length);
320 void * SCI_METHOD ConvertToDocument();
321 Sci::Position Undo();
322 Sci::Position Redo();
323 bool CanUndo() const { return cb.CanUndo(); }
324 bool CanRedo() const { return cb.CanRedo(); }
325 void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
326 bool SetUndoCollection(bool collectUndo) {
327 return cb.SetUndoCollection(collectUndo);
329 bool IsCollectingUndo() const { return cb.IsCollectingUndo(); }
330 void BeginUndoAction() { cb.BeginUndoAction(); }
331 void EndUndoAction() { cb.EndUndoAction(); }
332 void AddUndoAction(Sci::Position token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
333 void SetSavePoint();
334 bool IsSavePoint() const { return cb.IsSavePoint(); }
336 void TentativeStart() { cb.TentativeStart(); }
337 void TentativeCommit() { cb.TentativeCommit(); }
338 void TentativeUndo();
339 bool TentativeActive() const { return cb.TentativeActive(); }
341 const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); }
342 const char *RangePointer(Sci::Position position, Sci::Position rangeLength) { return cb.RangePointer(position, rangeLength); }
343 Sci::Position GapPosition() const { return cb.GapPosition(); }
345 int SCI_METHOD GetLineIndentation(Sci_Position line);
346 Sci::Position SetLineIndentation(Sci::Line line, Sci::Position indent);
347 Sci::Position GetLineIndentPosition(Sci::Line line) const;
348 Sci::Position GetColumn(Sci::Position pos);
349 Sci::Position CountCharacters(Sci::Position startPos, Sci::Position endPos) const;
350 Sci::Position CountUTF16(Sci::Position startPos, Sci::Position endPos) const;
351 Sci::Position FindColumn(Sci::Line line, Sci::Position column);
352 void Indent(bool forwards, Sci::Line lineBottom, Sci::Line lineTop);
353 static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted);
354 void ConvertLineEnds(int eolModeSet);
355 void SetReadOnly(bool set) { cb.SetReadOnly(set); }
356 bool IsReadOnly() const { return cb.IsReadOnly(); }
358 void DelChar(Sci::Position pos);
359 void DelCharBack(Sci::Position pos);
361 char CharAt(Sci::Position position) const { return cb.CharAt(position); }
362 void SCI_METHOD GetCharRange(char *buffer, Sci_Position position, Sci_Position lengthRetrieve) const {
363 cb.GetCharRange(buffer, position, lengthRetrieve);
365 char SCI_METHOD StyleAt(Sci_Position position) const { return cb.StyleAt(position); }
366 int StyleIndexAt(Sci_Position position) const { return static_cast<unsigned char>(cb.StyleAt(position)); }
367 void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
368 cb.GetStyleRange(buffer, position, lengthRetrieve);
370 int GetMark(Sci::Line line) const;
371 Sci::Line MarkerNext(Sci::Line lineStart, int mask) const;
372 int AddMark(Sci::Line line, int markerNum);
373 void AddMarkSet(Sci::Line line, int valueSet);
374 void DeleteMark(Sci::Line line, int markerNum);
375 void DeleteMarkFromHandle(int markerHandle);
376 void DeleteAllMarks(int markerNum);
377 Sci::Line LineFromHandle(int markerHandle) const;
378 Sci_Position SCI_METHOD LineStart(Sci_Position line) const;
379 bool IsLineStartPosition(Sci::Position position) const;
380 Sci_Position SCI_METHOD LineEnd(Sci_Position line) const;
381 Sci::Position LineEndPosition(Sci::Position position) const;
382 bool IsLineEndPosition(Sci::Position position) const;
383 bool IsPositionInLineEnd(Sci::Position position) const;
384 Sci::Position VCHomePosition(Sci::Position position) const;
386 int SCI_METHOD SetLevel(Sci_Position line, int level);
387 int SCI_METHOD GetLevel(Sci_Position line) const;
388 void ClearLevels();
389 Sci::Line GetLastChild(Sci::Line lineParent, int level=-1, Sci::Line lastLine=-1);
390 Sci::Line GetFoldParent(Sci::Line line) const;
391 void GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, Sci::Line line, Sci::Line lastLine);
393 Sci::Position ExtendWordSelect(Sci::Position pos, int delta, bool onlyWordCharacters=false) const;
394 Sci::Position NextWordStart(Sci::Position pos, int delta) const;
395 Sci::Position NextWordEnd(Sci::Position pos, int delta) const;
396 Sci_Position SCI_METHOD Length() const { return cb.Length(); }
397 void Allocate(Sci::Position newSize) { cb.Allocate(newSize); }
399 CharacterExtracted ExtractCharacter(Sci::Position position) const;
401 bool IsWordStartAt(Sci::Position pos) const;
402 bool IsWordEndAt(Sci::Position pos) const;
403 bool IsWordAt(Sci::Position start, Sci::Position end) const;
405 bool MatchesWordOptions(bool word, bool wordStart, Sci::Position pos, Sci::Position length) const;
406 bool HasCaseFolder() const;
407 void SetCaseFolder(CaseFolder *pcf_);
408 long FindText(Sci::Position minPos, Sci::Position maxPos, const char *search, int flags, Sci::Position *length);
409 const char *SubstituteByPosition(const char *text, Sci::Position *length);
410 Sci::Line LinesTotal() const;
412 void SetDefaultCharClasses(bool includeWordClass);
413 void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
414 int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) const;
415 void SCI_METHOD StartStyling(Sci_Position position, char mask);
416 bool SCI_METHOD SetStyleFor(Sci_Position length, char style);
417 bool SCI_METHOD SetStyles(Sci_Position length, const char *styles);
418 Sci::Position GetEndStyled() const { return endStyled; }
419 void EnsureStyledTo(Sci::Position pos);
420 void StyleToAdjustingLineDuration(Sci::Position pos);
421 void LexerChanged();
422 int GetStyleClock() const { return styleClock; }
423 void IncrementStyleClock();
424 void SCI_METHOD DecorationSetCurrentIndicator(int indicator);
425 void SCI_METHOD DecorationFillRange(Sci_Position position, int value, Sci_Position fillLength);
426 LexInterface *GetLexInterface() const;
427 void SetLexInterface(LexInterface *pLexInterface);
429 int SCI_METHOD SetLineState(Sci_Position line, int state);
430 int SCI_METHOD GetLineState(Sci_Position line) const;
431 Sci::Line GetMaxLineState() const;
432 void SCI_METHOD ChangeLexerState(Sci_Position start, Sci_Position end);
434 StyledText MarginStyledText(Sci::Line line) const;
435 void MarginSetStyle(Sci::Line line, int style);
436 void MarginSetStyles(Sci::Line line, const unsigned char *styles);
437 void MarginSetText(Sci::Line line, const char *text);
438 void MarginClearAll();
440 StyledText AnnotationStyledText(Sci::Line line) const;
441 void AnnotationSetText(Sci::Line line, const char *text);
442 void AnnotationSetStyle(Sci::Line line, int style);
443 void AnnotationSetStyles(Sci::Line line, const unsigned char *styles);
444 int AnnotationLines(Sci::Line line) const;
445 void AnnotationClearAll();
447 bool AddWatcher(DocWatcher *watcher, void *userData);
448 bool RemoveWatcher(DocWatcher *watcher, void *userData);
450 bool IsASCIIWordByte(unsigned char ch) const;
451 CharClassify::cc WordCharacterClass(unsigned int ch) const;
452 bool IsWordPartSeparator(unsigned int ch) const;
453 Sci::Position WordPartLeft(Sci::Position pos) const;
454 Sci::Position WordPartRight(Sci::Position pos) const;
455 Sci::Position ExtendStyleRange(Sci::Position pos, int delta, bool singleLine = false);
456 bool IsWhiteLine(Sci::Line line) const;
457 Sci::Position ParaUp(Sci::Position pos) const;
458 Sci::Position ParaDown(Sci::Position pos) const;
459 int IndentSize() const { return actualIndentInChars; }
460 Sci::Position BraceMatch(Sci::Position position, Sci::Position maxReStyle);
462 private:
463 void NotifyModifyAttempt();
464 void NotifySavePoint(bool atSavePoint);
465 void NotifyModified(DocModification mh);
468 class UndoGroup {
469 Document *pdoc;
470 bool groupNeeded;
471 public:
472 UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
473 pdoc(pdoc_), groupNeeded(groupNeeded_) {
474 if (groupNeeded) {
475 pdoc->BeginUndoAction();
478 ~UndoGroup() {
479 if (groupNeeded) {
480 pdoc->EndUndoAction();
483 bool Needed() const {
484 return groupNeeded;
490 * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
491 * scope of the change.
492 * If the DocWatcher is a document view then this can be used to optimise screen updating.
494 class DocModification {
495 public:
496 int modificationType;
497 Sci::Position position;
498 Sci::Position length;
499 Sci::Line linesAdded; /**< Negative if lines deleted. */
500 const char *text; /**< Only valid for changes to text, not for changes to style. */
501 Sci::Line line;
502 int foldLevelNow;
503 int foldLevelPrev;
504 Sci::Line annotationLinesAdded;
505 Sci::Position token;
507 DocModification(int modificationType_, Sci::Position position_=0, Sci::Position length_=0,
508 Sci::Line linesAdded_=0, const char *text_=0, Sci::Line line_=0) :
509 modificationType(modificationType_),
510 position(position_),
511 length(length_),
512 linesAdded(linesAdded_),
513 text(text_),
514 line(line_),
515 foldLevelNow(0),
516 foldLevelPrev(0),
517 annotationLinesAdded(0),
518 token(0) {}
520 DocModification(int modificationType_, const Action &act, Sci::Line linesAdded_=0) :
521 modificationType(modificationType_),
522 position(act.position),
523 length(act.lenData),
524 linesAdded(linesAdded_),
525 text(act.data.get()),
526 line(0),
527 foldLevelNow(0),
528 foldLevelPrev(0),
529 annotationLinesAdded(0),
530 token(0) {}
534 * A class that wants to receive notifications from a Document must be derived from DocWatcher
535 * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
537 class DocWatcher {
538 public:
539 virtual ~DocWatcher() {}
541 virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
542 virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
543 virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
544 virtual void NotifyDeleted(Document *doc, void *userData) = 0;
545 virtual void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) = 0;
546 virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
547 virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;
550 #ifdef SCI_NAMESPACE
552 #endif
554 #endif