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.
14 #include "Scintilla.h"
15 #include "SplitVector.h"
16 #include "Partitioning.h"
17 #include "CellBuffer.h"
21 using namespace Scintilla
;
24 MarkerHandleSet::MarkerHandleSet() {
28 MarkerHandleSet::~MarkerHandleSet() {
29 MarkerHandleNumber
*mhn
= root
;
31 MarkerHandleNumber
*mhnToFree
= mhn
;
38 int MarkerHandleSet::Length() const {
40 MarkerHandleNumber
*mhn
= root
;
48 int MarkerHandleSet::MarkValue() const {
50 MarkerHandleNumber
*mhn
= root
;
52 m
|= (1 << mhn
->number
);
58 bool MarkerHandleSet::Contains(int handle
) const {
59 MarkerHandleNumber
*mhn
= root
;
61 if (mhn
->handle
== handle
) {
69 bool MarkerHandleSet::InsertHandle(int handle
, int markerNum
) {
70 MarkerHandleNumber
*mhn
= new MarkerHandleNumber
;
72 mhn
->number
= markerNum
;
78 void MarkerHandleSet::RemoveHandle(int handle
) {
79 MarkerHandleNumber
**pmhn
= &root
;
81 MarkerHandleNumber
*mhn
= *pmhn
;
82 if (mhn
->handle
== handle
) {
87 pmhn
= &((*pmhn
)->next
);
91 bool MarkerHandleSet::RemoveNumber(int markerNum
, bool all
) {
92 bool performedDeletion
= false;
93 MarkerHandleNumber
**pmhn
= &root
;
95 MarkerHandleNumber
*mhn
= *pmhn
;
96 if (mhn
->number
== markerNum
) {
99 performedDeletion
= true;
103 pmhn
= &((*pmhn
)->next
);
106 return performedDeletion
;
109 void MarkerHandleSet::CombineWith(MarkerHandleSet
*other
) {
110 MarkerHandleNumber
**pmhn
= &root
;
112 pmhn
= &((*pmhn
)->next
);
118 LineMarkers::~LineMarkers() {
122 void LineMarkers::Init() {
123 for (int line
= 0; line
< markers
.Length(); line
++) {
124 delete markers
[line
];
130 void LineMarkers::InsertLine(int line
) {
131 if (markers
.Length()) {
132 markers
.Insert(line
, 0);
136 void LineMarkers::RemoveLine(int line
) {
137 // Retain the markers from the deleted line by oring them into the previous line
138 if (markers
.Length()) {
140 MergeMarkers(line
- 1);
142 markers
.Delete(line
);
146 int LineMarkers::LineFromHandle(int markerHandle
) {
147 if (markers
.Length()) {
148 for (int line
= 0; line
< markers
.Length(); line
++) {
150 if (markers
[line
]->Contains(markerHandle
)) {
159 void LineMarkers::MergeMarkers(int pos
) {
160 if (markers
[pos
+ 1] != NULL
) {
161 if (markers
[pos
] == NULL
)
162 markers
[pos
] = new MarkerHandleSet
;
163 markers
[pos
]->CombineWith(markers
[pos
+ 1]);
164 delete markers
[pos
+ 1];
165 markers
[pos
+ 1] = NULL
;
169 int LineMarkers::MarkValue(int line
) {
170 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
])
171 return markers
[line
]->MarkValue();
176 int LineMarkers::MarkerNext(int lineStart
, int mask
) const {
179 int length
= markers
.Length();
180 for (int iLine
= lineStart
; iLine
< length
; iLine
++) {
181 MarkerHandleSet
*onLine
= markers
[iLine
];
182 if (onLine
&& ((onLine
->MarkValue() & mask
) != 0))
183 //if ((pdoc->GetMark(iLine) & lParam) != 0)
189 int LineMarkers::AddMark(int line
, int markerNum
, int lines
) {
191 if (!markers
.Length()) {
192 // No existing markers so allocate one element per line
193 markers
.InsertValue(0, lines
, 0);
195 if (line
>= markers
.Length()) {
198 if (!markers
[line
]) {
199 // Need new structure to hold marker handle
200 markers
[line
] = new MarkerHandleSet();
202 markers
[line
]->InsertHandle(handleCurrent
, markerNum
);
204 return handleCurrent
;
207 bool LineMarkers::DeleteMark(int line
, int markerNum
, bool all
) {
208 bool someChanges
= false;
209 if (markers
.Length() && (line
>= 0) && (line
< markers
.Length()) && markers
[line
]) {
210 if (markerNum
== -1) {
212 delete markers
[line
];
213 markers
[line
] = NULL
;
215 someChanges
= markers
[line
]->RemoveNumber(markerNum
, all
);
216 if (markers
[line
]->Length() == 0) {
217 delete markers
[line
];
218 markers
[line
] = NULL
;
225 void LineMarkers::DeleteMarkFromHandle(int markerHandle
) {
226 int line
= LineFromHandle(markerHandle
);
228 markers
[line
]->RemoveHandle(markerHandle
);
229 if (markers
[line
]->Length() == 0) {
230 delete markers
[line
];
231 markers
[line
] = NULL
;
236 LineLevels::~LineLevels() {
239 void LineLevels::Init() {
243 void LineLevels::InsertLine(int line
) {
244 if (levels
.Length()) {
245 int level
= (line
< levels
.Length()) ? levels
[line
] : SC_FOLDLEVELBASE
;
246 levels
.InsertValue(line
, 1, level
);
250 void LineLevels::RemoveLine(int line
) {
251 if (levels
.Length()) {
252 // Move up following lines but merge header flag from this line
253 // to line before to avoid a temporary disappearence causing expansion.
254 int firstHeader
= levels
[line
] & SC_FOLDLEVELHEADERFLAG
;
256 if (line
== levels
.Length()-1) // Last line loses the header flag
257 levels
[line
-1] &= ~SC_FOLDLEVELHEADERFLAG
;
259 levels
[line
-1] |= firstHeader
;
263 void LineLevels::ExpandLevels(int sizeNew
) {
264 levels
.InsertValue(levels
.Length(), sizeNew
- levels
.Length(), SC_FOLDLEVELBASE
);
267 void LineLevels::ClearLevels() {
271 int LineLevels::SetLevel(int line
, int level
, int lines
) {
273 if ((line
>= 0) && (line
< lines
)) {
274 if (!levels
.Length()) {
275 ExpandLevels(lines
+ 1);
279 levels
[line
] = level
;
285 int LineLevels::GetLevel(int line
) const {
286 if (levels
.Length() && (line
>= 0) && (line
< levels
.Length())) {
289 return SC_FOLDLEVELBASE
;
293 LineState::~LineState() {
296 void LineState::Init() {
297 lineStates
.DeleteAll();
300 void LineState::InsertLine(int line
) {
301 if (lineStates
.Length()) {
302 lineStates
.EnsureLength(line
);
303 int val
= (line
< lineStates
.Length()) ? lineStates
[line
] : 0;
304 lineStates
.Insert(line
, val
);
308 void LineState::RemoveLine(int line
) {
309 if (lineStates
.Length() > line
) {
310 lineStates
.Delete(line
);
314 int LineState::SetLineState(int line
, int state
) {
315 lineStates
.EnsureLength(line
+ 1);
316 int stateOld
= lineStates
[line
];
317 lineStates
[line
] = state
;
321 int LineState::GetLineState(int line
) {
324 lineStates
.EnsureLength(line
+ 1);
325 return lineStates
[line
];
328 int LineState::GetMaxLineState() const {
329 return lineStates
.Length();
332 static int NumberLines(const char *text
) {
346 // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
347 // and then has text and optional styles.
349 static const int IndividualStyles
= 0x100;
351 struct AnnotationHeader
{
352 short style
; // Style IndividualStyles implies array of styles
357 LineAnnotation::~LineAnnotation() {
361 void LineAnnotation::Init() {
365 void LineAnnotation::InsertLine(int line
) {
366 if (annotations
.Length()) {
367 annotations
.EnsureLength(line
);
368 annotations
.Insert(line
, 0);
372 void LineAnnotation::RemoveLine(int line
) {
373 if (annotations
.Length() && (line
< annotations
.Length())) {
374 delete []annotations
[line
];
375 annotations
.Delete(line
);
379 bool LineAnnotation::MultipleStyles(int line
) const {
380 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
381 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
== IndividualStyles
;
386 int LineAnnotation::Style(int line
) const {
387 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
388 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
;
393 const char *LineAnnotation::Text(int line
) const {
394 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
395 return annotations
[line
]+sizeof(AnnotationHeader
);
400 const unsigned char *LineAnnotation::Styles(int line
) const {
401 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
] && MultipleStyles(line
))
402 return reinterpret_cast<unsigned char *>(annotations
[line
] + sizeof(AnnotationHeader
) + Length(line
));
407 static char *AllocateAnnotation(int length
, int style
) {
408 size_t len
= sizeof(AnnotationHeader
) + length
+ ((style
== IndividualStyles
) ? length
: 0);
409 char *ret
= new char[len
];
414 void LineAnnotation::SetText(int line
, const char *text
) {
415 if (text
&& (line
>= 0)) {
416 annotations
.EnsureLength(line
+1);
417 int style
= Style(line
);
418 if (annotations
[line
]) {
419 delete []annotations
[line
];
421 annotations
[line
] = AllocateAnnotation(static_cast<int>(strlen(text
)), style
);
422 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
423 pah
->style
= static_cast<short>(style
);
424 pah
->length
= static_cast<int>(strlen(text
));
425 pah
->lines
= static_cast<short>(NumberLines(text
));
426 memcpy(annotations
[line
]+sizeof(AnnotationHeader
), text
, pah
->length
);
428 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
]) {
429 delete []annotations
[line
];
430 annotations
[line
] = 0;
435 void LineAnnotation::ClearAll() {
436 for (int line
= 0; line
< annotations
.Length(); line
++) {
437 delete []annotations
[line
];
438 annotations
[line
] = 0;
440 annotations
.DeleteAll();
443 void LineAnnotation::SetStyle(int line
, int style
) {
444 annotations
.EnsureLength(line
+1);
445 if (!annotations
[line
]) {
446 annotations
[line
] = AllocateAnnotation(0, style
);
448 reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->style
= static_cast<short>(style
);
451 void LineAnnotation::SetStyles(int line
, const unsigned char *styles
) {
453 annotations
.EnsureLength(line
+1);
454 if (!annotations
[line
]) {
455 annotations
[line
] = AllocateAnnotation(0, IndividualStyles
);
457 AnnotationHeader
*pahSource
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
458 if (pahSource
->style
!= IndividualStyles
) {
459 char *allocation
= AllocateAnnotation(pahSource
->length
, IndividualStyles
);
460 AnnotationHeader
*pahAlloc
= reinterpret_cast<AnnotationHeader
*>(allocation
);
461 pahAlloc
->length
= pahSource
->length
;
462 pahAlloc
->lines
= pahSource
->lines
;
463 memcpy(allocation
+ sizeof(AnnotationHeader
), annotations
[line
] + sizeof(AnnotationHeader
), pahSource
->length
);
464 delete []annotations
[line
];
465 annotations
[line
] = allocation
;
468 AnnotationHeader
*pah
= reinterpret_cast<AnnotationHeader
*>(annotations
[line
]);
469 pah
->style
= IndividualStyles
;
470 memcpy(annotations
[line
] + sizeof(AnnotationHeader
) + pah
->length
, styles
, pah
->length
);
474 int LineAnnotation::Length(int line
) const {
475 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
476 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->length
;
481 int LineAnnotation::Lines(int line
) const {
482 if (annotations
.Length() && (line
>= 0) && (line
< annotations
.Length()) && annotations
[line
])
483 return reinterpret_cast<AnnotationHeader
*>(annotations
[line
])->lines
;