~ubuntu-branches/ubuntu/karmic/qscintilla2/karmic

« back to all changes in this revision

Viewing changes to src/PerLine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Marek
  • Date: 2009-06-20 12:11:11 UTC
  • mfrom: (1.1.3 upstream) (5.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090620121111-6xsr2u1usw62eprl
Tags: 2.4-3
* Upload rebuilt packages
* Fixes segfault on import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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) {
 
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);
 
113
                }
 
114
        }
 
115
        return performedDeletion;
 
116
}
 
117
 
 
118
void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
 
119
        MarkerHandleNumber **pmhn = &root;
 
120
        while (*pmhn) {
 
121
                pmhn = &((*pmhn)->next);
 
122
        }
 
123
        *pmhn = other->root;
 
124
        other->root = 0;
 
125
}
 
126
 
 
127
LineMarkers::~LineMarkers() {
 
128
        for (int line = 0; line < markers.Length(); line++) {
 
129
                delete markers[line];
 
130
                markers[line] = 0;
 
131
        }
 
132
        markers.DeleteAll();
 
133
}
 
134
 
 
135
void LineMarkers::InsertLine(int line) {
 
136
        if (markers.Length()) {
 
137
                markers.Insert(line, 0);
 
138
        }
 
139
}
 
140
 
 
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()) {
 
144
                if (line > 0) {
 
145
                        MergeMarkers(line - 1);
 
146
                }
 
147
                markers.Delete(line);
 
148
        }
 
149
}
 
150
 
 
151
int LineMarkers::LineFromHandle(int markerHandle) {
 
152
        if (markers.Length()) {
 
153
                for (int line = 0; line < markers.Length(); line++) {
 
154
                        if (markers[line]) {
 
155
                                if (markers[line]->Contains(markerHandle)) {
 
156
                                        return line;
 
157
                                }
 
158
                        }
 
159
                }
 
160
        }
 
161
        return -1;
 
162
}
 
163
 
 
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;
 
171
        }
 
172
}
 
173
 
 
174
int LineMarkers::MarkValue(int line) {
 
175
        if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
 
176
                return markers[line]->MarkValue();
 
177
        else
 
178
                return 0;
 
179
}
 
180
 
 
181
int LineMarkers::AddMark(int line, int markerNum, int lines) {
 
182
        handleCurrent++;
 
183
        if (!markers.Length()) {
 
184
                // No existing markers so allocate one element per line
 
185
                markers.InsertValue(0, lines, 0);
 
186
        }
 
187
        if (!markers[line]) {
 
188
                // Need new structure to hold marker handle
 
189
                markers[line] = new MarkerHandleSet();
 
190
                if (!markers[line])
 
191
                        return - 1;
 
192
        }
 
193
        markers[line]->InsertHandle(handleCurrent, markerNum);
 
194
 
 
195
        return handleCurrent;
 
196
}
 
197
 
 
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;
 
203
                } else {
 
204
                        bool performedDeletion = markers[line]->RemoveNumber(markerNum);
 
205
                        while (all && performedDeletion) {
 
206
                                performedDeletion = markers[line]->RemoveNumber(markerNum);
 
207
                        }
 
208
                        if (markers[line]->Length() == 0) {
 
209
                                delete markers[line];
 
210
                                markers[line] = NULL;
 
211
                        }
 
212
                }
 
213
        }
 
214
}
 
215
 
 
216
void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
 
217
        int line = LineFromHandle(markerHandle);
 
218
        if (line >= 0) {
 
219
                markers[line]->RemoveHandle(markerHandle);
 
220
                if (markers[line]->Length() == 0) {
 
221
                        delete markers[line];
 
222
                        markers[line] = NULL;
 
223
                }
 
224
        }
 
225
}
 
226
 
 
227
LineLevels::~LineLevels() {
 
228
}
 
229
 
 
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;
 
235
                }
 
236
                levels.InsertValue(line, 1, level);
 
237
        }
 
238
}
 
239
 
 
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;
 
245
                levels.Delete(line);
 
246
                if (line > 0)
 
247
                        levels[line-1] |= firstHeader;
 
248
        }
 
249
}
 
250
 
 
251
void LineLevels::ExpandLevels(int sizeNew) {
 
252
        levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
 
253
}
 
254
 
 
255
void LineLevels::ClearLevels() {
 
256
        levels.DeleteAll();
 
257
}
 
258
 
 
259
int LineLevels::SetLevel(int line, int level, int lines) {
 
260
        int prev = 0;
 
261
        if ((line >= 0) && (line < lines)) {
 
262
                if (!levels.Length()) {
 
263
                        ExpandLevels(lines + 1);
 
264
                }
 
265
                prev = levels[line];
 
266
                if (prev != level) {
 
267
                        levels[line] = level;
 
268
                }
 
269
        }
 
270
        return prev;
 
271
}
 
272
 
 
273
int LineLevels::GetLevel(int line) {
 
274
        if (levels.Length() && (line >= 0) && (line < levels.Length())) {
 
275
                return levels[line];
 
276
        } else {
 
277
                return SC_FOLDLEVELBASE;
 
278
        }
 
279
}
 
280
 
 
281
LineState::~LineState() {
 
282
}
 
283
 
 
284
void LineState::InsertLine(int line) {
 
285
        if (lineStates.Length()) {
 
286
                lineStates.EnsureLength(line);
 
287
                lineStates.Insert(line, 0);
 
288
        }
 
289
}
 
290
 
 
291
void LineState::RemoveLine(int line) {
 
292
        if (lineStates.Length() > line) {
 
293
                lineStates.Delete(line);
 
294
        }
 
295
}
 
296
 
 
297
int LineState::SetLineState(int line, int state) {
 
298
        lineStates.EnsureLength(line + 1);
 
299
        int stateOld = lineStates[line];
 
300
        lineStates[line] = state;
 
301
        return stateOld;
 
302
}
 
303
 
 
304
int LineState::GetLineState(int line) {
 
305
        lineStates.EnsureLength(line + 1);
 
306
        return lineStates[line];
 
307
}
 
308
 
 
309
int LineState::GetMaxLineState() {
 
310
        return lineStates.Length();
 
311
}
 
312
 
 
313
static int NumberLines(const char *text) {
 
314
        if (text) {
 
315
                int newLines = 0;
 
316
                while (*text) {
 
317
                        if (*text == '\n')
 
318
                                newLines++;
 
319
                        text++;
 
320
                }
 
321
                return newLines+1;
 
322
        } else {
 
323
                return 0;
 
324
        }
 
325
}
 
326
 
 
327
// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
 
328
// and then has text and optional styles.
 
329
 
 
330
static const int IndividualStyles = 0x100;
 
331
 
 
332
struct AnnotationHeader {
 
333
        short style;    // Style IndividualStyles implies array of styles
 
334
        short lines;
 
335
        int length;
 
336
};
 
337
 
 
338
LineAnnotation::~LineAnnotation() {
 
339
        ClearAll();
 
340
}
 
341
 
 
342
void LineAnnotation::InsertLine(int line) {
 
343
        if (annotations.Length()) {
 
344
                annotations.Insert(line, 0);
 
345
        }
 
346
}
 
347
 
 
348
void LineAnnotation::RemoveLine(int line) {
 
349
        if (annotations.Length() && (line < annotations.Length())) {
 
350
                delete []annotations[line];
 
351
                annotations.Delete(line);
 
352
        }
 
353
}
 
354
 
 
355
bool LineAnnotation::AnySet() const {
 
356
        return annotations.Length() > 0;
 
357
}
 
358
 
 
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;
 
362
        else
 
363
                return 0;
 
364
}
 
365
 
 
366
int LineAnnotation::Style(int line) {
 
367
        if (annotations.Length() && (line < annotations.Length()) && annotations[line])
 
368
                return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
 
369
        else
 
370
                return 0;
 
371
}
 
372
 
 
373
const char *LineAnnotation::Text(int line) const {
 
374
        if (annotations.Length() && (line < annotations.Length()) && annotations[line])
 
375
                return annotations[line]+sizeof(AnnotationHeader);
 
376
        else
 
377
                return 0;
 
378
}
 
379
 
 
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));
 
383
        else
 
384
                return 0;
 
385
}
 
386
 
 
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];
 
390
        memset(ret, 0, len);
 
391
        return ret;
 
392
}
 
393
 
 
394
void LineAnnotation::SetText(int line, const char *text) {
 
395
        if (text) {
 
396
                annotations.EnsureLength(line+1);
 
397
                int style = Style(line);
 
398
                if (annotations[line]) {
 
399
                        delete []annotations[line];
 
400
                }
 
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);
 
407
        } else {
 
408
                if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
 
409
                        delete []annotations[line];
 
410
                        annotations[line] = 0;
 
411
                }
 
412
        }
 
413
}
 
414
 
 
415
void LineAnnotation::ClearAll() {
 
416
        for (int line = 0; line < annotations.Length(); line++) {
 
417
                delete []annotations[line];
 
418
                annotations[line] = 0;
 
419
        }
 
420
        annotations.DeleteAll();
 
421
}
 
422
 
 
423
void LineAnnotation::SetStyle(int line, int style) {
 
424
        annotations.EnsureLength(line+1);
 
425
        if (!annotations[line]) {
 
426
                annotations[line] = AllocateAnnotation(0, style);
 
427
        }
 
428
        reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
 
429
}
 
430
 
 
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);
 
435
        } else {
 
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;
 
445
                }
 
446
        }
 
447
        AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
 
448
        pah->style = IndividualStyles;
 
449
        memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
 
450
}
 
451
 
 
452
int LineAnnotation::Length(int line) const {
 
453
        if (annotations.Length() && (line < annotations.Length()) && annotations[line])
 
454
                return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
 
455
        else
 
456
                return 0;
 
457
}
 
458
 
 
459
int LineAnnotation::Lines(int line) const {
 
460
        if (annotations.Length() && (line < annotations.Length()) && annotations[line])
 
461
                return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
 
462
        else
 
463
                return 0;
 
464
}