wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / stc / scintilla / src / PerLine.cxx
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.
7
8 #include <string.h>
9
10 #include "Platform.h"
11
12 #include "Scintilla.h"
13 #include "SplitVector.h"
14 #include "Partitioning.h"
15 #include "CellBuffer.h"
16 #include "PerLine.h"
17
18 #ifdef SCI_NAMESPACE
19 using namespace Scintilla;
20 #endif
21
22 MarkerHandleSet::MarkerHandleSet() {
23 root = 0;
24 }
25
26 MarkerHandleSet::~MarkerHandleSet() {
27 MarkerHandleNumber *mhn = root;
28 while (mhn) {
29 MarkerHandleNumber *mhnToFree = mhn;
30 mhn = mhn->next;
31 delete mhnToFree;
32 }
33 root = 0;
34 }
35
36 int MarkerHandleSet::Length() const {
37 int c = 0;
38 MarkerHandleNumber *mhn = root;
39 while (mhn) {
40 c++;
41 mhn = mhn->next;
42 }
43 return c;
44 }
45
46 int MarkerHandleSet::NumberFromHandle(int handle) const {
47 MarkerHandleNumber *mhn = root;
48 while (mhn) {
49 if (mhn->handle == handle) {
50 return mhn->number;
51 }
52 mhn = mhn->next;
53 }
54 return - 1;
55 }
56
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;
63 }
64 return m;
65 }
66
67 bool MarkerHandleSet::Contains(int handle) const {
68 MarkerHandleNumber *mhn = root;
69 while (mhn) {
70 if (mhn->handle == handle) {
71 return true;
72 }
73 mhn = mhn->next;
74 }
75 return false;
76 }
77
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;
87 }
88
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;
97 }
98 pmhn = &((*pmhn)->next);
99 }
100 }
101
102 bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) {
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 if (!all)
112 break;
113 } else {
114 pmhn = &((*pmhn)->next);
115 }
116 }
117 return performedDeletion;
118 }
119
120 void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
121 MarkerHandleNumber **pmhn = &root;
122 while (*pmhn) {
123 pmhn = &((*pmhn)->next);
124 }
125 *pmhn = other->root;
126 other->root = 0;
127 }
128
129 LineMarkers::~LineMarkers() {
130 Init();
131 }
132
133 void LineMarkers::Init() {
134 for (int line = 0; line < markers.Length(); line++) {
135 delete markers[line];
136 markers[line] = 0;
137 }
138 markers.DeleteAll();
139 }
140
141 void LineMarkers::InsertLine(int line) {
142 if (markers.Length()) {
143 markers.Insert(line, 0);
144 }
145 }
146
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()) {
150 if (line > 0) {
151 MergeMarkers(line - 1);
152 }
153 markers.Delete(line);
154 }
155 }
156
157 int LineMarkers::LineFromHandle(int markerHandle) {
158 if (markers.Length()) {
159 for (int line = 0; line < markers.Length(); line++) {
160 if (markers[line]) {
161 if (markers[line]->Contains(markerHandle)) {
162 return line;
163 }
164 }
165 }
166 }
167 return -1;
168 }
169
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;
177 }
178 }
179
180 int LineMarkers::MarkValue(int line) {
181 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
182 return markers[line]->MarkValue();
183 else
184 return 0;
185 }
186
187 int LineMarkers::MarkerNext(int lineStart, int mask) const {
188 if (lineStart < 0)
189 lineStart = 0;
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)
195 return iLine;
196 }
197 return -1;
198 }
199
200 int LineMarkers::AddMark(int line, int markerNum, int lines) {
201 handleCurrent++;
202 if (!markers.Length()) {
203 // No existing markers so allocate one element per line
204 markers.InsertValue(0, lines, 0);
205 }
206 if (line >= markers.Length()) {
207 return -1;
208 }
209 if (!markers[line]) {
210 // Need new structure to hold marker handle
211 markers[line] = new MarkerHandleSet();
212 if (!markers[line])
213 return -1;
214 }
215 markers[line]->InsertHandle(handleCurrent, markerNum);
216
217 return handleCurrent;
218 }
219
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) {
224 someChanges = true;
225 delete markers[line];
226 markers[line] = NULL;
227 } else {
228 someChanges = markers[line]->RemoveNumber(markerNum, all);
229 if (markers[line]->Length() == 0) {
230 delete markers[line];
231 markers[line] = NULL;
232 }
233 }
234 }
235 return someChanges;
236 }
237
238 void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
239 int line = LineFromHandle(markerHandle);
240 if (line >= 0) {
241 markers[line]->RemoveHandle(markerHandle);
242 if (markers[line]->Length() == 0) {
243 delete markers[line];
244 markers[line] = NULL;
245 }
246 }
247 }
248
249 LineLevels::~LineLevels() {
250 }
251
252 void LineLevels::Init() {
253 levels.DeleteAll();
254 }
255
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);
260 }
261 }
262
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;
268 levels.Delete(line);
269 if (line == levels.Length()-1) // Last line loses the header flag
270 levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
271 else if (line > 0)
272 levels[line-1] |= firstHeader;
273 }
274 }
275
276 void LineLevels::ExpandLevels(int sizeNew) {
277 levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
278 }
279
280 void LineLevels::ClearLevels() {
281 levels.DeleteAll();
282 }
283
284 int LineLevels::SetLevel(int line, int level, int lines) {
285 int prev = 0;
286 if ((line >= 0) && (line < lines)) {
287 if (!levels.Length()) {
288 ExpandLevels(lines + 1);
289 }
290 prev = levels[line];
291 if (prev != level) {
292 levels[line] = level;
293 }
294 }
295 return prev;
296 }
297
298 int LineLevels::GetLevel(int line) {
299 if (levels.Length() && (line >= 0) && (line < levels.Length())) {
300 return levels[line];
301 } else {
302 return SC_FOLDLEVELBASE;
303 }
304 }
305
306 LineState::~LineState() {
307 }
308
309 void LineState::Init() {
310 lineStates.DeleteAll();
311 }
312
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);
318 }
319 }
320
321 void LineState::RemoveLine(int line) {
322 if (lineStates.Length() > line) {
323 lineStates.Delete(line);
324 }
325 }
326
327 int LineState::SetLineState(int line, int state) {
328 lineStates.EnsureLength(line + 1);
329 int stateOld = lineStates[line];
330 lineStates[line] = state;
331 return stateOld;
332 }
333
334 int LineState::GetLineState(int line) {
335 if (line < 0)
336 return 0;
337 lineStates.EnsureLength(line + 1);
338 return lineStates[line];
339 }
340
341 int LineState::GetMaxLineState() {
342 return lineStates.Length();
343 }
344
345 static int NumberLines(const char *text) {
346 if (text) {
347 int newLines = 0;
348 while (*text) {
349 if (*text == '\n')
350 newLines++;
351 text++;
352 }
353 return newLines+1;
354 } else {
355 return 0;
356 }
357 }
358
359 // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
360 // and then has text and optional styles.
361
362 static const int IndividualStyles = 0x100;
363
364 struct AnnotationHeader {
365 short style; // Style IndividualStyles implies array of styles
366 short lines;
367 int length;
368 };
369
370 LineAnnotation::~LineAnnotation() {
371 ClearAll();
372 }
373
374 void LineAnnotation::Init() {
375 ClearAll();
376 }
377
378 void LineAnnotation::InsertLine(int line) {
379 if (annotations.Length()) {
380 annotations.EnsureLength(line);
381 annotations.Insert(line, 0);
382 }
383 }
384
385 void LineAnnotation::RemoveLine(int line) {
386 if (annotations.Length() && (line < annotations.Length())) {
387 delete []annotations[line];
388 annotations.Delete(line);
389 }
390 }
391
392 bool LineAnnotation::AnySet() const {
393 return annotations.Length() > 0;
394 }
395
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;
399 else
400 return 0;
401 }
402
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;
406 else
407 return 0;
408 }
409
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);
413 else
414 return 0;
415 }
416
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));
420 else
421 return 0;
422 }
423
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];
427 memset(ret, 0, len);
428 return ret;
429 }
430
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];
437 }
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);
444 } else {
445 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) {
446 delete []annotations[line];
447 annotations[line] = 0;
448 }
449 }
450 }
451
452 void LineAnnotation::ClearAll() {
453 for (int line = 0; line < annotations.Length(); line++) {
454 delete []annotations[line];
455 annotations[line] = 0;
456 }
457 annotations.DeleteAll();
458 }
459
460 void LineAnnotation::SetStyle(int line, int style) {
461 annotations.EnsureLength(line+1);
462 if (!annotations[line]) {
463 annotations[line] = AllocateAnnotation(0, style);
464 }
465 reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
466 }
467
468 void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
469 if (line >= 0) {
470 annotations.EnsureLength(line+1);
471 if (!annotations[line]) {
472 annotations[line] = AllocateAnnotation(0, IndividualStyles);
473 } else {
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;
483 }
484 }
485 AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
486 pah->style = IndividualStyles;
487 memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
488 }
489 }
490
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;
494 else
495 return 0;
496 }
497
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;
501 else
502 return 0;
503 }