upgraded to scintilla 3.2.0
[TortoiseGit.git] / ext / scintilla / src / PerLine.cxx
blobc5c0077ba5ab44314d8fae3473c7748bdddcaf73
1 // Scintilla source code edit control
2 /** @file PerLine.cxx
3 ** Manages data associated with each line of the document
4 **/
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.
8 #include <string.h>
10 #include "Platform.h"
12 #include "Scintilla.h"
13 #include "SplitVector.h"
14 #include "Partitioning.h"
15 #include "CellBuffer.h"
16 #include "PerLine.h"
18 #ifdef SCI_NAMESPACE
19 using namespace Scintilla;
20 #endif
22 MarkerHandleSet::MarkerHandleSet() {
23 root = 0;
26 MarkerHandleSet::~MarkerHandleSet() {
27 MarkerHandleNumber *mhn = root;
28 while (mhn) {
29 MarkerHandleNumber *mhnToFree = mhn;
30 mhn = mhn->next;
31 delete mhnToFree;
33 root = 0;
36 int MarkerHandleSet::Length() const {
37 int c = 0;
38 MarkerHandleNumber *mhn = root;
39 while (mhn) {
40 c++;
41 mhn = mhn->next;
43 return c;
46 int MarkerHandleSet::NumberFromHandle(int handle) const {
47 MarkerHandleNumber *mhn = root;
48 while (mhn) {
49 if (mhn->handle == handle) {
50 return mhn->number;
52 mhn = mhn->next;
54 return - 1;
57 int MarkerHandleSet::MarkValue() const {
58 unsigned int m = 0;
59 MarkerHandleNumber *mhn = root;
60 while (mhn) {
61 m |= (1 << mhn->number);
62 mhn = mhn->next;
64 return m;
67 bool MarkerHandleSet::Contains(int handle) const {
68 MarkerHandleNumber *mhn = root;
69 while (mhn) {
70 if (mhn->handle == handle) {
71 return true;
73 mhn = mhn->next;
75 return false;
78 bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
79 MarkerHandleNumber *mhn = new MarkerHandleNumber;
80 if (!mhn)
81 return false;
82 mhn->handle = handle;
83 mhn->number = markerNum;
84 mhn->next = root;
85 root = mhn;
86 return true;
89 void MarkerHandleSet::RemoveHandle(int handle) {
90 MarkerHandleNumber **pmhn = &root;
91 while (*pmhn) {
92 MarkerHandleNumber *mhn = *pmhn;
93 if (mhn->handle == handle) {
94 *pmhn = mhn->next;
95 delete mhn;
96 return;
98 pmhn = &((*pmhn)->next);
102 bool MarkerHandleSet::RemoveNumber(int markerNum) {
103 bool performedDeletion = false;
104 MarkerHandleNumber **pmhn = &root;
105 while (*pmhn) {
106 MarkerHandleNumber *mhn = *pmhn;
107 if (mhn->number == markerNum) {
108 *pmhn = mhn->next;
109 delete mhn;
110 performedDeletion = true;
111 } else {
112 pmhn = &((*pmhn)->next);
115 return performedDeletion;
118 void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
119 MarkerHandleNumber **pmhn = &root;
120 while (*pmhn) {
121 pmhn = &((*pmhn)->next);
123 *pmhn = other->root;
124 other->root = 0;
127 LineMarkers::~LineMarkers() {
128 Init();
131 void LineMarkers::Init() {
132 for (int line = 0; line < markers.Length(); line++) {
133 delete markers[line];
134 markers[line] = 0;
136 markers.DeleteAll();
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()) {
148 if (line > 0) {
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++) {
158 if (markers[line]) {
159 if (markers[line]->Contains(markerHandle)) {
160 return line;
165 return -1;
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();
181 else
182 return 0;
185 int LineMarkers::MarkerNext(int lineStart, int mask) const {
186 if (lineStart < 0)
187 lineStart = 0;
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)
193 return iLine;
195 return -1;
198 int LineMarkers::AddMark(int line, int markerNum, int lines) {
199 handleCurrent++;
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()) {
205 return -1;
207 if (!markers[line]) {
208 // Need new structure to hold marker handle
209 markers[line] = new MarkerHandleSet();
210 if (!markers[line])
211 return -1;
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) {
222 someChanges = true;
223 delete markers[line];
224 markers[line] = NULL;
225 } else {
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;
238 return someChanges;
241 void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
242 int line = LineFromHandle(markerHandle);
243 if (line >= 0) {
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() {
256 levels.DeleteAll();
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;
271 levels.Delete(line);
272 if (line == levels.Length()-1) // Last line loses the header flag
273 levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
274 else if (line > 0)
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() {
284 levels.DeleteAll();
287 int LineLevels::SetLevel(int line, int level, int lines) {
288 int prev = 0;
289 if ((line >= 0) && (line < lines)) {
290 if (!levels.Length()) {
291 ExpandLevels(lines + 1);
293 prev = levels[line];
294 if (prev != level) {
295 levels[line] = level;
298 return prev;
301 int LineLevels::GetLevel(int line) {
302 if (levels.Length() && (line >= 0) && (line < levels.Length())) {
303 return levels[line];
304 } else {
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;
334 return stateOld;
337 int LineState::GetLineState(int line) {
338 if (line < 0)
339 return 0;
340 lineStates.EnsureLength(line + 1);
341 return lineStates[line];
344 int LineState::GetMaxLineState() {
345 return lineStates.Length();
348 static int NumberLines(const char *text) {
349 if (text) {
350 int newLines = 0;
351 while (*text) {
352 if (*text == '\n')
353 newLines++;
354 text++;
356 return newLines+1;
357 } else {
358 return 0;
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
369 short lines;
370 int length;
373 LineAnnotation::~LineAnnotation() {
374 ClearAll();
377 void LineAnnotation::Init() {
378 ClearAll();
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;
402 else
403 return 0;
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;
409 else
410 return 0;
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);
416 else
417 return 0;
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));
423 else
424 return 0;
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];
430 memset(ret, 0, len);
431 return ret;
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);
447 } else {
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) {
472 if (line >= 0) {
473 annotations.EnsureLength(line+1);
474 if (!annotations[line]) {
475 annotations[line] = AllocateAnnotation(0, IndividualStyles);
476 } else {
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;
497 else
498 return 0;
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;
504 else
505 return 0;