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
, bool all
) {
103 bool performedDeletion
= false;
104 MarkerHandleNumber
**pmhn
= &root
;
106 MarkerHandleNumber
*mhn
= *pmhn
;
107 if (mhn
->number
== markerNum
) {
110 performedDeletion
= true;
114 pmhn
= &((*pmhn
)->next
);
117 return performedDeletion
;
120 void MarkerHandleSet::CombineWith(MarkerHandleSet
*other
) {
121 MarkerHandleNumber
**pmhn
= &root
;
123 pmhn
= &((*pmhn
)->next
);
129 LineMarkers::~LineMarkers() {
133 void LineMarkers::Init() {
134 for (int line
= 0; line
< markers
.Length(); line
++) {
135 delete markers
[line
];
141 void LineMarkers::InsertLine(int line
) {
142 if (markers
.Length()) {
143 markers
.Insert(line
, 0);
147 void LineMarkers::RemoveLine(int line
) {
148 // Retain the markers from the deleted line by oring them into the previous line
149 if (markers
.Length()) {
151 MergeMarkers(line
- 1);
153 markers
.Delete(line
);
157 int LineMarkers::LineFromHandle(int markerHandle
) {
158 if (markers
.Length()) {
159 for (int line
= 0; line
< markers
.Length(); line
++) {
161 if (markers
[line
]->Contains(markerHandle
)) {
170 void LineMarkers::MergeMarkers(int pos
) {
171 if (markers
[pos
+ 1] != NULL
) {
172 if (markers
[pos
] == NULL
)
173 markers
[pos
] = new MarkerHandleSet
;
174 markers
[pos
]->CombineWith(markers
[pos
+ 1]);
175 delete markers
[pos
+ 1];
176 markers
[pos
+ 1] = NULL
;
180 int LineMarkers::MarkValue(int line
) {
181 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
])
182 return markers
[line
]->MarkValue();
187 int LineMarkers::MarkerNext(int lineStart
, int mask
) const {
190 int length
= markers
.Length();
191 for (int iLine
= lineStart
; iLine
< length
; iLine
++) {
192 MarkerHandleSet
*onLine
= markers
[iLine
];
193 if (onLine
&& ((onLine
->MarkValue() & mask
) != 0))
194 //if ((pdoc->GetMark(iLine) & lParam) != 0)
200 int LineMarkers::AddMark(int line
, int markerNum
, int lines
) {
202 if (!markers
.Length()) {
203 // No existing markers so allocate one element per line
204 markers
.InsertValue(0, lines
, 0);
206 if (line
>= markers
.Length()) {
209 if (!markers
[line
]) {
210 // Need new structure to hold marker handle
211 markers
[line
] = new MarkerHandleSet();
215 markers
[line
]->InsertHandle(handleCurrent
, markerNum
);
217 return handleCurrent
;
220 bool LineMarkers::DeleteMark(int line
, int markerNum
, bool all
) {
221 bool someChanges
= false;
222 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
]) {
223 if (markerNum
== -1) {
225 delete markers
[line
];
226 markers
[line
] = NULL
;
228 someChanges
= markers
[line
]->RemoveNumber(markerNum
, all
);
229 if (markers
[line
]->Length() == 0) {
230 delete markers
[line
];
231 markers
[line
] = NULL
;
238 void LineMarkers::DeleteMarkFromHandle(int markerHandle
) {
239 int line
= LineFromHandle(markerHandle
);
241 markers
[line
]->RemoveHandle(markerHandle
);
242 if (markers
[line
]->Length() == 0) {
243 delete markers
[line
];
244 markers
[line
] = NULL
;
249 LineLevels::~LineLevels() {
252 void LineLevels::Init() {
256 void LineLevels::InsertLine(int line
) {
257 if (levels
.Length()) {
258 int level
= (line
< levels
.Length()) ? levels
[line
] : SC_FOLDLEVELBASE
;
259 levels
.InsertValue(line
, 1, level
);
263 void LineLevels::RemoveLine(int line
) {
264 if (levels
.Length()) {
265 // Move up following lines but merge header flag from this line
266 // to line before to avoid a temporary disappearence causing expansion.
267 int firstHeader
= levels
[line
] & SC_FOLDLEVELHEADERFLAG
;
269 if (line
== levels
.Length()-1) // Last line loses the header flag
270 levels
[line
-1] &= ~SC_FOLDLEVELHEADERFLAG
;
272 levels
[line
-1] |= firstHeader
;
276 void LineLevels::ExpandLevels(int sizeNew
) {
277 levels
.InsertValue(levels
.Length(), sizeNew
- levels
.Length(), SC_FOLDLEVELBASE
);
280 void LineLevels::ClearLevels() {
284 int LineLevels::SetLevel(int line
, int level
, int lines
) {
286 if ((line
>= 0) && (line
< lines
)) {
287 if (!levels
.Length()) {
288 ExpandLevels(lines
+ 1);
292 levels
[line
] = level
;
298 int LineLevels::GetLevel(int line
) {
299 if (levels
.Length() && (line
>= 0) && (line
< levels
.Length())) {
302 return SC_FOLDLEVELBASE
;
306 LineState::~LineState() {
309 void LineState::Init() {
310 lineStates
.DeleteAll();
313 void LineState::InsertLine(int line
) {
314 if (lineStates
.Length()) {
315 lineStates
.EnsureLength(line
);
316 int val
= (line
< lineStates
.Length()) ? lineStates
[line
] : 0;
317 lineStates
.Insert(line
, val
);
321 void LineState::RemoveLine(int line
) {
322 if (lineStates
.Length() > line
) {
323 lineStates
.Delete(line
);
327 int LineState::SetLineState(int line
, int state
) {
328 lineStates
.EnsureLength(line
+ 1);
329 int stateOld
= lineStates
[line
];
330 lineStates
[line
] = state
;
334 int LineState::GetLineState(int line
) {
337 lineStates
.EnsureLength(line
+ 1);
338 return lineStates
[line
];
341 int LineState::GetMaxLineState() {
342 return lineStates
.Length();
345 static int NumberLines(const char *text
) {
359 // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
360 // and then has text and optional styles.
362 static const int IndividualStyles
= 0x100;
364 struct AnnotationHeader
{
365 short style
; // Style IndividualStyles implies array of styles
370 LineAnnotation::~LineAnnotation() {
374 void LineAnnotation::Init() {
378 void LineAnnotation::InsertLine(int line
) {
379 if (annotations
.Length()) {
380 annotations
.EnsureLength(line
);
381 annotations
.Insert(line
, 0);
385 void LineAnnotation::RemoveLine(int line
) {
386 if (annotations
.Length() && (line
< annotations
.Length())) {
387 delete []annotations
[line
];
388 annotations
.Delete(line
);
392 bool LineAnnotation::AnySet() const {
393 return annotations
.Length() > 0;
396 bool LineAnnotation::MultipleStyles(int line
) const {
397 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
398 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
== IndividualStyles
;
403 int LineAnnotation::Style(int line
) {
404 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
405 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
;
410 const char *LineAnnotation::Text(int line
) const {
411 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
412 return annotations
[line
]+sizeof(AnnotationHeader
);
417 const unsigned char *LineAnnotation::Styles(int line
) const {
418 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
] && MultipleStyles(line
))
419 return reinterpret_cast<unsigned char *>(annotations
[line
] + sizeof(AnnotationHeader
) + Length(line
));
424 static char *AllocateAnnotation(int length
, int style
) {
425 size_t len
= sizeof(AnnotationHeader
) + length
+ ((style
== IndividualStyles
) ? length
: 0);
426 char *ret
= new char[len
];
431 void LineAnnotation::SetText(int line
, const char *text
) {
432 if (text
&& (line
>= 0)) {
433 annotations
.EnsureLength(line
+1);
434 int style
= Style(line
);
435 if (annotations
[line
]) {
436 delete []annotations
[line
];
438 annotations
[line
] = AllocateAnnotation(static_cast<int>(strlen(text
)), style
);
439 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
440 pah
->style
= static_cast<short>(style
);
441 pah
->length
= static_cast<int>(strlen(text
));
442 pah
->lines
= static_cast<short>(NumberLines(text
));
443 memcpy(annotations
[line
]+sizeof(AnnotationHeader
), text
, pah
->length
);
445 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
]) {
446 delete []annotations
[line
];
447 annotations
[line
] = 0;
452 void LineAnnotation::ClearAll() {
453 for (int line
= 0; line
< annotations
.Length(); line
++) {
454 delete []annotations
[line
];
455 annotations
[line
] = 0;
457 annotations
.DeleteAll();
460 void LineAnnotation::SetStyle(int line
, int style
) {
461 annotations
.EnsureLength(line
+1);
462 if (!annotations
[line
]) {
463 annotations
[line
] = AllocateAnnotation(0, style
);
465 reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
= static_cast<short>(style
);
468 void LineAnnotation::SetStyles(int line
, const unsigned char *styles
) {
470 annotations
.EnsureLength(line
+1);
471 if (!annotations
[line
]) {
472 annotations
[line
] = AllocateAnnotation(0, IndividualStyles
);
474 AnnotationHeader
*pahSource
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
475 if (pahSource
->style
!= IndividualStyles
) {
476 char *allocation
= AllocateAnnotation(pahSource
->length
, IndividualStyles
);
477 AnnotationHeader
*pahAlloc
= reinterpret_cast<AnnotationHeader
*>(allocation
);
478 pahAlloc
->length
= pahSource
->length
;
479 pahAlloc
->lines
= pahSource
->lines
;
480 memcpy(allocation
+ sizeof(AnnotationHeader
), annotations
[line
] + sizeof(AnnotationHeader
), pahSource
->length
);
481 delete []annotations
[line
];
482 annotations
[line
] = allocation
;
485 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
486 pah
->style
= IndividualStyles
;
487 memcpy(annotations
[line
] + sizeof(AnnotationHeader
) + pah
->length
, styles
, pah
->length
);
491 int LineAnnotation::Length(int line
) const {
492 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
493 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->length
;
498 int LineAnnotation::Lines(int line
) const {
499 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
500 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->lines
;