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) {
103
bool performedDeletion = false;
104
MarkerHandleNumber **pmhn = &root;
106
MarkerHandleNumber *mhn = *pmhn;
107
if (mhn->number == markerNum) {
110
performedDeletion = true;
112
pmhn = &((*pmhn)->next);
115
return performedDeletion;
118
void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
119
MarkerHandleNumber **pmhn = &root;
121
pmhn = &((*pmhn)->next);
127
LineMarkers::~LineMarkers() {
131
void LineMarkers::Init() {
132
for (int line = 0; line < markers.Length(); line++) {
133
delete markers[line];
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()) {
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++) {
159
if (markers[line]->Contains(markerHandle)) {
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();
185
int LineMarkers::AddMark(int line, int markerNum, int lines) {
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()) {
194
if (!markers[line]) {
195
// Need new structure to hold marker handle
196
markers[line] = new MarkerHandleSet();
200
markers[line]->InsertHandle(handleCurrent, markerNum);
202
return handleCurrent;
205
void LineMarkers::DeleteMark(int line, int markerNum, bool all) {
206
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
207
if (markerNum == -1) {
208
delete markers[line];
209
markers[line] = NULL;
211
bool performedDeletion = markers[line]->RemoveNumber(markerNum);
212
while (all && performedDeletion) {
213
performedDeletion = markers[line]->RemoveNumber(markerNum);
215
if (markers[line]->Length() == 0) {
216
delete markers[line];
217
markers[line] = NULL;
223
void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
224
int line = LineFromHandle(markerHandle);
226
markers[line]->RemoveHandle(markerHandle);
227
if (markers[line]->Length() == 0) {
228
delete markers[line];
229
markers[line] = NULL;
234
LineLevels::~LineLevels() {
237
void LineLevels::Init() {
241
void LineLevels::InsertLine(int line) {
242
if (levels.Length()) {
243
int level = SC_FOLDLEVELBASE;
244
if ((line > 0) && (line < levels.Length())) {
245
level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
247
levels.InsertValue(line, 1, level);
251
void LineLevels::RemoveLine(int line) {
252
if (levels.Length()) {
253
// Move up following lines but merge header flag from this line
254
// to line before to avoid a temporary disappearence causing expansion.
255
int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
257
if (line == levels.Length()-1) // Last line loses the header flag
258
levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
260
levels[line-1] |= firstHeader;
264
void LineLevels::ExpandLevels(int sizeNew) {
265
levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
268
void LineLevels::ClearLevels() {
272
int LineLevels::SetLevel(int line, int level, int lines) {
274
if ((line >= 0) && (line < lines)) {
275
if (!levels.Length()) {
276
ExpandLevels(lines + 1);
280
levels[line] = level;
286
int LineLevels::GetLevel(int line) {
287
if (levels.Length() && (line >= 0) && (line < levels.Length())) {
290
return SC_FOLDLEVELBASE;
294
LineState::~LineState() {
297
void LineState::Init() {
298
lineStates.DeleteAll();
301
void LineState::InsertLine(int line) {
302
if (lineStates.Length()) {
303
lineStates.EnsureLength(line);
304
lineStates.Insert(line, 0);
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) {
322
lineStates.EnsureLength(line + 1);
323
return lineStates[line];
326
int LineState::GetMaxLineState() {
327
return lineStates.Length();
330
static int NumberLines(const char *text) {
344
// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
345
// and then has text and optional styles.
347
static const int IndividualStyles = 0x100;
349
struct AnnotationHeader {
350
short style; // Style IndividualStyles implies array of styles
355
LineAnnotation::~LineAnnotation() {
359
void LineAnnotation::Init() {
363
void LineAnnotation::InsertLine(int line) {
364
if (annotations.Length()) {
365
annotations.EnsureLength(line);
366
annotations.Insert(line, 0);
370
void LineAnnotation::RemoveLine(int line) {
371
if (annotations.Length() && (line < annotations.Length())) {
372
delete []annotations[line];
373
annotations.Delete(line);
377
bool LineAnnotation::AnySet() const {
378
return annotations.Length() > 0;
381
bool LineAnnotation::MultipleStyles(int line) const {
382
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
383
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
388
int LineAnnotation::Style(int line) {
389
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
390
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
395
const char *LineAnnotation::Text(int line) const {
396
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
397
return annotations[line]+sizeof(AnnotationHeader);
402
const unsigned char *LineAnnotation::Styles(int line) const {
403
if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
404
return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
409
static char *AllocateAnnotation(int length, int style) {
410
size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
411
char *ret = new char[len];
416
void LineAnnotation::SetText(int line, const char *text) {
418
annotations.EnsureLength(line+1);
419
int style = Style(line);
420
if (annotations[line]) {
421
delete []annotations[line];
423
annotations[line] = AllocateAnnotation(strlen(text), style);
424
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
425
pah->style = static_cast<short>(style);
426
pah->length = strlen(text);
427
pah->lines = static_cast<short>(NumberLines(text));
428
memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
430
if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
431
delete []annotations[line];
432
annotations[line] = 0;
437
void LineAnnotation::ClearAll() {
438
for (int line = 0; line < annotations.Length(); line++) {
439
delete []annotations[line];
440
annotations[line] = 0;
442
annotations.DeleteAll();
445
void LineAnnotation::SetStyle(int line, int style) {
446
annotations.EnsureLength(line+1);
447
if (!annotations[line]) {
448
annotations[line] = AllocateAnnotation(0, style);
450
reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
453
void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
454
annotations.EnsureLength(line+1);
455
if (!annotations[line]) {
456
annotations[line] = AllocateAnnotation(0, IndividualStyles);
458
AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
459
if (pahSource->style != IndividualStyles) {
460
char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
461
AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
462
pahAlloc->length = pahSource->length;
463
pahAlloc->lines = pahSource->lines;
464
memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
465
delete []annotations[line];
466
annotations[line] = allocation;
469
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
470
pah->style = IndividualStyles;
471
memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
474
int LineAnnotation::Length(int line) const {
475
if (annotations.Length() && (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 < annotations.Length()) && annotations[line])
483
return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;