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

« back to all changes in this revision

Viewing changes to scintilla/Document.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mfrom: (1.2.1 upstream) (9 hardy)
  • mto: (3.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080502113745-xzp4g6dmovrpoj17
Tags: 0.14-1
New upstream release (Closes: #478126)

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"
 
18
#include "RunStyles.h"
17
19
#include "CellBuffer.h"
18
20
#include "CharClassify.h"
 
21
#include "Decoration.h"
19
22
#include "Document.h"
20
23
#include "RESearch.h"
21
24
 
 
25
#ifdef SCI_NAMESPACE
 
26
using namespace Scintilla;
 
27
#endif
 
28
 
22
29
// This is ASCII specific but is safe with chars >= 0x80
23
30
static inline bool isspacechar(unsigned char ch) {
24
31
        return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
53
60
        stylingMask = 0;
54
61
        endStyled = 0;
55
62
        styleClock = 0;
56
 
        enteredCount = 0;
 
63
        enteredModification = 0;
 
64
        enteredStyling = 0;
57
65
        enteredReadOnlyCount = 0;
58
66
        tabInChars = 8;
59
67
        indentInChars = 0;
104
112
int Document::AddMark(int line, int markerNum) {
105
113
        int prev = cb.AddMark(line, markerNum);
106
114
        DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
107
 
        mh.line = line;
108
115
        NotifyModified(mh);
109
116
        return prev;
110
117
}
115
122
                if (m & 1)
116
123
                        cb.AddMark(line, i);
117
124
        DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
118
 
        mh.line = line;
119
125
        NotifyModified(mh);
120
126
}
121
127
 
122
128
void Document::DeleteMark(int line, int markerNum) {
123
129
        cb.DeleteMark(line, markerNum);
124
130
        DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
125
 
        mh.line = line;
126
131
        NotifyModified(mh);
127
132
}
128
133
 
140
145
        NotifyModified(mh);
141
146
}
142
147
 
143
 
int Document::LineStart(int line) {
 
148
int Document::LineStart(int line) const {
144
149
        return cb.LineStart(line);
145
150
}
146
151
 
147
 
int Document::LineEnd(int line) {
 
152
int Document::LineEnd(int line) const {
148
153
        if (line == LinesTotal() - 1) {
149
154
                return LineStart(line + 1);
150
155
        } else {
182
187
        int prev = cb.SetLevel(line, level);
183
188
        if (prev != level) {
184
189
                DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
185
 
                                   LineStart(line), 0, 0, 0);
186
 
                mh.line = line;
 
190
                                   LineStart(line), 0, 0, 0, line);
187
191
                mh.foldLevelNow = level;
188
192
                mh.foldLevelPrev = prev;
189
193
                NotifyModified(mh);
261
265
                if (ch < 0x80)
262
266
                        return 1;
263
267
                int len = 2;
264
 
                if (ch >= (0x80 + 0x40 + 0x20))
 
268
                if (ch >= (0x80 + 0x40 + 0x20 + 0x10))
 
269
                        len = 4;
 
270
                else if (ch >= (0x80 + 0x40 + 0x20))
265
271
                        len = 3;
266
272
                int lengthDoc = Length();
267
273
                if ((pos + len) > lengthDoc)
281
287
        }
282
288
}
283
289
 
 
290
static bool IsTrailByte(int ch) {
 
291
        return (ch >= 0x80) && (ch < (0x80 + 0x40));
 
292
}
 
293
 
 
294
static int BytesFromLead(int leadByte) {
 
295
        if (leadByte > 0xF4) {
 
296
                // Characters longer than 4 bytes not possible in current UTF-8
 
297
                return 0;
 
298
        } else if (leadByte >= 0xF0) {
 
299
                return 4;
 
300
        } else if (leadByte >= 0xE0) {
 
301
                return 3;
 
302
        } else if (leadByte >= 0xC2) {
 
303
                return 2;
 
304
        }
 
305
        return 0;
 
306
}
 
307
 
 
308
bool Document::InGoodUTF8(int pos, int &start, int &end) {
 
309
        int lead = pos;
 
310
        while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1))))
 
311
                lead--;
 
312
        start = 0;
 
313
        if (lead > 0) {
 
314
                start = lead-1;
 
315
        }
 
316
        int leadByte = static_cast<unsigned char>(cb.CharAt(start));
 
317
        int bytes = BytesFromLead(leadByte);
 
318
        if (bytes == 0) {
 
319
                return false;
 
320
        } else {
 
321
                int trailBytes = bytes - 1;
 
322
                int len = pos - lead + 1;
 
323
                if (len > trailBytes)
 
324
                        // pos too far from lead
 
325
                        return false;
 
326
                // Check that there are enough trails for this lead
 
327
                int trail = pos + 1;
 
328
                while ((trail-lead<trailBytes) && (trail < Length())) {
 
329
                        if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) {
 
330
                                return false;
 
331
                        }
 
332
                        trail++;
 
333
                }
 
334
                end = start + bytes;
 
335
                return true;
 
336
        }
 
337
}
 
338
 
284
339
// Normalise a position so that it is not halfway through a two byte character.
285
340
// This can occur in two situations -
286
341
// When lines are terminated with \r\n pairs which should be treated as one character.
307
362
        if (dbcsCodePage) {
308
363
                if (SC_CP_UTF8 == dbcsCodePage) {
309
364
                        unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
310
 
                        while ((pos > 0) && (pos < Length()) && (ch >= 0x80) && (ch < (0x80 + 0x40))) {
311
 
                                // ch is a trail byte
 
365
                        int startUTF = pos;
 
366
                        int endUTF = pos;
 
367
                        if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {
 
368
                                // ch is a trail byte within a UTF-8 character
312
369
                                if (moveDir > 0)
313
 
                                        pos++;
 
370
                                        pos = endUTF;
314
371
                                else
315
 
                                        pos--;
316
 
                                ch = static_cast<unsigned char>(cb.CharAt(pos));
 
372
                                        pos = startUTF;
317
373
                        }
318
374
                } else {
319
375
                        // Anchor DBCS calculations at start of line because start of line can
358
414
        }
359
415
}
360
416
 
361
 
// Document only modified by gateways DeleteChars, InsertStyledString, Undo, Redo, and SetStyleAt.
 
417
// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt.
362
418
// SetStyleAt does not change the persistent state of a document
363
419
 
364
 
// Unlike Undo, Redo, and InsertStyledString, the pos argument is a cell number not a char number
365
420
bool Document::DeleteChars(int pos, int len) {
366
421
        if (len == 0)
367
422
                return false;
368
423
        if ((pos + len) > Length())
369
424
                return false;
370
425
        CheckReadOnly();
371
 
        if (enteredCount != 0) {
 
426
        if (enteredModification != 0) {
372
427
                return false;
373
428
        } else {
374
 
                enteredCount++;
 
429
                enteredModification++;
375
430
                if (!cb.IsReadOnly()) {
376
431
                        NotifyModified(
377
432
                            DocModification(
380
435
                                0, 0));
381
436
                        int prevLinesTotal = LinesTotal();
382
437
                        bool startSavePoint = cb.IsSavePoint();
383
 
                        const char *text = cb.DeleteChars(pos * 2, len * 2);
 
438
                        bool startSequence = false;
 
439
                        const char *text = cb.DeleteChars(pos, len, startSequence);
384
440
                        if (startSavePoint && cb.IsCollectingUndo())
385
441
                                NotifySavePoint(!startSavePoint);
386
442
                        if ((pos < Length()) || (pos == 0))
389
445
                                ModifiedAt(pos-1);
390
446
                        NotifyModified(
391
447
                            DocModification(
392
 
                                SC_MOD_DELETETEXT | SC_PERFORMED_USER,
 
448
                                SC_MOD_DELETETEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
393
449
                                pos, len,
394
450
                                LinesTotal() - prevLinesTotal, text));
395
451
                }
396
 
                enteredCount--;
 
452
                enteredModification--;
397
453
        }
398
454
        return !cb.IsReadOnly();
399
455
}
400
456
 
401
457
/**
402
 
 * Insert a styled string (char/style pairs) with a length.
 
458
 * Insert a string with a length.
403
459
 */
404
 
bool Document::InsertStyledString(int position, char *s, int insertLength) {
 
460
bool Document::InsertString(int position, const char *s, int insertLength) {
 
461
        if (insertLength <= 0) {
 
462
                return false;
 
463
        }
405
464
        CheckReadOnly();
406
 
        if (enteredCount != 0) {
 
465
        if (enteredModification != 0) {
407
466
                return false;
408
467
        } else {
409
 
                enteredCount++;
 
468
                enteredModification++;
410
469
                if (!cb.IsReadOnly()) {
411
470
                        NotifyModified(
412
471
                            DocModification(
413
472
                                SC_MOD_BEFOREINSERT | SC_PERFORMED_USER,
414
 
                                position / 2, insertLength / 2,
 
473
                                position, insertLength,
415
474
                                0, s));
416
475
                        int prevLinesTotal = LinesTotal();
417
476
                        bool startSavePoint = cb.IsSavePoint();
418
 
                        const char *text = cb.InsertString(position, s, insertLength);
 
477
                        bool startSequence = false;
 
478
                        const char *text = cb.InsertString(position, s, insertLength, startSequence);
419
479
                        if (startSavePoint && cb.IsCollectingUndo())
420
480
                                NotifySavePoint(!startSavePoint);
421
 
                        ModifiedAt(position / 2);
 
481
                        ModifiedAt(position);
422
482
                        NotifyModified(
423
483
                            DocModification(
424
 
                                SC_MOD_INSERTTEXT | SC_PERFORMED_USER,
425
 
                                position / 2, insertLength / 2,
 
484
                                SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
 
485
                                position, insertLength,
426
486
                                LinesTotal() - prevLinesTotal, text));
427
487
                }
428
 
                enteredCount--;
 
488
                enteredModification--;
429
489
        }
430
490
        return !cb.IsReadOnly();
431
491
}
433
493
int Document::Undo() {
434
494
        int newPos = -1;
435
495
        CheckReadOnly();
436
 
        if (enteredCount == 0) {
437
 
                enteredCount++;
 
496
        if (enteredModification == 0) {
 
497
                enteredModification++;
438
498
                if (!cb.IsReadOnly()) {
439
499
                        bool startSavePoint = cb.IsSavePoint();
440
500
                        bool multiLine = false;
481
541
                        if (startSavePoint != endSavePoint)
482
542
                                NotifySavePoint(endSavePoint);
483
543
                }
484
 
                enteredCount--;
 
544
                enteredModification--;
485
545
        }
486
546
        return newPos;
487
547
}
489
549
int Document::Redo() {
490
550
        int newPos = -1;
491
551
        CheckReadOnly();
492
 
        if (enteredCount == 0) {
493
 
                enteredCount++;
 
552
        if (enteredModification == 0) {
 
553
                enteredModification++;
494
554
                if (!cb.IsReadOnly()) {
495
555
                        bool startSavePoint = cb.IsSavePoint();
496
556
                        bool multiLine = false;
535
595
                        if (startSavePoint != endSavePoint)
536
596
                                NotifySavePoint(endSavePoint);
537
597
                }
538
 
                enteredCount--;
 
598
                enteredModification--;
539
599
        }
540
600
        return newPos;
541
601
}
544
604
 * Insert a single character.
545
605
 */
546
606
bool Document::InsertChar(int pos, char ch) {
547
 
        char chs[2];
 
607
        char chs[1];
548
608
        chs[0] = ch;
549
 
        chs[1] = 0;
550
 
        return InsertStyledString(pos*2, chs, 2);
 
609
        return InsertString(pos, chs, 1);
551
610
}
552
611
 
553
612
/**
554
613
 * Insert a null terminated string.
555
614
 */
556
 
bool Document::InsertString(int position, const char *s) {
 
615
bool Document::InsertCString(int position, const char *s) {
557
616
        return InsertString(position, s, strlen(s));
558
617
}
559
618
 
560
 
/**
561
 
 * Insert a string with a length.
562
 
 */
563
 
bool Document::InsertString(int position, const char *s, size_t insertLength) {
564
 
        bool changed = false;
565
 
        if (insertLength > 0) {
566
 
                char *sWithStyle = new char[insertLength * 2];
567
 
                if (sWithStyle) {
568
 
                        for (size_t i = 0; i < insertLength; i++) {
569
 
                                sWithStyle[i*2] = s[i];
570
 
                                sWithStyle[i*2 + 1] = 0;
571
 
                        }
572
 
                        changed = InsertStyledString(position*2, sWithStyle,
573
 
                                static_cast<int>(insertLength*2));
574
 
                        delete []sWithStyle;
575
 
                }
576
 
        }
577
 
        return changed;
578
 
}
579
 
 
580
619
void Document::ChangeChar(int pos, char ch) {
581
620
        DeleteChars(pos, 1);
582
621
        InsertChar(pos, ch);
653
692
                int indentPos = GetLineIndentPosition(line);
654
693
                BeginUndoAction();
655
694
                DeleteChars(thisLineStart, indentPos - thisLineStart);
656
 
                InsertString(thisLineStart, linebuf);
 
695
                InsertCString(thisLineStart, linebuf);
657
696
                EndUndoAction();
658
697
        }
659
698
}
660
699
 
661
 
int Document::GetLineIndentPosition(int line) {
 
700
int Document::GetLineIndentPosition(int line) const {
662
701
        if (line < 0)
663
702
                return 0;
664
703
        int pos = LineStart(line);
682
721
                                return column;
683
722
                        } else if (ch == '\n') {
684
723
                                return column;
 
724
                        } else if (i >= Length()) {
 
725
                                return column;
685
726
                        } else {
686
727
                                column++;
687
 
                                i = MovePositionOutsideChar(i + 1, 1);
 
728
                                i = MovePositionOutsideChar(i + 1, 1, false);
688
729
                        }
689
730
                }
690
731
        }
706
747
                                return position;
707
748
                        } else {
708
749
                                columnCurrent++;
709
 
                                position = MovePositionOutsideChar(position + 1, 1);
 
750
                                position = MovePositionOutsideChar(position + 1, 1, false);
710
751
                        }
711
752
                }
712
753
        }
797
838
        EndUndoAction();
798
839
}
799
840
 
800
 
bool Document::IsWhiteLine(int line) {
 
841
bool Document::IsWhiteLine(int line) const {
801
842
        int currentChar = LineStart(line);
802
843
        int endLine = LineEnd(line);
803
844
        while (currentChar < endLine) {
854
895
                while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart))
855
896
                        pos--;
856
897
        } else {
857
 
                if (!onlyWordCharacters)
 
898
                if (!onlyWordCharacters && pos < Length())
858
899
                        ccStart = WordCharClass(cb.CharAt(pos));
859
900
                while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart))
860
901
                        pos++;
1242
1283
        return substituted;
1243
1284
}
1244
1285
 
1245
 
int Document::LinesTotal() {
 
1286
int Document::LinesTotal() const {
1246
1287
        return cb.Lines();
1247
1288
}
1248
1289
 
1275
1316
 
1276
1317
void Document::SetStylingBits(int bits) {
1277
1318
        stylingBits = bits;
1278
 
        stylingBitsMask = 0;
1279
 
        for (int bit = 0; bit < stylingBits; bit++) {
1280
 
                stylingBitsMask <<= 1;
1281
 
                stylingBitsMask |= 1;
1282
 
        }
 
1319
        stylingBitsMask = (1 << stylingBits) - 1;
1283
1320
}
1284
1321
 
1285
1322
void Document::StartStyling(int position, char mask) {
1288
1325
}
1289
1326
 
1290
1327
bool Document::SetStyleFor(int length, char style) {
1291
 
        if (enteredCount != 0) {
 
1328
        if (enteredStyling != 0) {
1292
1329
                return false;
1293
1330
        } else {
1294
 
                enteredCount++;
 
1331
                enteredStyling++;
1295
1332
                style &= stylingMask;
1296
1333
                int prevEndStyled = endStyled;
1297
1334
                if (cb.SetStyleFor(endStyled, length, style, stylingMask)) {
1300
1337
                        NotifyModified(mh);
1301
1338
                }
1302
1339
                endStyled += length;
1303
 
                enteredCount--;
 
1340
                enteredStyling--;
1304
1341
                return true;
1305
1342
        }
1306
1343
}
1307
1344
 
1308
1345
bool Document::SetStyles(int length, char *styles) {
1309
 
        if (enteredCount != 0) {
 
1346
        if (enteredStyling != 0) {
1310
1347
                return false;
1311
1348
        } else {
1312
 
                enteredCount++;
 
1349
                enteredStyling++;
1313
1350
                bool didChange = false;
1314
1351
                int startMod = 0;
1315
1352
                int endMod = 0;
1328
1365
                                           startMod, endMod - startMod + 1);
1329
1366
                        NotifyModified(mh);
1330
1367
                }
1331
 
                enteredCount--;
 
1368
                enteredStyling--;
1332
1369
                return true;
1333
1370
        }
1334
1371
}
1335
1372
 
1336
 
bool Document::EnsureStyledTo(int pos) {
1337
 
        if (pos > GetEndStyled()) {
 
1373
void Document::EnsureStyledTo(int pos) {
 
1374
        if ((enteredStyling == 0) && (pos > GetEndStyled())) {
1338
1375
                IncrementStyleClock();
1339
1376
                // Ask the watchers to style, and stop as soon as one responds.
1340
1377
                for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) {
1341
1378
                        watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos);
1342
1379
                }
1343
1380
        }
1344
 
        return pos <= GetEndStyled();
 
1381
}
 
1382
 
 
1383
int Document::SetLineState(int line, int state) { 
 
1384
        int statePrevious = cb.SetLineState(line, state);
 
1385
        if (state != statePrevious) {
 
1386
                DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
 
1387
                NotifyModified(mh);
 
1388
        }
 
1389
        return statePrevious;
1345
1390
}
1346
1391
 
1347
1392
void Document::IncrementStyleClock() {
1348
 
        styleClock++;
1349
 
        if (styleClock > 0x100000) {
1350
 
                styleClock = 0;
 
1393
        styleClock = (styleClock + 1) % 0x100000;
 
1394
}
 
1395
 
 
1396
void Document::DecorationFillRange(int position, int value, int fillLength) {
 
1397
        if (decorations.FillRange(position, value, fillLength)) {
 
1398
                DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER,
 
1399
                                                        position, fillLength);
 
1400
                NotifyModified(mh);
1351
1401
        }
1352
1402
}
1353
1403
 
1408
1458
}
1409
1459
 
1410
1460
void Document::NotifyModified(DocModification mh) {
 
1461
        if (mh.modificationType & SC_MOD_INSERTTEXT) {
 
1462
                decorations.InsertSpace(mh.position, mh.length);
 
1463
        } else if (mh.modificationType & SC_MOD_DELETETEXT) {
 
1464
                decorations.DeleteRange(mh.position, mh.length);
 
1465
        }
1411
1466
        for (int i = 0; i < lenWatchers; i++) {
1412
1467
                watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
1413
1468
        }