1 // Scintilla source code edit control
3 ** Text document that handles notifications, DBCS, styling, words and end of line.
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.
16 * A Position is a position within a document between two characters or at the beginning or end.
17 * Sometimes used as a character index where it identifies the character after the position.
20 const Position invalidPosition
= -1;
23 * The range class represents a range of text in a document.
24 * The two values are not sorted as one end may be more significant than the other
25 * as is the case for the selection where the end position is the position of the caret.
26 * If either position is invalidPosition then the range is invalid and most operations will fail.
33 Range(Position pos
=0) :
34 start(pos
), end(pos
) {
36 Range(Position start_
, Position end_
) :
37 start(start_
), end(end_
) {
41 return (start
!= invalidPosition
) && (end
!= invalidPosition
);
44 // Is the position within the range?
45 bool Contains(Position pos
) const {
47 return (pos
>= start
&& pos
<= end
);
49 return (pos
<= start
&& pos
>= end
);
53 // Is the character after pos within the range?
54 bool ContainsCharacter(Position pos
) const {
56 return (pos
>= start
&& pos
< end
);
58 return (pos
< start
&& pos
>= end
);
62 bool Contains(Range other
) const {
63 return Contains(other
.start
) && Contains(other
.end
);
66 bool Overlaps(Range other
) const {
68 Contains(other
.start
) ||
69 Contains(other
.end
) ||
70 other
.Contains(start
) ||
76 class DocModification
;
80 * Interface class for regular expression searching
82 class RegexSearchBase
{
84 virtual ~RegexSearchBase() {}
86 virtual long FindText(Document
*doc
, int minPos
, int maxPos
, const char *s
,
87 bool caseSensitive
, bool word
, bool wordStart
, int flags
, int *length
) = 0;
89 ///@return String with the substitutions, must remain valid until the next call or destruction
90 virtual const char *SubstituteByPosition(Document
*doc
, const char *text
, int *length
) = 0;
93 /// Factory function for RegexSearchBase
94 extern RegexSearchBase
*CreateRegexSearch(CharClassify
*charClassTable
);
101 const unsigned char *styles
;
102 StyledText(size_t length_
, const char *text_
, bool multipleStyles_
, int style_
, const unsigned char *styles_
) :
103 length(length_
), text(text_
), multipleStyles(multipleStyles_
), style(style_
), styles(styles_
) {
105 // Return number of bytes from start to before '\n' or end of text.
106 // Return 1 when start is outside text
107 size_t LineLength(size_t start
) const {
109 while ((cur
< length
) && (text
[cur
] != '\n'))
113 size_t StyleAt(size_t i
) const {
114 return multipleStyles
? styles
[i
] : style
;
118 class HighlightDelimiter
{
120 HighlightDelimiter() : isEnabled(false) {
127 firstChangeableLineBefore
= -1;
128 firstChangeableLineAfter
= -1;
131 bool NeedsDrawing(int line
) const {
132 return isEnabled
&& (line
<= firstChangeableLineBefore
|| line
>= firstChangeableLineAfter
);
135 bool IsFoldBlockHighlighted(int line
) const {
136 return isEnabled
&& beginFoldBlock
!= -1 && beginFoldBlock
<= line
&& line
<= endFoldBlock
;
139 bool IsHeadOfFoldBlock(int line
) const {
140 return beginFoldBlock
== line
&& line
< endFoldBlock
;
143 bool IsBodyOfFoldBlock(int line
) const {
144 return beginFoldBlock
!= -1 && beginFoldBlock
< line
&& line
< endFoldBlock
;
147 bool IsTailOfFoldBlock(int line
) const {
148 return beginFoldBlock
!= -1 && beginFoldBlock
< line
&& line
== endFoldBlock
;
151 int beginFoldBlock
; // Begin of current fold block
152 int endFoldBlock
; // End of current fold block
153 int firstChangeableLineBefore
; // First line that triggers repaint before starting line that determined current fold block
154 int firstChangeableLineAfter
; // First line that triggers repaint after starting line that determined current fold block
164 bool performingStyle
; ///< Prevent reentrance
166 LexInterface(Document
*pdoc_
) : pdoc(pdoc_
), instance(0), performingStyle(false) {
168 virtual ~LexInterface() {
170 void Colourise(int start
, int end
);
171 int LineEndTypesSupported();
172 bool UseContainerLexing() const {
173 return instance
== 0;
179 class Document
: PerLine
, public IDocumentWithLineEnd
, public ILoader
{
182 /** Used to pair watcher pointer with user data. */
183 struct WatcherWithUserData
{
186 WatcherWithUserData(DocWatcher
*watcher_
=0, void *userData_
=0) :
187 watcher(watcher_
), userData(userData_
) {
189 bool operator==(const WatcherWithUserData
&other
) const {
190 return (watcher
== other
.watcher
) && (userData
== other
.userData
);
197 CharClassify charClass
;
202 int enteredModification
;
204 int enteredReadOnlyCount
;
206 std::vector
<WatcherWithUserData
> watchers
;
208 // ldSize is not real data - it is for dimensions and loops
209 enum lineData
{ ldMarkers
, ldLevels
, ldState
, ldMargin
, ldAnnotation
, ldSize
};
210 PerLine
*perLineData
[ldSize
];
213 RegexSearchBase
*regex
;
223 /// Can also be SC_CP_UTF8 to enable UTF-8 mode
228 int actualIndentInChars
;
231 bool backspaceUnindents
;
233 DecorationList decorations
;
239 int SCI_METHOD
Release();
242 int LineEndTypesSupported() const;
243 bool SetDBCSCodePage(int dbcsCodePage_
);
244 int GetLineEndTypesAllowed() const { return cb
.GetLineEndTypes(); }
245 bool SetLineEndTypesAllowed(int lineEndBitSet_
);
246 int GetLineEndTypesActive() const { return cb
.GetLineEndTypes(); }
247 virtual void InsertLine(int line
);
248 virtual void RemoveLine(int line
);
250 int SCI_METHOD
Version() const {
254 void SCI_METHOD
SetErrorStatus(int status
);
256 int SCI_METHOD
LineFromPosition(int pos
) const;
257 int ClampPositionIntoDocument(int pos
) const;
258 bool IsCrLf(int pos
) const;
259 int LenChar(int pos
);
260 bool InGoodUTF8(int pos
, int &start
, int &end
) const;
261 int MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
=true);
262 int NextPosition(int pos
, int moveDir
) const;
263 bool NextCharacter(int &pos
, int moveDir
) const; // Returns true if pos changed
264 int SCI_METHOD
GetRelativePosition(int positionStart
, int characterOffset
) const;
265 int SCI_METHOD
GetCharacterAndWidth(int position
, int *pWidth
) const;
266 int SCI_METHOD
CodePage() const;
267 bool SCI_METHOD
IsDBCSLeadByte(char ch
) const;
268 int SafeSegment(const char *text
, int length
, int lengthSegment
) const;
270 // Gateways to modifying document
271 void ModifiedAt(int pos
);
272 void CheckReadOnly();
273 bool DeleteChars(int pos
, int len
);
274 bool InsertString(int position
, const char *s
, int insertLength
);
275 int SCI_METHOD
AddData(char *data
, int length
);
276 void * SCI_METHOD
ConvertToDocument();
279 bool CanUndo() const { return cb
.CanUndo(); }
280 bool CanRedo() const { return cb
.CanRedo(); }
281 void DeleteUndoHistory() { cb
.DeleteUndoHistory(); }
282 bool SetUndoCollection(bool collectUndo
) {
283 return cb
.SetUndoCollection(collectUndo
);
285 bool IsCollectingUndo() const { return cb
.IsCollectingUndo(); }
286 void BeginUndoAction() { cb
.BeginUndoAction(); }
287 void EndUndoAction() { cb
.EndUndoAction(); }
288 void AddUndoAction(int token
, bool mayCoalesce
) { cb
.AddUndoAction(token
, mayCoalesce
); }
290 bool IsSavePoint() const { return cb
.IsSavePoint(); }
291 const char * SCI_METHOD
BufferPointer() { return cb
.BufferPointer(); }
292 const char *RangePointer(int position
, int rangeLength
) { return cb
.RangePointer(position
, rangeLength
); }
293 int GapPosition() const { return cb
.GapPosition(); }
295 int SCI_METHOD
GetLineIndentation(int line
);
296 void SetLineIndentation(int line
, int indent
);
297 int GetLineIndentPosition(int line
) const;
298 int GetColumn(int position
);
299 int CountCharacters(int startPos
, int endPos
);
300 int FindColumn(int line
, int column
);
301 void Indent(bool forwards
, int lineBottom
, int lineTop
);
302 static std::string
TransformLineEnds(const char *s
, size_t len
, int eolModeWanted
);
303 void ConvertLineEnds(int eolModeSet
);
304 void SetReadOnly(bool set
) { cb
.SetReadOnly(set
); }
305 bool IsReadOnly() const { return cb
.IsReadOnly(); }
307 bool InsertChar(int pos
, char ch
);
308 bool InsertCString(int position
, const char *s
);
309 void DelChar(int pos
);
310 void DelCharBack(int pos
);
312 char CharAt(int position
) const { return cb
.CharAt(position
); }
313 void SCI_METHOD
GetCharRange(char *buffer
, int position
, int lengthRetrieve
) const {
314 cb
.GetCharRange(buffer
, position
, lengthRetrieve
);
316 char SCI_METHOD
StyleAt(int position
) const { return cb
.StyleAt(position
); }
317 void GetStyleRange(unsigned char *buffer
, int position
, int lengthRetrieve
) const {
318 cb
.GetStyleRange(buffer
, position
, lengthRetrieve
);
320 int GetMark(int line
);
321 int MarkerNext(int lineStart
, int mask
) const;
322 int AddMark(int line
, int markerNum
);
323 void AddMarkSet(int line
, int valueSet
);
324 void DeleteMark(int line
, int markerNum
);
325 void DeleteMarkFromHandle(int markerHandle
);
326 void DeleteAllMarks(int markerNum
);
327 int LineFromHandle(int markerHandle
);
328 int SCI_METHOD
LineStart(int line
) const;
329 int SCI_METHOD
LineEnd(int line
) const;
330 int LineEndPosition(int position
) const;
331 bool IsLineEndPosition(int position
) const;
332 bool IsPositionInLineEnd(int position
) const;
333 int VCHomePosition(int position
) const;
335 int SCI_METHOD
SetLevel(int line
, int level
);
336 int SCI_METHOD
GetLevel(int line
) const;
338 int GetLastChild(int lineParent
, int level
=-1, int lastLine
=-1);
339 int GetFoldParent(int line
) const;
340 void GetHighlightDelimiters(HighlightDelimiter
&hDelimiter
, int line
, int lastLine
);
342 void Indent(bool forwards
);
343 int ExtendWordSelect(int pos
, int delta
, bool onlyWordCharacters
=false);
344 int NextWordStart(int pos
, int delta
);
345 int NextWordEnd(int pos
, int delta
);
346 int SCI_METHOD
Length() const { return cb
.Length(); }
347 void Allocate(int newSize
) { cb
.Allocate(newSize
); }
348 bool MatchesWordOptions(bool word
, bool wordStart
, int pos
, int length
) const;
349 bool HasCaseFolder(void) const;
350 void SetCaseFolder(CaseFolder
*pcf_
);
351 long FindText(int minPos
, int maxPos
, const char *search
, bool caseSensitive
, bool word
,
352 bool wordStart
, bool regExp
, int flags
, int *length
);
353 const char *SubstituteByPosition(const char *text
, int *length
);
354 int LinesTotal() const;
356 void SetDefaultCharClasses(bool includeWordClass
);
357 void SetCharClasses(const unsigned char *chars
, CharClassify::cc newCharClass
);
358 int GetCharsOfClass(CharClassify::cc charClass
, unsigned char *buffer
);
359 void SetStylingBits(int bits
);
360 void SCI_METHOD
StartStyling(int position
, char mask
);
361 bool SCI_METHOD
SetStyleFor(int length
, char style
);
362 bool SCI_METHOD
SetStyles(int length
, const char *styles
);
363 int GetEndStyled() const { return endStyled
; }
364 void EnsureStyledTo(int pos
);
366 int GetStyleClock() const { return styleClock
; }
367 void IncrementStyleClock();
368 void SCI_METHOD
DecorationSetCurrentIndicator(int indicator
) {
369 decorations
.SetCurrentIndicator(indicator
);
371 void SCI_METHOD
DecorationFillRange(int position
, int value
, int fillLength
);
373 int SCI_METHOD
SetLineState(int line
, int state
);
374 int SCI_METHOD
GetLineState(int line
) const;
375 int GetMaxLineState();
376 void SCI_METHOD
ChangeLexerState(int start
, int end
);
378 StyledText
MarginStyledText(int line
) const;
379 void MarginSetStyle(int line
, int style
);
380 void MarginSetStyles(int line
, const unsigned char *styles
);
381 void MarginSetText(int line
, const char *text
);
382 void MarginClearAll();
384 StyledText
AnnotationStyledText(int line
) const;
385 void AnnotationSetText(int line
, const char *text
);
386 void AnnotationSetStyle(int line
, int style
);
387 void AnnotationSetStyles(int line
, const unsigned char *styles
);
388 int AnnotationLines(int line
) const;
389 void AnnotationClearAll();
391 bool AddWatcher(DocWatcher
*watcher
, void *userData
);
392 bool RemoveWatcher(DocWatcher
*watcher
, void *userData
);
394 CharClassify::cc
WordCharClass(unsigned char ch
) const;
395 bool IsWordPartSeparator(char ch
) const;
396 int WordPartLeft(int pos
);
397 int WordPartRight(int pos
);
398 int ExtendStyleRange(int pos
, int delta
, bool singleLine
= false);
399 bool IsWhiteLine(int line
) const;
400 int ParaUp(int pos
) const;
401 int ParaDown(int pos
) const;
402 int IndentSize() const { return actualIndentInChars
; }
403 int BraceMatch(int position
, int maxReStyle
);
406 bool IsWordStartAt(int pos
) const;
407 bool IsWordEndAt(int pos
) const;
408 bool IsWordAt(int start
, int end
) const;
410 void NotifyModifyAttempt();
411 void NotifySavePoint(bool atSavePoint
);
412 void NotifyModified(DocModification mh
);
419 UndoGroup(Document
*pdoc_
, bool groupNeeded_
=true) :
420 pdoc(pdoc_
), groupNeeded(groupNeeded_
) {
422 pdoc
->BeginUndoAction();
427 pdoc
->EndUndoAction();
430 bool Needed() const {
437 * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
438 * scope of the change.
439 * If the DocWatcher is a document view then this can be used to optimise screen updating.
441 class DocModification
{
443 int modificationType
;
446 int linesAdded
; /**< Negative if lines deleted. */
447 const char *text
; /**< Only valid for changes to text, not for changes to style. */
451 int annotationLinesAdded
;
454 DocModification(int modificationType_
, int position_
=0, int length_
=0,
455 int linesAdded_
=0, const char *text_
=0, int line_
=0) :
456 modificationType(modificationType_
),
459 linesAdded(linesAdded_
),
464 annotationLinesAdded(0),
467 DocModification(int modificationType_
, const Action
&act
, int linesAdded_
=0) :
468 modificationType(modificationType_
),
469 position(act
.position
),
471 linesAdded(linesAdded_
),
476 annotationLinesAdded(0),
481 * A class that wants to receive notifications from a Document must be derived from DocWatcher
482 * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
486 virtual ~DocWatcher() {}
488 virtual void NotifyModifyAttempt(Document
*doc
, void *userData
) = 0;
489 virtual void NotifySavePoint(Document
*doc
, void *userData
, bool atSavePoint
) = 0;
490 virtual void NotifyModified(Document
*doc
, DocModification mh
, void *userData
) = 0;
491 virtual void NotifyDeleted(Document
*doc
, void *userData
) = 0;
492 virtual void NotifyStyleNeeded(Document
*doc
, void *userData
, int endPos
) = 0;
493 virtual void NotifyLexerChanged(Document
*doc
, void *userData
) = 0;
494 virtual void NotifyErrorOccurred(Document
*doc
, void *userData
, int status
) = 0;