~ubuntu-branches/ubuntu/raring/geany/raring-proposed

« back to all changes in this revision

Viewing changes to scintilla/CellBuffer.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080502113745-7q62rqhl2ku02ptu
Import upstream version 0.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
#include "Platform.h"
14
14
 
15
15
#include "Scintilla.h"
16
 
#include "SVector.h"
 
16
#include "SplitVector.h"
 
17
#include "Partitioning.h"
17
18
#include "CellBuffer.h"
18
19
 
 
20
#ifdef SCI_NAMESPACE
 
21
using namespace Scintilla;
 
22
#endif
 
23
 
19
24
MarkerHandleSet::MarkerHandleSet() {
20
25
        root = 0;
21
26
}
30
35
        root = 0;
31
36
}
32
37
 
33
 
int MarkerHandleSet::Length() {
 
38
int MarkerHandleSet::Length() const {
34
39
        int c = 0;
35
40
        MarkerHandleNumber *mhn = root;
36
41
        while (mhn) {
40
45
        return c;
41
46
}
42
47
 
43
 
int MarkerHandleSet::NumberFromHandle(int handle) {
 
48
int MarkerHandleSet::NumberFromHandle(int handle) const {
44
49
        MarkerHandleNumber *mhn = root;
45
50
        while (mhn) {
46
51
                if (mhn->handle == handle) {
51
56
        return - 1;
52
57
}
53
58
 
54
 
int MarkerHandleSet::MarkValue() {
 
59
int MarkerHandleSet::MarkValue() const {
55
60
        unsigned int m = 0;
56
61
        MarkerHandleNumber *mhn = root;
57
62
        while (mhn) {
61
66
        return m;
62
67
}
63
68
 
64
 
bool MarkerHandleSet::Contains(int handle) {
 
69
bool MarkerHandleSet::Contains(int handle) const {
65
70
        MarkerHandleNumber *mhn = root;
66
71
        while (mhn) {
67
72
                if (mhn->handle == handle) {
90
95
                if (mhn->handle == handle) {
91
96
                        *pmhn = mhn->next;
92
97
                        delete mhn;
93
 
                        return ;
 
98
                        return;
94
99
                }
95
100
                pmhn = &((*pmhn)->next);
96
101
        }
121
126
        other->root = 0;
122
127
}
123
128
 
124
 
LineVector::LineVector() {
125
 
        linesData = 0;
126
 
        lines = 0;
127
 
        size = 0;
128
 
        levels = 0;
129
 
        sizeLevels = 0;
 
129
LineVector::LineVector() : starts(256) {
130
130
        handleCurrent = 1;
131
 
        growSize = 1000;
132
131
 
133
132
        Init();
134
133
}
135
134
 
136
135
LineVector::~LineVector() {
137
 
        for (int line = 0; line < lines; line++) {
138
 
                delete linesData[line].handleSet;
139
 
                linesData[line].handleSet = 0;
 
136
        starts.DeleteAll();
 
137
        for (int line = 0; line < markers.Length(); line++) {
 
138
                delete markers[line];
 
139
                markers[line] = 0;
140
140
        }
141
 
        delete []linesData;
142
 
        linesData = 0;
143
 
        delete []levels;
144
 
        levels = 0;
 
141
        markers.DeleteAll();
 
142
        levels.DeleteAll();
145
143
}
146
144
 
147
145
void LineVector::Init() {
148
 
        for (int line = 0; line < lines; line++) {
149
 
                delete linesData[line].handleSet;
150
 
                linesData[line].handleSet = 0;
151
 
        }
152
 
        delete []linesData;
153
 
        linesData = new LineData[static_cast<int>(growSize)];
154
 
        size = growSize;
155
 
        lines = 1;
156
 
        delete []levels;
157
 
        levels = 0;
158
 
        sizeLevels = 0;
159
 
}
160
 
 
161
 
void LineVector::Expand(int sizeNew) {
162
 
        LineData *linesDataNew = new LineData[sizeNew];
163
 
        if (linesDataNew) {
164
 
                for (int i = 0; i < size; i++)
165
 
                        linesDataNew[i] = linesData[i];
166
 
                // Do not delete handleSets here as they are transferred to new linesData
167
 
                delete []linesData;
168
 
                linesData = linesDataNew;
169
 
                size = sizeNew;
170
 
        } else {
171
 
                Platform::DebugPrintf("No memory available\n");
172
 
                // TODO: Blow up
173
 
        }
174
 
 
 
146
        starts.DeleteAll();
 
147
        for (int line = 0; line < markers.Length(); line++) {
 
148
                delete markers[line];
 
149
                markers[line] = 0;
 
150
        }
 
151
        markers.DeleteAll();
 
152
        levels.DeleteAll();
175
153
}
176
154
 
177
155
void LineVector::ExpandLevels(int sizeNew) {
178
 
        if (sizeNew == -1)
179
 
                sizeNew = size;
180
 
        int *levelsNew = new int[sizeNew];
181
 
        if (levelsNew) {
182
 
                int i = 0;
183
 
                for (; i < sizeLevels; i++)
184
 
                        levelsNew[i] = levels[i];
185
 
                for (; i < sizeNew; i++)
186
 
                        levelsNew[i] = SC_FOLDLEVELBASE;
187
 
                delete []levels;
188
 
                levels = levelsNew;
189
 
                sizeLevels = sizeNew;
190
 
        } else {
191
 
                Platform::DebugPrintf("No memory available\n");
192
 
                // TODO: Blow up
193
 
        }
194
 
 
 
156
        levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
195
157
}
196
158
 
197
159
void LineVector::ClearLevels() {
198
 
        delete []levels;
199
 
        levels = 0;
200
 
        sizeLevels = 0;
201
 
}
202
 
 
203
 
void LineVector::InsertValue(int pos, int value) {
204
 
        //Platform::DebugPrintf("InsertValue[%d] = %d\n", pos, value);
205
 
        if ((lines + 2) >= size) {
206
 
                if (growSize * 6 < size)
207
 
                        growSize *= 2;
208
 
                Expand(size + growSize);
209
 
                if (levels) {
210
 
                        ExpandLevels(size + growSize);
211
 
                }
212
 
        }
213
 
        lines++;
214
 
        for (int i = lines; i > pos; i--) {
215
 
                linesData[i] = linesData[i - 1];
216
 
        }
217
 
        linesData[pos].startPosition = value;
218
 
        linesData[pos].handleSet = 0;
219
 
        if (levels) {
220
 
                for (int j = lines; j > pos; j--) {
221
 
                        levels[j] = levels[j - 1];
222
 
                }
223
 
                if (pos == 0) {
224
 
                        levels[pos] = SC_FOLDLEVELBASE;
225
 
                } else if (pos == (lines - 1)) {        // Last line will not be a folder
226
 
                        levels[pos] = SC_FOLDLEVELBASE;
227
 
                } else {
228
 
                        levels[pos] = levels[pos - 1];
229
 
                }
230
 
        }
231
 
}
232
 
 
233
 
void LineVector::SetValue(int pos, int value) {
234
 
        //Platform::DebugPrintf("SetValue[%d] = %d\n", pos, value);
235
 
        if ((pos + 2) >= size) {
236
 
                //Platform::DebugPrintf("Resize %d %d\n", size,pos);
237
 
                Expand(pos + growSize);
238
 
                //Platform::DebugPrintf("end Resize %d %d\n", size,pos);
239
 
                lines = pos;
240
 
                if (levels) {
241
 
                        ExpandLevels(pos + growSize);
242
 
                }
243
 
        }
244
 
        linesData[pos].startPosition = value;
245
 
}
246
 
 
247
 
void LineVector::Remove(int pos) {
248
 
        //Platform::DebugPrintf("Remove %d\n", pos);
 
160
        levels.DeleteAll();
 
161
}
 
162
 
 
163
int LineVector::SetLevel(int line, int level) {
 
164
        int prev = 0;
 
165
        if ((line >= 0) && (line < Lines())) {
 
166
                if (!levels.Length()) {
 
167
                        ExpandLevels(Lines() + 1);
 
168
                }
 
169
                prev = levels[line];
 
170
                if (prev != level) {
 
171
                        levels[line] = level;
 
172
                }
 
173
        }
 
174
        return prev;
 
175
}
 
176
 
 
177
int LineVector::GetLevel(int line) {
 
178
        if (levels.Length() && (line >= 0) && (line < Lines())) {
 
179
                return levels[line];
 
180
        } else {
 
181
                return SC_FOLDLEVELBASE;
 
182
        }
 
183
}
 
184
 
 
185
void LineVector::InsertText(int line, int delta) {
 
186
        starts.InsertText(line, delta);
 
187
}
 
188
 
 
189
void LineVector::InsertLine(int line, int position) {
 
190
        starts.InsertPartition(line, position);
 
191
        if (markers.Length()) {
 
192
                markers.Insert(line, 0);
 
193
        }
 
194
        if (levels.Length()) {
 
195
                int level = SC_FOLDLEVELBASE;
 
196
                if ((line > 0) && (line < Lines())) {
 
197
                        level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
 
198
                }
 
199
                levels.InsertValue(line, 1, level);
 
200
        }
 
201
}
 
202
 
 
203
void LineVector::SetLineStart(int line, int position) {
 
204
        starts.SetPartitionStartPosition(line, position);
 
205
}
 
206
 
 
207
void LineVector::RemoveLine(int line) {
 
208
        starts.RemovePartition(line);
249
209
        // Retain the markers from the deleted line by oring them into the previous line
250
 
        if (pos > 0) {
251
 
                MergeMarkers(pos - 1);
252
 
        }
253
 
        for (int i = pos; i < lines; i++) {
254
 
                linesData[i] = linesData[i + 1];
255
 
        }
256
 
        if (levels) {
 
210
        if (markers.Length()) {
 
211
                if (line > 0) {
 
212
                        MergeMarkers(line - 1);
 
213
                }
 
214
                markers.Delete(line);
 
215
        }
 
216
        if (levels.Length()) {
257
217
                // Move up following lines but merge header flag from this line
258
218
                // to line before to avoid a temporary disappearence causing expansion.
259
 
                int firstHeader = levels[pos] & SC_FOLDLEVELHEADERFLAG;
260
 
                for (int j = pos; j < lines; j++) {
261
 
                        levels[j] = levels[j + 1];
262
 
                }
263
 
                if (pos > 0)
264
 
                        levels[pos-1] |= firstHeader;
 
219
                int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
 
220
                levels.Delete(line);
 
221
                if (line > 0)
 
222
                        levels[line-1] |= firstHeader;
265
223
        }
266
 
        lines--;
267
224
}
268
225
 
269
226
int LineVector::LineFromPosition(int pos) {
270
 
        //Platform::DebugPrintf("LineFromPostion %d lines=%d end = %d\n", pos, lines, linesData[lines].startPosition);
271
 
        if (lines == 0)
 
227
        return starts.PartitionFromPosition(pos);
 
228
}
 
229
 
 
230
int LineVector::MarkValue(int line) {
 
231
        if (markers.Length() && markers[line])
 
232
                return markers[line]->MarkValue();
 
233
        else
272
234
                return 0;
273
 
        //Platform::DebugPrintf("LineFromPosition %d\n", pos);
274
 
        if (pos >= linesData[lines].startPosition)
275
 
                return lines - 1;
276
 
        int lower = 0;
277
 
        int upper = lines;
278
 
        do {
279
 
                int middle = (upper + lower + 1) / 2;   // Round high
280
 
                if (pos < linesData[middle].startPosition) {
281
 
                        upper = middle - 1;
282
 
                } else {
283
 
                        lower = middle;
284
 
                }
285
 
        } while (lower < upper);
286
 
        //Platform::DebugPrintf("LineFromPostion %d %d %d\n", pos, lower, linesData[lower].startPosition, linesData[lower > 1 ? lower - 1 : 0].startPosition);
287
 
        return lower;
288
235
}
289
236
 
290
237
int LineVector::AddMark(int line, int markerNum) {
291
238
        handleCurrent++;
292
 
        if (!linesData[line].handleSet) {
 
239
        if (!markers.Length()) {
 
240
                // No existing markers so allocate one element per line
 
241
                markers.InsertValue(0, Lines(), 0);
 
242
        }
 
243
        if (!markers[line]) {
293
244
                // Need new structure to hold marker handle
294
 
                linesData[line].handleSet = new MarkerHandleSet;
295
 
                if (!linesData[line].handleSet)
 
245
                markers[line] = new MarkerHandleSet();
 
246
                if (!markers[line])
296
247
                        return - 1;
297
248
        }
298
 
        linesData[line].handleSet->InsertHandle(handleCurrent, markerNum);
 
249
        markers[line]->InsertHandle(handleCurrent, markerNum);
299
250
 
300
251
        return handleCurrent;
301
252
}
302
253
 
303
254
void LineVector::MergeMarkers(int pos) {
304
 
        if (linesData[pos + 1].handleSet != NULL) {
305
 
                if (linesData[pos].handleSet == NULL )
306
 
                        linesData[pos].handleSet = new MarkerHandleSet;
307
 
                linesData[pos].handleSet->CombineWith(linesData[pos + 1].handleSet);
308
 
                delete linesData[pos + 1].handleSet;
309
 
                linesData[pos + 1].handleSet = NULL;
 
255
        if (markers[pos + 1] != NULL) {
 
256
                if (markers[pos] == NULL)
 
257
                        markers[pos] = new MarkerHandleSet;
 
258
                markers[pos]->CombineWith(markers[pos + 1]);
 
259
                delete markers[pos + 1];
 
260
                markers[pos + 1] = NULL;
310
261
        }
311
262
}
312
263
 
313
264
void LineVector::DeleteMark(int line, int markerNum, bool all) {
314
 
        if (linesData[line].handleSet) {
 
265
        if (markers.Length() && markers[line]) {
315
266
                if (markerNum == -1) {
316
 
                        delete linesData[line].handleSet;
317
 
                        linesData[line].handleSet = 0;
 
267
                        delete markers[line];
 
268
                        markers[line] = NULL;
318
269
                } else {
319
 
                        bool performedDeletion = 
320
 
                                linesData[line].handleSet->RemoveNumber(markerNum);
 
270
                        bool performedDeletion = markers[line]->RemoveNumber(markerNum);
321
271
                        while (all && performedDeletion) {
322
 
                                performedDeletion = 
323
 
                                        linesData[line].handleSet->RemoveNumber(markerNum);
 
272
                                performedDeletion = markers[line]->RemoveNumber(markerNum);
324
273
                        }
325
 
                        if (linesData[line].handleSet->Length() == 0) {
326
 
                                delete linesData[line].handleSet;
327
 
                                linesData[line].handleSet = 0;
 
274
                        if (markers[line]->Length() == 0) {
 
275
                                delete markers[line];
 
276
                                markers[line] = NULL;
328
277
                        }
329
278
                }
330
279
        }
333
282
void LineVector::DeleteMarkFromHandle(int markerHandle) {
334
283
        int line = LineFromHandle(markerHandle);
335
284
        if (line >= 0) {
336
 
                linesData[line].handleSet->RemoveHandle(markerHandle);
337
 
                if (linesData[line].handleSet->Length() == 0) {
338
 
                        delete linesData[line].handleSet;
339
 
                        linesData[line].handleSet = 0;
 
285
                markers[line]->RemoveHandle(markerHandle);
 
286
                if (markers[line]->Length() == 0) {
 
287
                        delete markers[line];
 
288
                        markers[line] = NULL;
340
289
                }
341
290
        }
342
291
}
343
292
 
344
293
int LineVector::LineFromHandle(int markerHandle) {
345
 
        for (int line = 0; line < lines; line++) {
346
 
                if (linesData[line].handleSet) {
347
 
                        if (linesData[line].handleSet->Contains(markerHandle)) {
348
 
                                return line;
 
294
        if (markers.Length()) {
 
295
                for (int line = 0; line < Lines(); line++) {
 
296
                        if (markers[line]) {
 
297
                                if (markers[line]->Contains(markerHandle)) {
 
298
                                        return line;
 
299
                                }
349
300
                        }
350
301
                }
351
302
        }
352
 
        return - 1;
 
303
        return -1;
353
304
}
354
305
 
355
306
Action::Action() {
437
388
                int lenActionsNew = lenActions * 2;
438
389
                Action *actionsNew = new Action[lenActionsNew];
439
390
                if (!actionsNew)
440
 
                        return ;
 
391
                        return;
441
392
                for (int act = 0; act <= currentAction; act++)
442
393
                        actionsNew[act].Grab(&actions[act]);
443
394
                delete []actions;
446
397
        }
447
398
}
448
399
 
449
 
void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData) {
 
400
void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData,
 
401
        bool &startSequence) {
450
402
        EnsureUndoRoom();
451
403
        //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
452
404
        //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
454
406
        if (currentAction < savePoint) {
455
407
                savePoint = -1;
456
408
        }
 
409
        int oldCurrentAction = currentAction;
457
410
        if (currentAction >= 1) {
458
411
                if (0 == undoSequenceDepth) {
459
412
                        // Top level actions may not always be coalesced
486
439
                                        currentAction++;
487
440
                                }
488
441
                        } else {
489
 
                                //Platform::DebugPrintf("action coalesced\n");
 
442
                                // Action coalesced.
490
443
                        }
491
444
 
492
445
                } else {
497
450
        } else {
498
451
                currentAction++;
499
452
        }
 
453
        startSequence = oldCurrentAction != currentAction;
500
454
        actions[currentAction].Create(at, position, data, lengthData);
501
455
        currentAction++;
502
456
        actions[currentAction].Create(startAction);
517
471
}
518
472
 
519
473
void UndoHistory::EndUndoAction() {
 
474
        PLATFORM_ASSERT(undoSequenceDepth > 0);
520
475
        EnsureUndoRoom();
521
476
        undoSequenceDepth--;
522
477
        if (0 == undoSequenceDepth) {
600
555
        currentAction++;
601
556
}
602
557
 
603
 
CellBuffer::CellBuffer(int initialLength) {
604
 
        body = new char[initialLength];
605
 
        size = initialLength;
606
 
        length = 0;
607
 
        part1len = 0;
608
 
        gaplen = initialLength;
609
 
        part2body = body + gaplen;
 
558
CellBuffer::CellBuffer() {
610
559
        readOnly = false;
611
560
        collectingUndo = true;
612
 
        growSize = 4000;
613
561
}
614
562
 
615
563
CellBuffer::~CellBuffer() {
616
 
        delete []body;
617
 
        body = 0;
618
 
}
619
 
 
620
 
void CellBuffer::GapTo(int position) {
621
 
        if (position == part1len)
622
 
                return ;
623
 
        if (position < part1len) {
624
 
                int diff = part1len - position;
625
 
                //Platform::DebugPrintf("Move gap backwards to %d diff = %d part1len=%d length=%d \n", position,diff, part1len, length);
626
 
                for (int i = 0; i < diff; i++)
627
 
                        body[part1len + gaplen - i - 1] = body[part1len - i - 1];
628
 
        } else {        // position > part1len
629
 
                int diff = position - part1len;
630
 
                //Platform::DebugPrintf("Move gap forwards to %d diff =%d\n", position,diff);
631
 
                for (int i = 0; i < diff; i++)
632
 
                        body[part1len + i] = body[part1len + gaplen + i];
633
 
        }
634
 
        part1len = position;
635
 
        part2body = body + gaplen;
636
 
}
637
 
 
638
 
void CellBuffer::RoomFor(int insertionLength) {
639
 
        //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
640
 
        if (gaplen <= insertionLength) {
641
 
                //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
642
 
                if (growSize * 6 < size)
643
 
                        growSize *= 2;
644
 
                int newSize = size + insertionLength + growSize;
645
 
                Allocate(newSize);
646
 
        }
647
 
}
648
 
 
649
 
// To make it easier to write code that uses ByteAt, a position outside the range of the buffer
650
 
// can be retrieved. All characters outside the range have the value '\0'.
651
 
char CellBuffer::ByteAt(int position) {
652
 
        if (position < part1len) {
653
 
                if (position < 0) {
654
 
                        return '\0';
655
 
                } else {
656
 
                        return body[position];
657
 
                }
658
 
        } else {
659
 
                if (position >= length) {
660
 
                        return '\0';
661
 
                } else {
662
 
                        return part2body[position];
663
 
                }
664
 
        }
665
 
}
666
 
 
667
 
void CellBuffer::SetByteAt(int position, char ch) {
668
 
 
669
 
        if (position < 0) {
670
 
                //Platform::DebugPrintf("Bad position %d\n",position);
671
 
                return ;
672
 
        }
673
 
        if (position >= length + 11) {
674
 
                Platform::DebugPrintf("Very Bad position %d of %d\n", position, length);
675
 
                //exit(2);
676
 
                return ;
677
 
        }
678
 
        if (position >= length) {
679
 
                //Platform::DebugPrintf("Bad position %d of %d\n",position,length);
680
 
                return ;
681
 
        }
682
 
 
683
 
        if (position < part1len) {
684
 
                body[position] = ch;
685
 
        } else {
686
 
                part2body[position] = ch;
687
 
        }
688
 
}
689
 
 
690
 
char CellBuffer::CharAt(int position) {
691
 
        return ByteAt(position*2);
 
564
}
 
565
 
 
566
char CellBuffer::CharAt(int position) const {
 
567
        return substance.ValueAt(position);
692
568
}
693
569
 
694
570
void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) {
695
571
        if (lengthRetrieve < 0)
696
 
                return ;
 
572
                return;
697
573
        if (position < 0)
698
 
                return ;
699
 
        int bytePos = position * 2;
700
 
        if ((bytePos + lengthRetrieve * 2) > length) {
701
 
                Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", bytePos,
702
 
                                      lengthRetrieve, length);
703
 
                return ;
 
574
                return;
 
575
        if ((position + lengthRetrieve) > substance.Length()) {
 
576
                Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position,
 
577
                                      lengthRetrieve, substance.Length());
 
578
                return;
704
579
        }
705
 
        GapTo(0);       // Move the buffer so its easy to subscript into it
706
 
        char *pb = part2body + bytePos;
707
 
        while (lengthRetrieve--) {
708
 
                *buffer++ = *pb;
709
 
                pb += 2;
 
580
        
 
581
        for (int i=0; i<lengthRetrieve; i++) {
 
582
                *buffer++ = substance.ValueAt(position + i);
710
583
        }
711
584
}
712
585
 
713
586
char CellBuffer::StyleAt(int position) {
714
 
        return ByteAt(position*2 + 1);
 
587
        return style.ValueAt(position);
715
588
}
716
589
 
717
 
const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
 
590
// The char* returned is to an allocation owned by the undo history
 
591
const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) {
718
592
        char *data = 0;
719
593
        // InsertString and DeleteChars are the bottleneck though which all changes occur
720
594
        if (!readOnly) {
721
595
                if (collectingUndo) {
722
596
                        // Save into the undo/redo stack, but only the characters - not the formatting
723
597
                        // This takes up about half load time
724
 
                        data = new char[insertLength / 2];
725
 
                        for (int i = 0; i < insertLength / 2; i++) {
726
 
                                data[i] = s[i * 2];
 
598
                        data = new char[insertLength];
 
599
                        for (int i = 0; i < insertLength; i++) {
 
600
                                data[i] = s[i];
727
601
                        }
728
 
                        uh.AppendAction(insertAction, position / 2, data, insertLength / 2);
 
602
                        uh.AppendAction(insertAction, position, data, insertLength, startSequence);
729
603
                }
730
604
 
731
605
                BasicInsertString(position, s, insertLength);
733
607
        return data;
734
608
}
735
609
 
736
 
bool CellBuffer::SetStyleAt(int position, char style, char mask) {
737
 
        style &= mask;
738
 
        char curVal = ByteAt(position * 2 + 1);
739
 
        if ((curVal & mask) != style) {
740
 
                SetByteAt(position*2 + 1, static_cast<char>((curVal & ~mask) | style));
 
610
bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) {
 
611
        styleValue &= mask;
 
612
        char curVal = style.ValueAt(position);
 
613
        if ((curVal & mask) != styleValue) {
 
614
                style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
741
615
                return true;
742
616
        } else {
743
617
                return false;
744
618
        }
745
619
}
746
620
 
747
 
bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mask) {
748
 
        int bytePos = position * 2 + 1;
 
621
bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) {
749
622
        bool changed = false;
750
623
        PLATFORM_ASSERT(lengthStyle == 0 ||
751
 
                (lengthStyle > 0 && lengthStyle + position < length));
 
624
                (lengthStyle > 0 && lengthStyle + position <= style.Length()));
752
625
        while (lengthStyle--) {
753
 
                char curVal = ByteAt(bytePos);
754
 
                if ((curVal & mask) != style) {
755
 
                        SetByteAt(bytePos, static_cast<char>((curVal & ~mask) | style));
 
626
                char curVal = style.ValueAt(position);
 
627
                if ((curVal & mask) != styleValue) {
 
628
                        style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
756
629
                        changed = true;
757
630
                }
758
 
                bytePos += 2;
 
631
                position++;
759
632
        }
760
633
        return changed;
761
634
}
762
635
 
763
 
const char *CellBuffer::DeleteChars(int position, int deleteLength) {
 
636
// The char* returned is to an allocation owned by the undo history
 
637
const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) {
764
638
        // InsertString and DeleteChars are the bottleneck though which all changes occur
765
639
        PLATFORM_ASSERT(deleteLength > 0);
766
640
        char *data = 0;
767
641
        if (!readOnly) {
768
642
                if (collectingUndo) {
769
643
                        // Save into the undo/redo stack, but only the characters - not the formatting
770
 
                        data = new char[deleteLength / 2];
771
 
                        for (int i = 0; i < deleteLength / 2; i++) {
772
 
                                data[i] = ByteAt(position + i * 2);
 
644
                        data = new char[deleteLength];
 
645
                        for (int i = 0; i < deleteLength; i++) {
 
646
                                data[i] = substance.ValueAt(position + i);
773
647
                        }
774
 
                        uh.AppendAction(removeAction, position / 2, data, deleteLength / 2);
 
648
                        uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
775
649
                }
776
650
 
777
651
                BasicDeleteChars(position, deleteLength);
779
653
        return data;
780
654
}
781
655
 
782
 
int CellBuffer::ByteLength() {
783
 
        return length;
784
 
}
785
 
 
786
 
int CellBuffer::Length() {
787
 
        return ByteLength() / 2;
 
656
int CellBuffer::Length() const {
 
657
        return substance.Length();
788
658
}
789
659
 
790
660
void CellBuffer::Allocate(int newSize) {
791
 
        if (newSize > length) {
792
 
                GapTo(length);
793
 
                char *newBody = new char[newSize];
794
 
                memcpy(newBody, body, length);
795
 
                delete []body;
796
 
                body = newBody;
797
 
                gaplen += newSize - size;
798
 
                part2body = body + gaplen;
799
 
                size = newSize;
800
 
        }
801
 
}
802
 
 
803
 
int CellBuffer::Lines() {
804
 
        //Platform::DebugPrintf("Lines = %d\n", lv.lines);
805
 
        return lv.lines;
806
 
}
807
 
 
808
 
int CellBuffer::LineStart(int line) {
 
661
        substance.ReAllocate(newSize);
 
662
        style.ReAllocate(newSize);
 
663
}
 
664
 
 
665
int CellBuffer::Lines() const {
 
666
        return lv.Lines();
 
667
}
 
668
 
 
669
int CellBuffer::LineStart(int line) const {
809
670
        if (line < 0)
810
671
                return 0;
811
 
        else if (line > lv.lines)
 
672
        else if (line >= Lines())
812
673
                return Length();
813
674
        else
814
 
                return lv.linesData[line].startPosition;
 
675
                return lv.LineStart(line);
815
676
}
816
677
 
817
678
bool CellBuffer::IsReadOnly() {
831
692
}
832
693
 
833
694
int CellBuffer::AddMark(int line, int markerNum) {
834
 
        if ((line >= 0) && (line < lv.lines)) {
 
695
        if ((line >= 0) && (line < Lines())) {
835
696
                return lv.AddMark(line, markerNum);
836
697
        }
837
698
        return - 1;
838
699
}
839
700
 
840
701
void CellBuffer::DeleteMark(int line, int markerNum) {
841
 
        if ((line >= 0) && (line < lv.lines)) {
 
702
        if ((line >= 0) && (line < Lines())) {
842
703
                lv.DeleteMark(line, markerNum, false);
843
704
        }
844
705
}
848
709
}
849
710
 
850
711
int CellBuffer::GetMark(int line) {
851
 
        if ((line >= 0) && (line < lv.lines) && (lv.linesData[line].handleSet))
852
 
                return lv.linesData[line].handleSet->MarkValue();
 
712
        if ((line >= 0) && (line < Lines()))
 
713
                return lv.MarkValue(line);
853
714
        return 0;
854
715
}
855
716
 
856
717
void CellBuffer::DeleteAllMarks(int markerNum) {
857
 
        for (int line = 0; line < lv.lines; line++) {
 
718
        for (int line = 0; line < Lines(); line++) {
858
719
                lv.DeleteMark(line, markerNum, true);
859
720
        }
860
721
}
865
726
 
866
727
// Without undo
867
728
 
868
 
void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
869
 
        //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
 
729
void CellBuffer::InsertLine(int line, int position) {
 
730
        lv.InsertLine(line, position);
 
731
        if (lineStates.Length()) {
 
732
                lineStates.EnsureLength(line);
 
733
                lineStates.Insert(line, 0);
 
734
        }
 
735
}
 
736
 
 
737
void CellBuffer::RemoveLine(int line) {
 
738
        lv.RemoveLine(line);
 
739
        if (lineStates.Length() > line) {
 
740
                lineStates.Delete(line);
 
741
        }
 
742
}
 
743
 
 
744
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
870
745
        if (insertLength == 0)
871
 
                return ;
 
746
                return;
872
747
        PLATFORM_ASSERT(insertLength > 0);
873
 
        RoomFor(insertLength);
874
 
        GapTo(position);
875
 
 
876
 
        memcpy(body + part1len, s, insertLength);
877
 
        length += insertLength;
878
 
        part1len += insertLength;
879
 
        gaplen -= insertLength;
880
 
        part2body = body + gaplen;
881
 
 
882
 
        int lineInsert = lv.LineFromPosition(position / 2) + 1;
 
748
 
 
749
        substance.InsertFromArray(position, s, 0, insertLength);
 
750
        style.InsertValue(position, insertLength, 0);
 
751
 
 
752
        int lineInsert = lv.LineFromPosition(position) + 1;
883
753
        // Point all the lines after the insertion point further along in the buffer
884
 
        for (int lineAfter = lineInsert; lineAfter <= lv.lines; lineAfter++) {
885
 
                lv.linesData[lineAfter].startPosition += insertLength / 2;
886
 
        }
887
 
        char chPrev = ' ';
888
 
        if ((position - 2) >= 0)
889
 
                chPrev = ByteAt(position - 2);
890
 
        char chAfter = ' ';
891
 
        if ((position + insertLength) < length)
892
 
                chAfter = ByteAt(position + insertLength);
 
754
        lv.InsertText(lineInsert-1, insertLength);
 
755
        char chPrev = substance.ValueAt(position - 1);
 
756
        char chAfter = substance.ValueAt(position + insertLength);
893
757
        if (chPrev == '\r' && chAfter == '\n') {
894
 
                //Platform::DebugPrintf("Splitting a crlf pair at %d\n", lineInsert);
895
758
                // Splitting up a crlf pair at position
896
 
                lv.InsertValue(lineInsert, position / 2);
 
759
                InsertLine(lineInsert, position);
897
760
                lineInsert++;
898
761
        }
899
762
        char ch = ' ';
900
 
        for (int i = 0; i < insertLength; i += 2) {
 
763
        for (int i = 0; i < insertLength; i++) {
901
764
                ch = s[i];
902
765
                if (ch == '\r') {
903
 
                        //Platform::DebugPrintf("Inserting cr at %d\n", lineInsert);
904
 
                        lv.InsertValue(lineInsert, (position + i) / 2 + 1);
 
766
                        InsertLine(lineInsert, (position + i) + 1);
905
767
                        lineInsert++;
906
768
                } else if (ch == '\n') {
907
769
                        if (chPrev == '\r') {
908
 
                                //Platform::DebugPrintf("Patching cr before lf at %d\n", lineInsert-1);
909
770
                                // Patch up what was end of line
910
 
                                lv.SetValue(lineInsert - 1, (position + i) / 2 + 1);
 
771
                                lv.SetLineStart(lineInsert - 1, (position + i) + 1);
911
772
                        } else {
912
 
                                //Platform::DebugPrintf("Inserting lf at %d\n", lineInsert);
913
 
                                lv.InsertValue(lineInsert, (position + i) / 2 + 1);
 
773
                                InsertLine(lineInsert, (position + i) + 1);
914
774
                                lineInsert++;
915
775
                        }
916
776
                }
917
777
                chPrev = ch;
918
778
        }
919
 
        // Joining two lines where last insertion is cr and following text starts with lf
 
779
        // Joining two lines where last insertion is cr and following substance starts with lf
920
780
        if (chAfter == '\n') {
921
781
                if (ch == '\r') {
922
 
                        //Platform::DebugPrintf("Joining cr before lf at %d\n", lineInsert-1);
923
782
                        // End of line already in buffer so drop the newly created one
924
 
                        lv.Remove(lineInsert - 1);
 
783
                        RemoveLine(lineInsert - 1);
925
784
                }
926
785
        }
927
786
}
928
787
 
929
788
void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
930
 
        //Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength);
931
789
        if (deleteLength == 0)
932
 
                return ;
 
790
                return;
933
791
 
934
 
        if ((position == 0) && (deleteLength == length)) {
 
792
        if ((position == 0) && (deleteLength == substance.Length())) {
935
793
                // If whole buffer is being deleted, faster to reinitialise lines data
936
794
                // than to delete each line.
937
 
                //printf("Whole buffer being deleted\n");
938
795
                lv.Init();
939
796
        } else {
940
797
                // Have to fix up line positions before doing deletion as looking at text in buffer
941
798
                // to work out which lines have been removed
942
799
 
943
 
                int lineRemove = lv.LineFromPosition(position / 2) + 1;
944
 
                // Point all the lines after the insertion point further along in the buffer
945
 
                for (int lineAfter = lineRemove; lineAfter <= lv.lines; lineAfter++) {
946
 
                        lv.linesData[lineAfter].startPosition -= deleteLength / 2;
947
 
                }
948
 
                char chPrev = ' ';
949
 
                if (position >= 2)
950
 
                        chPrev = ByteAt(position - 2);
 
800
                int lineRemove = lv.LineFromPosition(position) + 1;
 
801
                lv.InsertText(lineRemove-1, - (deleteLength));
 
802
                char chPrev = substance.ValueAt(position - 1);
951
803
                char chBefore = chPrev;
952
 
                char chNext = ' ';
953
 
                if (position < length)
954
 
                        chNext = ByteAt(position);
 
804
                char chNext = substance.ValueAt(position);
955
805
                bool ignoreNL = false;
956
806
                if (chPrev == '\r' && chNext == '\n') {
957
 
                        //Platform::DebugPrintf("Deleting lf after cr, move line end to cr at %d\n", lineRemove);
958
807
                        // Move back one
959
 
                        lv.SetValue(lineRemove, position / 2);
 
808
                        lv.SetLineStart(lineRemove, position);
960
809
                        lineRemove++;
961
810
                        ignoreNL = true;        // First \n is not real deletion
962
811
                }
963
812
 
964
813
                char ch = chNext;
965
 
                for (int i = 0; i < deleteLength; i += 2) {
966
 
                        chNext = ' ';
967
 
                        if ((position + i + 2) < length)
968
 
                                chNext = ByteAt(position + i + 2);
969
 
                        //Platform::DebugPrintf("Deleting %d %x\n", i, ch);
 
814
                for (int i = 0; i < deleteLength; i++) {
 
815
                        chNext = substance.ValueAt(position + i + 1);
970
816
                        if (ch == '\r') {
971
817
                                if (chNext != '\n') {
972
 
                                        //Platform::DebugPrintf("Removing cr end of line\n");
973
 
                                        lv.Remove(lineRemove);
 
818
                                        RemoveLine(lineRemove);
974
819
                                }
975
820
                        } else if (ch == '\n') {
976
821
                                if (ignoreNL) {
977
822
                                        ignoreNL = false;       // Further \n are real deletions
978
823
                                } else {
979
 
                                        //Platform::DebugPrintf("Removing lf end of line\n");
980
 
                                        lv.Remove(lineRemove);
 
824
                                        RemoveLine(lineRemove);
981
825
                                }
982
826
                        }
983
827
 
985
829
                }
986
830
                // May have to fix up end if last deletion causes cr to be next to lf
987
831
                // or removes one of a crlf pair
988
 
                char chAfter = ' ';
989
 
                if ((position + deleteLength) < length)
990
 
                        chAfter = ByteAt(position + deleteLength);
 
832
                char chAfter = substance.ValueAt(position + deleteLength);
991
833
                if (chBefore == '\r' && chAfter == '\n') {
992
 
                        //d.printf("Joining cr before lf at %d\n", lineRemove);
993
834
                        // Using lineRemove-1 as cr ended line before start of deletion
994
 
                        lv.Remove(lineRemove - 1);
995
 
                        lv.SetValue(lineRemove - 1, position / 2 + 1);
 
835
                        RemoveLine(lineRemove - 1);
 
836
                        lv.SetLineStart(lineRemove - 1, position + 1);
996
837
                }
997
838
        }
998
 
        GapTo(position);
999
 
        length -= deleteLength;
1000
 
        gaplen += deleteLength;
1001
 
        part2body = body + gaplen;
 
839
        substance.DeleteRange(position, deleteLength);
 
840
        style.DeleteRange(position, deleteLength);
1002
841
}
1003
842
 
1004
843
bool CellBuffer::SetUndoCollection(bool collectUndo) {
1038
877
void CellBuffer::PerformUndoStep() {
1039
878
        const Action &actionStep = uh.GetUndoStep();
1040
879
        if (actionStep.at == insertAction) {
1041
 
                BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
 
880
                BasicDeleteChars(actionStep.position, actionStep.lenData);
1042
881
        } else if (actionStep.at == removeAction) {
1043
 
                char *styledData = new char[actionStep.lenData * 2];
1044
 
                for (int i = 0; i < actionStep.lenData; i++) {
1045
 
                        styledData[i*2] = actionStep.data[i];
1046
 
                        styledData[i*2 + 1] = 0;
1047
 
                }
1048
 
                BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
1049
 
                delete []styledData;
 
882
                BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
1050
883
        }
1051
884
        uh.CompletedUndoStep();
1052
885
}
1066
899
void CellBuffer::PerformRedoStep() {
1067
900
        const Action &actionStep = uh.GetRedoStep();
1068
901
        if (actionStep.at == insertAction) {
1069
 
                char *styledData = new char[actionStep.lenData * 2];
1070
 
                for (int i = 0; i < actionStep.lenData; i++) {
1071
 
                        styledData[i*2] = actionStep.data[i];
1072
 
                        styledData[i*2 + 1] = 0;
1073
 
                }
1074
 
                BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
1075
 
                delete []styledData;
 
902
                BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
1076
903
        } else if (actionStep.at == removeAction) {
1077
 
                BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
 
904
                BasicDeleteChars(actionStep.position, actionStep.lenData);
1078
905
        }
1079
906
        uh.CompletedRedoStep();
1080
907
}
1081
908
 
1082
909
int CellBuffer::SetLineState(int line, int state) {
 
910
        lineStates.EnsureLength(line + 1);
1083
911
        int stateOld = lineStates[line];
1084
912
        lineStates[line] = state;
1085
913
        return stateOld;
1086
914
}
1087
915
 
1088
916
int CellBuffer::GetLineState(int line) {
 
917
        lineStates.EnsureLength(line + 1);
1089
918
        return lineStates[line];
1090
919
}
1091
920
 
1094
923
}
1095
924
 
1096
925
int CellBuffer::SetLevel(int line, int level) {
1097
 
        int prev = 0;
1098
 
        if ((line >= 0) && (line < lv.lines)) {
1099
 
                if (!lv.levels) {
1100
 
                        lv.ExpandLevels();
1101
 
                }
1102
 
                prev = lv.levels[line];
1103
 
                if (lv.levels[line] != level) {
1104
 
                        lv.levels[line] = level;
1105
 
                }
1106
 
        }
1107
 
        return prev;
 
926
        return lv.SetLevel(line, level);
1108
927
}
1109
928
 
1110
929
int CellBuffer::GetLevel(int line) {
1111
 
        if (lv.levels && (line >= 0) && (line < lv.lines)) {
1112
 
                return lv.levels[line];
1113
 
        } else {
1114
 
                return SC_FOLDLEVELBASE;
1115
 
        }
 
930
        return lv.GetLevel(line);
1116
931
}
1117
932
 
1118
933
void CellBuffer::ClearLevels() {