1 // Scintilla source code edit control
3 ** Text document that handles notifications, DBCS, styling, words and end of line.
5 // Copyright 1998-2003 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
;
120 virtual ~CaseFolder() {
122 virtual size_t Fold(char *folded
, size_t sizeFolded
, const char *mixed
, size_t lenMixed
) = 0;
125 class CaseFolderTable
: public CaseFolder
{
130 virtual ~CaseFolderTable();
131 virtual size_t Fold(char *folded
, size_t sizeFolded
, const char *mixed
, size_t lenMixed
);
132 void SetTranslation(char ch
, char chTranslation
);
133 void StandardASCII();
138 class Document
: PerLine
{
141 /** Used to pair watcher pointer with user data. */
142 class WatcherWithUserData
{
146 WatcherWithUserData() {
152 enum charClassification
{ ccSpace
, ccNewLine
, ccWord
, ccPunctuation
};
156 CharClassify charClass
;
160 int enteredModification
;
162 int enteredReadOnlyCount
;
164 WatcherWithUserData
*watchers
;
167 // ldSize is not real data - it is for dimensions and loops
168 enum lineData
{ ldMarkers
, ldLevels
, ldState
, ldMargin
, ldAnnotation
, ldSize
};
169 PerLine
*perLineData
[ldSize
];
172 RegexSearchBase
*regex
;
179 /// Can also be SC_CP_UTF8 to enable UTF-8 mode
183 int actualIndentInChars
;
186 bool backspaceUnindents
;
188 DecorationList decorations
;
197 virtual void InsertLine(int line
);
198 virtual void RemoveLine(int line
);
200 int LineFromPosition(int pos
) const;
201 int ClampPositionIntoDocument(int pos
);
202 bool IsCrLf(int pos
);
203 int LenChar(int pos
);
204 bool InGoodUTF8(int pos
, int &start
, int &end
);
205 int MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
=true);
207 // Gateways to modifying document
208 void ModifiedAt(int pos
);
209 void CheckReadOnly();
210 bool DeleteChars(int pos
, int len
);
211 bool InsertString(int position
, const char *s
, int insertLength
);
214 bool CanUndo() { return cb
.CanUndo(); }
215 bool CanRedo() { return cb
.CanRedo(); }
216 void DeleteUndoHistory() { cb
.DeleteUndoHistory(); }
217 bool SetUndoCollection(bool collectUndo
) {
218 return cb
.SetUndoCollection(collectUndo
);
220 bool IsCollectingUndo() { return cb
.IsCollectingUndo(); }
221 void BeginUndoAction() { cb
.BeginUndoAction(); }
222 void EndUndoAction() { cb
.EndUndoAction(); }
223 void AddUndoAction(int token
, bool mayCoalesce
) { cb
.AddUndoAction(token
, mayCoalesce
); }
225 bool IsSavePoint() { return cb
.IsSavePoint(); }
226 const char *BufferPointer() { return cb
.BufferPointer(); }
228 int GetLineIndentation(int line
);
229 void SetLineIndentation(int line
, int indent
);
230 int GetLineIndentPosition(int line
) const;
231 int GetColumn(int position
);
232 int FindColumn(int line
, int column
);
233 void Indent(bool forwards
, int lineBottom
, int lineTop
);
234 static char *TransformLineEnds(int *pLenOut
, const char *s
, size_t len
, int eolMode
);
235 void ConvertLineEnds(int eolModeSet
);
236 void SetReadOnly(bool set
) { cb
.SetReadOnly(set
); }
237 bool IsReadOnly() { return cb
.IsReadOnly(); }
239 bool InsertChar(int pos
, char ch
);
240 bool InsertCString(int position
, const char *s
);
241 void ChangeChar(int pos
, char ch
);
242 void DelChar(int pos
);
243 void DelCharBack(int pos
);
245 char CharAt(int position
) { return cb
.CharAt(position
); }
246 void GetCharRange(char *buffer
, int position
, int lengthRetrieve
) const {
247 cb
.GetCharRange(buffer
, position
, lengthRetrieve
);
249 char StyleAt(int position
) const { return cb
.StyleAt(position
); }
250 int GetMark(int line
);
251 int AddMark(int line
, int markerNum
);
252 void AddMarkSet(int line
, int valueSet
);
253 void DeleteMark(int line
, int markerNum
);
254 void DeleteMarkFromHandle(int markerHandle
);
255 void DeleteAllMarks(int markerNum
);
256 int LineFromHandle(int markerHandle
);
257 int LineStart(int line
) const;
258 int LineEnd(int line
) const;
259 int LineEndPosition(int position
) const;
260 bool IsLineEndPosition(int position
) const;
261 int VCHomePosition(int position
) const;
263 int SetLevel(int line
, int level
);
264 int GetLevel(int line
) const;
266 int GetLastChild(int lineParent
, int level
=-1);
267 int GetFoldParent(int line
);
269 void Indent(bool forwards
);
270 int ExtendWordSelect(int pos
, int delta
, bool onlyWordCharacters
=false);
271 int NextWordStart(int pos
, int delta
);
272 int NextWordEnd(int pos
, int delta
);
273 int Length() const { return cb
.Length(); }
274 void Allocate(int newSize
) { cb
.Allocate(newSize
); }
275 size_t ExtractChar(int pos
, char *bytes
);
276 bool MatchesWordOptions(bool word
, bool wordStart
, int pos
, int length
);
277 long FindText(int minPos
, int maxPos
, const char *search
, bool caseSensitive
, bool word
,
278 bool wordStart
, bool regExp
, int flags
, int *length
, CaseFolder
*pcf
);
279 const char *SubstituteByPosition(const char *text
, int *length
);
280 int LinesTotal() const;
282 void ChangeCase(Range r
, bool makeUpperCase
);
284 void SetDefaultCharClasses(bool includeWordClass
);
285 void SetCharClasses(const unsigned char *chars
, CharClassify::cc newCharClass
);
286 void SetStylingBits(int bits
);
287 void StartStyling(int position
, char mask
);
288 bool SetStyleFor(int length
, char style
);
289 bool SetStyles(int length
, const char *styles
);
290 int GetEndStyled() { return endStyled
; }
291 void EnsureStyledTo(int pos
);
292 int GetStyleClock() { return styleClock
; }
293 void IncrementStyleClock();
294 void DecorationFillRange(int position
, int value
, int fillLength
);
296 int SetLineState(int line
, int state
);
297 int GetLineState(int line
) const;
298 int GetMaxLineState();
300 StyledText
MarginStyledText(int line
);
301 void MarginSetStyle(int line
, int style
);
302 void MarginSetStyles(int line
, const unsigned char *styles
);
303 void MarginSetText(int line
, const char *text
);
304 int MarginLength(int line
) const;
305 void MarginClearAll();
307 bool AnnotationAny() const;
308 StyledText
AnnotationStyledText(int line
);
309 void AnnotationSetText(int line
, const char *text
);
310 void AnnotationSetStyle(int line
, int style
);
311 void AnnotationSetStyles(int line
, const unsigned char *styles
);
312 int AnnotationLength(int line
) const;
313 int AnnotationLines(int line
) const;
314 void AnnotationClearAll();
316 bool AddWatcher(DocWatcher
*watcher
, void *userData
);
317 bool RemoveWatcher(DocWatcher
*watcher
, void *userData
);
318 const WatcherWithUserData
*GetWatchers() const { return watchers
; }
319 int GetLenWatchers() const { return lenWatchers
; }
321 bool IsWordPartSeparator(char ch
);
322 int WordPartLeft(int pos
);
323 int WordPartRight(int pos
);
324 int ExtendStyleRange(int pos
, int delta
, bool singleLine
= false);
325 bool IsWhiteLine(int line
) const;
327 int ParaDown(int pos
);
328 int IndentSize() { return actualIndentInChars
; }
329 int BraceMatch(int position
, int maxReStyle
);
332 CharClassify::cc
WordCharClass(unsigned char ch
);
333 bool IsWordStartAt(int pos
);
334 bool IsWordEndAt(int pos
);
335 bool IsWordAt(int start
, int end
);
337 void NotifyModifyAttempt();
338 void NotifySavePoint(bool atSavePoint
);
339 void NotifyModified(DocModification mh
);
346 UndoGroup(Document
*pdoc_
, bool groupNeeded_
=true) :
347 pdoc(pdoc_
), groupNeeded(groupNeeded_
) {
349 pdoc
->BeginUndoAction();
354 pdoc
->EndUndoAction();
357 bool Needed() const {
364 * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
365 * scope of the change.
366 * If the DocWatcher is a document view then this can be used to optimise screen updating.
368 class DocModification
{
370 int modificationType
;
373 int linesAdded
; /**< Negative if lines deleted. */
374 const char *text
; /**< Only valid for changes to text, not for changes to style. */
378 int annotationLinesAdded
;
381 DocModification(int modificationType_
, int position_
=0, int length_
=0,
382 int linesAdded_
=0, const char *text_
=0, int line_
=0) :
383 modificationType(modificationType_
),
386 linesAdded(linesAdded_
),
391 annotationLinesAdded(0),
394 DocModification(int modificationType_
, const Action
&act
, int linesAdded_
=0) :
395 modificationType(modificationType_
),
396 position(act
.position
),
398 linesAdded(linesAdded_
),
403 annotationLinesAdded(0),
408 * A class that wants to receive notifications from a Document must be derived from DocWatcher
409 * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
413 virtual ~DocWatcher() {}
415 virtual void NotifyModifyAttempt(Document
*doc
, void *userData
) = 0;
416 virtual void NotifySavePoint(Document
*doc
, void *userData
, bool atSavePoint
) = 0;
417 virtual void NotifyModified(Document
*doc
, DocModification mh
, void *userData
) = 0;
418 virtual void NotifyDeleted(Document
*doc
, void *userData
) = 0;
419 virtual void NotifyStyleNeeded(Document
*doc
, void *userData
, int endPos
) = 0;