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() {
128
for (int line = 0; line < markers.Length(); line++) {
129
delete markers[line];
135
void LineMarkers::InsertLine(int line) {
136
if (markers.Length()) {
137
markers.Insert(line, 0);
141
void LineMarkers::RemoveLine(int line) {
142
// Retain the markers from the deleted line by oring them into the previous line
143
if (markers.Length()) {
145
MergeMarkers(line - 1);
147
markers.Delete(line);
151
int LineMarkers::LineFromHandle(int markerHandle) {
152
if (markers.Length()) {
153
for (int line = 0; line < markers.Length(); line++) {
155
if (markers[line]->Contains(markerHandle)) {
164
void LineMarkers::MergeMarkers(int pos) {
165
if (markers[pos + 1] != NULL) {
166
if (markers[pos] == NULL)
167
markers[pos] = new MarkerHandleSet;
168
markers[pos]->CombineWith(markers[pos + 1]);
169
delete markers[pos + 1];
170
markers[pos + 1] = NULL;
174
int LineMarkers::MarkValue(int line) {
175
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
176
return markers[line]->MarkValue();
181
int LineMarkers::AddMark(int line, int markerNum, int lines) {
183
if (!markers.Length()) {
184
// No existing markers so allocate one element per line
185
markers.InsertValue(0, lines, 0);
187
if (!markers[line]) {
188
// Need new structure to hold marker handle
189
markers[line] = new MarkerHandleSet();
193
markers[line]->InsertHandle(handleCurrent, markerNum);
195
return handleCurrent;
198
void LineMarkers::DeleteMark(int line, int markerNum, bool all) {
199
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
200
if (markerNum == -1) {
201
delete markers[line];
202
markers[line] = NULL;
204
bool performedDeletion = markers[line]->RemoveNumber(markerNum);
205
while (all && performedDeletion) {
206
performedDeletion = markers[line]->RemoveNumber(markerNum);
208
if (markers[line]->Length() == 0) {
209
delete markers[line];
210
markers[line] = NULL;
216
void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
217
int line = LineFromHandle(markerHandle);
219
markers[line]->RemoveHandle(markerHandle);
220
if (markers[line]->Length() == 0) {
221
delete markers[line];
222
markers[line] = NULL;
227
LineLevels::~LineLevels() {
230
void LineLevels::InsertLine(int line) {
231
if (levels.Length()) {
232
int level = SC_FOLDLEVELBASE;
233
if ((line > 0) && (line < levels.Length())) {
234
level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
236
levels.InsertValue(line, 1, level);
240
void LineLevels::RemoveLine(int line) {
241
if (levels.Length()) {
242
// Move up following lines but merge header flag from this line
243
// to line before to avoid a temporary disappearence causing expansion.
244
int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
247
levels[line-1] |= firstHeader;
251
void LineLevels::ExpandLevels(int sizeNew) {
252
levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
255
void LineLevels::ClearLevels() {
259
int LineLevels::SetLevel(int line, int level, int lines) {
261
if ((line >= 0) && (line < lines)) {
262
if (!levels.Length()) {
263
ExpandLevels(lines + 1);
267
levels[line] = level;
273
int LineLevels::GetLevel(int line) {
274
if (levels.Length() && (line >= 0) && (line < levels.Length())) {
277
return SC_FOLDLEVELBASE;
281
LineState::~LineState() {
284
void LineState::InsertLine(int line) {
285
if (lineStates.Length()) {
286
lineStates.EnsureLength(line);
287
lineStates.Insert(line, 0);
291
void LineState::RemoveLine(int line) {
292
if (lineStates.Length() > line) {
293
lineStates.Delete(line);
297
int LineState::SetLineState(int line, int state) {
298
lineStates.EnsureLength(line + 1);
299
int stateOld = lineStates[line];
300
lineStates[line] = state;
304
int LineState::GetLineState(int line) {
305
lineStates.EnsureLength(line + 1);
306
return lineStates[line];
309
int LineState::GetMaxLineState() {
310
return lineStates.Length();
313
static int NumberLines(const char *text) {
327
// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
328
// and then has text and optional styles.
330
static const int IndividualStyles = 0x100;
332
struct AnnotationHeader {
333
short style; // Style IndividualStyles implies array of styles
338
LineAnnotation::~LineAnnotation() {
342
void LineAnnotation::InsertLine(int line) {
343
if (annotations.Length()) {
344
annotations.Insert(line, 0);
348
void LineAnnotation::RemoveLine(int line) {
349
if (annotations.Length() && (line < annotations.Length())) {
350
delete []annotations[line];
351
annotations.Delete(line);
355
bool LineAnnotation::AnySet() const {
356
return annotations.Length() > 0;
359
bool LineAnnotation::MultipleStyles(int line) const {
360
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
361
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
366
int LineAnnotation::Style(int line) {
367
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
368
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
373
const char *LineAnnotation::Text(int line) const {
374
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
375
return annotations[line]+sizeof(AnnotationHeader);
380
const unsigned char *LineAnnotation::Styles(int line) const {
381
if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
382
return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
387
static char *AllocateAnnotation(int length, int style) {
388
size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
389
char *ret = new char[len];
394
void LineAnnotation::SetText(int line, const char *text) {
396
annotations.EnsureLength(line+1);
397
int style = Style(line);
398
if (annotations[line]) {
399
delete []annotations[line];
401
annotations[line] = AllocateAnnotation(strlen(text), style);
402
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader*>(annotations[line]);
403
pah->style = static_cast<short>(style);
404
pah->length = strlen(text);
405
pah->lines = static_cast<short>(NumberLines(text));
406
memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
408
if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
409
delete []annotations[line];
410
annotations[line] = 0;
415
void LineAnnotation::ClearAll() {
416
for (int line = 0; line < annotations.Length(); line++) {
417
delete []annotations[line];
418
annotations[line] = 0;
420
annotations.DeleteAll();
423
void LineAnnotation::SetStyle(int line, int style) {
424
annotations.EnsureLength(line+1);
425
if (!annotations[line]) {
426
annotations[line] = AllocateAnnotation(0, style);
428
reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
431
void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
432
annotations.EnsureLength(line+1);
433
if (!annotations[line]) {
434
annotations[line] = AllocateAnnotation(0, IndividualStyles);
436
AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
437
if (pahSource->style != IndividualStyles) {
438
char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
439
AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
440
pahAlloc->length = pahSource->length;
441
pahAlloc->lines = pahSource->lines;
442
memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
443
delete []annotations[line];
444
annotations[line] = allocation;
447
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
448
pah->style = IndividualStyles;
449
memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
452
int LineAnnotation::Length(int line) const {
453
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
454
return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
459
int LineAnnotation::Lines(int line) const {
460
if (annotations.Length() && (line < annotations.Length()) && annotations[line])
461
return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;