1 // Scintilla source code edit control
3 ** Manages data associated with each line of the document
5 // Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
12 #include "Scintilla.h"
13 #include "SplitVector.h"
14 #include "Partitioning.h"
15 #include "CellBuffer.h"
19 using namespace Scintilla
;
22 MarkerHandleSet::MarkerHandleSet() {
26 MarkerHandleSet::~MarkerHandleSet() {
27 MarkerHandleNumber
*mhn
= root
;
29 MarkerHandleNumber
*mhnToFree
= mhn
;
36 int MarkerHandleSet::Length() const {
38 MarkerHandleNumber
*mhn
= root
;
46 int MarkerHandleSet::NumberFromHandle(int handle
) const {
47 MarkerHandleNumber
*mhn
= root
;
49 if (mhn
->handle
== handle
) {
57 int MarkerHandleSet::MarkValue() const {
59 MarkerHandleNumber
*mhn
= root
;
61 m
|= (1 << mhn
->number
);
67 bool MarkerHandleSet::Contains(int handle
) const {
68 MarkerHandleNumber
*mhn
= root
;
70 if (mhn
->handle
== handle
) {
78 bool MarkerHandleSet::InsertHandle(int handle
, int markerNum
) {
79 MarkerHandleNumber
*mhn
= new MarkerHandleNumber
;
83 mhn
->number
= markerNum
;
89 void MarkerHandleSet::RemoveHandle(int handle
) {
90 MarkerHandleNumber
**pmhn
= &root
;
92 MarkerHandleNumber
*mhn
= *pmhn
;
93 if (mhn
->handle
== handle
) {
98 pmhn
= &((*pmhn
)->next
);
102 bool MarkerHandleSet::RemoveNumber(int markerNum
) {
103 bool performedDeletion
= false;
104 MarkerHandleNumber
**pmhn
= &root
;
106 MarkerHandleNumber
*mhn
= *pmhn
;
107 if (mhn
->number
== markerNum
) {
110 performedDeletion
= true;
112 pmhn
= &((*pmhn
)->next
);
115 return performedDeletion
;
118 void MarkerHandleSet::CombineWith(MarkerHandleSet
*other
) {
119 MarkerHandleNumber
**pmhn
= &root
;
121 pmhn
= &((*pmhn
)->next
);
127 LineMarkers::~LineMarkers() {
131 void LineMarkers::Init() {
132 for (int line
= 0; line
< markers
.Length(); line
++) {
133 delete markers
[line
];
139 void LineMarkers::InsertLine(int line
) {
140 if (markers
.Length()) {
141 markers
.Insert(line
, 0);
145 void LineMarkers::RemoveLine(int line
) {
146 // Retain the markers from the deleted line by oring them into the previous line
147 if (markers
.Length()) {
149 MergeMarkers(line
- 1);
151 markers
.Delete(line
);
155 int LineMarkers::LineFromHandle(int markerHandle
) {
156 if (markers
.Length()) {
157 for (int line
= 0; line
< markers
.Length(); line
++) {
159 if (markers
[line
]->Contains(markerHandle
)) {
168 void LineMarkers::MergeMarkers(int pos
) {
169 if (markers
[pos
+ 1] != NULL
) {
170 if (markers
[pos
] == NULL
)
171 markers
[pos
] = new MarkerHandleSet
;
172 markers
[pos
]->CombineWith(markers
[pos
+ 1]);
173 delete markers
[pos
+ 1];
174 markers
[pos
+ 1] = NULL
;
178 int LineMarkers::MarkValue(int line
) {
179 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
])
180 return markers
[line
]->MarkValue();
185 int LineMarkers::MarkerNext(int lineStart
, int mask
) const {
188 int length
= markers
.Length();
189 for (int iLine
= lineStart
; iLine
< length
; iLine
++) {
190 MarkerHandleSet
*onLine
= markers
[iLine
];
191 if (onLine
&& ((onLine
->MarkValue() & mask
) != 0))
192 //if ((pdoc->GetMark(iLine) & lParam) != 0)
198 int LineMarkers::AddMark(int line
, int markerNum
, int lines
) {
200 if (!markers
.Length()) {
201 // No existing markers so allocate one element per line
202 markers
.InsertValue(0, lines
, 0);
204 if (line
>= markers
.Length()) {
207 if (!markers
[line
]) {
208 // Need new structure to hold marker handle
209 markers
[line
] = new MarkerHandleSet();
213 markers
[line
]->InsertHandle(handleCurrent
, markerNum
);
215 return handleCurrent
;
218 bool LineMarkers::DeleteMark(int line
, int markerNum
, bool all
) {
219 bool someChanges
= false;
220 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
]) {
221 if (markerNum
== -1) {
223 delete markers
[line
];
224 markers
[line
] = NULL
;
226 bool performedDeletion
= markers
[line
]->RemoveNumber(markerNum
);
227 someChanges
= someChanges
|| performedDeletion
;
228 while (all
&& performedDeletion
) {
229 performedDeletion
= markers
[line
]->RemoveNumber(markerNum
);
230 someChanges
= someChanges
|| performedDeletion
;
232 if (markers
[line
]->Length() == 0) {
233 delete markers
[line
];
234 markers
[line
] = NULL
;
241 void LineMarkers::DeleteMarkFromHandle(int markerHandle
) {
242 int line
= LineFromHandle(markerHandle
);
244 markers
[line
]->RemoveHandle(markerHandle
);
245 if (markers
[line
]->Length() == 0) {
246 delete markers
[line
];
247 markers
[line
] = NULL
;
252 LineLevels::~LineLevels() {
255 void LineLevels::Init() {
259 void LineLevels::InsertLine(int line
) {
260 if (levels
.Length()) {
261 int level
= (line
< levels
.Length()) ? levels
[line
] : SC_FOLDLEVELBASE
;
262 levels
.InsertValue(line
, 1, level
);
266 void LineLevels::RemoveLine(int line
) {
267 if (levels
.Length()) {
268 // Move up following lines but merge header flag from this line
269 // to line before to avoid a temporary disappearence causing expansion.
270 int firstHeader
= levels
[line
] & SC_FOLDLEVELHEADERFLAG
;
272 if (line
== levels
.Length()-1) // Last line loses the header flag
273 levels
[line
-1] &= ~SC_FOLDLEVELHEADERFLAG
;
275 levels
[line
-1] |= firstHeader
;
279 void LineLevels::ExpandLevels(int sizeNew
) {
280 levels
.InsertValue(levels
.Length(), sizeNew
- levels
.Length(), SC_FOLDLEVELBASE
);
283 void LineLevels::ClearLevels() {
287 int LineLevels::SetLevel(int line
, int level
, int lines
) {
289 if ((line
>= 0) && (line
< lines
)) {
290 if (!levels
.Length()) {
291 ExpandLevels(lines
+ 1);
295 levels
[line
] = level
;
301 int LineLevels::GetLevel(int line
) {
302 if (levels
.Length() && (line
>= 0) && (line
< levels
.Length())) {
305 return SC_FOLDLEVELBASE
;
309 LineState::~LineState() {
312 void LineState::Init() {
313 lineStates
.DeleteAll();
316 void LineState::InsertLine(int line
) {
317 if (lineStates
.Length()) {
318 lineStates
.EnsureLength(line
);
319 int val
= (line
< lineStates
.Length()) ? lineStates
[line
] : 0;
320 lineStates
.Insert(line
, val
);
324 void LineState::RemoveLine(int line
) {
325 if (lineStates
.Length() > line
) {
326 lineStates
.Delete(line
);
330 int LineState::SetLineState(int line
, int state
) {
331 lineStates
.EnsureLength(line
+ 1);
332 int stateOld
= lineStates
[line
];
333 lineStates
[line
] = state
;
337 int LineState::GetLineState(int line
) {
340 lineStates
.EnsureLength(line
+ 1);
341 return lineStates
[line
];
344 int LineState::GetMaxLineState() {
345 return lineStates
.Length();
348 static int NumberLines(const char *text
) {
362 // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
363 // and then has text and optional styles.
365 static const int IndividualStyles
= 0x100;
367 struct AnnotationHeader
{
368 short style
; // Style IndividualStyles implies array of styles
373 LineAnnotation::~LineAnnotation() {
377 void LineAnnotation::Init() {
381 void LineAnnotation::InsertLine(int line
) {
382 if (annotations
.Length()) {
383 annotations
.EnsureLength(line
);
384 annotations
.Insert(line
, 0);
388 void LineAnnotation::RemoveLine(int line
) {
389 if (annotations
.Length() && (line
< annotations
.Length())) {
390 delete []annotations
[line
];
391 annotations
.Delete(line
);
395 bool LineAnnotation::AnySet() const {
396 return annotations
.Length() > 0;
399 bool LineAnnotation::MultipleStyles(int line
) const {
400 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
401 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
== IndividualStyles
;
406 int LineAnnotation::Style(int line
) {
407 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
408 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
;
413 const char *LineAnnotation::Text(int line
) const {
414 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
415 return annotations
[line
]+sizeof(AnnotationHeader
);
420 const unsigned char *LineAnnotation::Styles(int line
) const {
421 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
] && MultipleStyles(line
))
422 return reinterpret_cast<unsigned char *>(annotations
[line
] + sizeof(AnnotationHeader
) + Length(line
));
427 static char *AllocateAnnotation(int length
, int style
) {
428 size_t len
= sizeof(AnnotationHeader
) + length
+ ((style
== IndividualStyles
) ? length
: 0);
429 char *ret
= new char[len
];
434 void LineAnnotation::SetText(int line
, const char *text
) {
435 if (text
&& (line
>= 0)) {
436 annotations
.EnsureLength(line
+1);
437 int style
= Style(line
);
438 if (annotations
[line
]) {
439 delete []annotations
[line
];
441 annotations
[line
] = AllocateAnnotation(static_cast<int>(strlen(text
)), style
);
442 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
443 pah
->style
= static_cast<short>(style
);
444 pah
->length
= static_cast<int>(strlen(text
));
445 pah
->lines
= static_cast<short>(NumberLines(text
));
446 memcpy(annotations
[line
]+sizeof(AnnotationHeader
), text
, pah
->length
);
448 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
]) {
449 delete []annotations
[line
];
450 annotations
[line
] = 0;
455 void LineAnnotation::ClearAll() {
456 for (int line
= 0; line
< annotations
.Length(); line
++) {
457 delete []annotations
[line
];
458 annotations
[line
] = 0;
460 annotations
.DeleteAll();
463 void LineAnnotation::SetStyle(int line
, int style
) {
464 annotations
.EnsureLength(line
+1);
465 if (!annotations
[line
]) {
466 annotations
[line
] = AllocateAnnotation(0, style
);
468 reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
= static_cast<short>(style
);
471 void LineAnnotation::SetStyles(int line
, const unsigned char *styles
) {
473 annotations
.EnsureLength(line
+1);
474 if (!annotations
[line
]) {
475 annotations
[line
] = AllocateAnnotation(0, IndividualStyles
);
477 AnnotationHeader
*pahSource
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
478 if (pahSource
->style
!= IndividualStyles
) {
479 char *allocation
= AllocateAnnotation(pahSource
->length
, IndividualStyles
);
480 AnnotationHeader
*pahAlloc
= reinterpret_cast<AnnotationHeader
*>(allocation
);
481 pahAlloc
->length
= pahSource
->length
;
482 pahAlloc
->lines
= pahSource
->lines
;
483 memcpy(allocation
+ sizeof(AnnotationHeader
), annotations
[line
] + sizeof(AnnotationHeader
), pahSource
->length
);
484 delete []annotations
[line
];
485 annotations
[line
] = allocation
;
488 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
489 pah
->style
= IndividualStyles
;
490 memcpy(annotations
[line
] + sizeof(AnnotationHeader
) + pah
->length
, styles
, pah
->length
);
494 int LineAnnotation::Length(int line
) const {
495 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
496 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->length
;
501 int LineAnnotation::Lines(int line
) const {
502 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
503 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->lines
;