Move document encoding conversion with BOM support to encodings.[ch]
[geany-mirror.git] / scintilla / src / PerLine.cxx
blob8fc6e2531fd0cab0016f5fdb84439596d50eb0fd
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::AddMark(int line, int markerNum, int lines) {
186 handleCurrent++;
187 if (!markers.Length()) {
188 // No existing markers so allocate one element per line
189 markers.InsertValue(0, lines, 0);
191 if (line >= markers.Length()) {
192 return -1;
194 if (!markers[line]) {
195 // Need new structure to hold marker handle
196 markers[line] = new MarkerHandleSet();
197 if (!markers[line])
198 return -1;
200 markers[line]->InsertHandle(handleCurrent, markerNum);
202 return handleCurrent;
205 bool LineMarkers::DeleteMark(int line, int markerNum, bool all) {
206 bool someChanges = false;
207 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
208 if (markerNum == -1) {
209 someChanges = true;
210 delete markers[line];
211 markers[line] = NULL;
212 } else {
213 bool performedDeletion = markers[line]->RemoveNumber(markerNum);
214 someChanges = someChanges || performedDeletion;
215 while (all && performedDeletion) {
216 performedDeletion = markers[line]->RemoveNumber(markerNum);
217 someChanges = someChanges || performedDeletion;
219 if (markers[line]->Length() == 0) {
220 delete markers[line];
221 markers[line] = NULL;
225 return someChanges;
228 void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
229 int line = LineFromHandle(markerHandle);
230 if (line >= 0) {
231 markers[line]->RemoveHandle(markerHandle);
232 if (markers[line]->Length() == 0) {
233 delete markers[line];
234 markers[line] = NULL;
239 LineLevels::~LineLevels() {
242 void LineLevels::Init() {
243 levels.DeleteAll();
246 void LineLevels::InsertLine(int line) {
247 if (levels.Length()) {
248 int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
249 levels.InsertValue(line, 1, level);
253 void LineLevels::RemoveLine(int line) {
254 if (levels.Length()) {
255 // Move up following lines but merge header flag from this line
256 // to line before to avoid a temporary disappearence causing expansion.
257 int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
258 levels.Delete(line);
259 if (line == levels.Length()-1) // Last line loses the header flag
260 levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
261 else if (line > 0)
262 levels[line-1] |= firstHeader;
266 void LineLevels::ExpandLevels(int sizeNew) {
267 levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
270 void LineLevels::ClearLevels() {
271 levels.DeleteAll();
274 int LineLevels::SetLevel(int line, int level, int lines) {
275 int prev = 0;
276 if ((line >= 0) && (line < lines)) {
277 if (!levels.Length()) {
278 ExpandLevels(lines + 1);
280 prev = levels[line];
281 if (prev != level) {
282 levels[line] = level;
285 return prev;
288 int LineLevels::GetLevel(int line) {
289 if (levels.Length() && (line >= 0) && (line < levels.Length())) {
290 return levels[line];
291 } else {
292 return SC_FOLDLEVELBASE;
296 LineState::~LineState() {
299 void LineState::Init() {
300 lineStates.DeleteAll();
303 void LineState::InsertLine(int line) {
304 if (lineStates.Length()) {
305 lineStates.EnsureLength(line);
306 int val = (line < lineStates.Length()) ? lineStates[line] : 0;
307 lineStates.Insert(line, val);
311 void LineState::RemoveLine(int line) {
312 if (lineStates.Length() > line) {
313 lineStates.Delete(line);
317 int LineState::SetLineState(int line, int state) {
318 lineStates.EnsureLength(line + 1);
319 int stateOld = lineStates[line];
320 lineStates[line] = state;
321 return stateOld;
324 int LineState::GetLineState(int line) {
325 if (line < 0)
326 return 0;
327 lineStates.EnsureLength(line + 1);
328 return lineStates[line];
331 int LineState::GetMaxLineState() {
332 return lineStates.Length();
335 static int NumberLines(const char *text) {
336 if (text) {
337 int newLines = 0;
338 while (*text) {
339 if (*text == '\n')
340 newLines++;
341 text++;
343 return newLines+1;
344 } else {
345 return 0;
349 // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
350 // and then has text and optional styles.
352 static const int IndividualStyles = 0x100;
354 struct AnnotationHeader {
355 short style; // Style IndividualStyles implies array of styles
356 short lines;
357 int length;
360 LineAnnotation::~LineAnnotation() {
361 ClearAll();
364 void LineAnnotation::Init() {
365 ClearAll();
368 void LineAnnotation::InsertLine(int line) {
369 if (annotations.Length()) {
370 annotations.EnsureLength(line);
371 annotations.Insert(line, 0);
375 void LineAnnotation::RemoveLine(int line) {
376 if (annotations.Length() && (line < annotations.Length())) {
377 delete []annotations[line];
378 annotations.Delete(line);
382 bool LineAnnotation::AnySet() const {
383 return annotations.Length() > 0;
386 bool LineAnnotation::MultipleStyles(int line) const {
387 if (annotations.Length() && (line < annotations.Length()) && annotations[line])
388 return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
389 else
390 return 0;
393 int LineAnnotation::Style(int line) {
394 if (annotations.Length() && (line < annotations.Length()) && annotations[line])
395 return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
396 else
397 return 0;
400 const char *LineAnnotation::Text(int line) const {
401 if (annotations.Length() && (line < annotations.Length()) && annotations[line])
402 return annotations[line]+sizeof(AnnotationHeader);
403 else
404 return 0;
407 const unsigned char *LineAnnotation::Styles(int line) const {
408 if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
409 return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
410 else
411 return 0;
414 static char *AllocateAnnotation(int length, int style) {
415 size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
416 char *ret = new char[len];
417 memset(ret, 0, len);
418 return ret;
421 void LineAnnotation::SetText(int line, const char *text) {
422 if (text) {
423 annotations.EnsureLength(line+1);
424 int style = Style(line);
425 if (annotations[line]) {
426 delete []annotations[line];
428 annotations[line] = AllocateAnnotation(strlen(text), style);
429 AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
430 pah->style = static_cast<short>(style);
431 pah->length = strlen(text);
432 pah->lines = static_cast<short>(NumberLines(text));
433 memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
434 } else {
435 if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
436 delete []annotations[line];
437 annotations[line] = 0;
442 void LineAnnotation::ClearAll() {
443 for (int line = 0; line < annotations.Length(); line++) {
444 delete []annotations[line];
445 annotations[line] = 0;
447 annotations.DeleteAll();
450 void LineAnnotation::SetStyle(int line, int style) {
451 annotations.EnsureLength(line+1);
452 if (!annotations[line]) {
453 annotations[line] = AllocateAnnotation(0, style);
455 reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
458 void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
459 annotations.EnsureLength(line+1);
460 if (!annotations[line]) {
461 annotations[line] = AllocateAnnotation(0, IndividualStyles);
462 } else {
463 AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
464 if (pahSource->style != IndividualStyles) {
465 char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
466 AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
467 pahAlloc->length = pahSource->length;
468 pahAlloc->lines = pahSource->lines;
469 memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
470 delete []annotations[line];
471 annotations[line] = allocation;
474 AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
475 pah->style = IndividualStyles;
476 memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
479 int LineAnnotation::Length(int line) const {
480 if (annotations.Length() && (line < annotations.Length()) && annotations[line])
481 return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
482 else
483 return 0;
486 int LineAnnotation::Lines(int line) const {
487 if (annotations.Length() && (line < annotations.Length()) && annotations[line])
488 return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
489 else
490 return 0;