~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to scintilla/Document.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2009-01-01 18:40:50 UTC
  • mfrom: (1.1.8 upstream) (3.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20090101184050-u635kualu7amyt4a
Tags: 0.15-1ubuntu1
* Merge from debian experimental, remaining change:
  - patches/20_add_debdiff_as_diff_type.dpatch: Also recognize .dpatch files
    as diff's
  - debian/geany.xpm: Replace icon with a .xpm of the new one

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
        lenWatchers = 0;
74
74
 
75
75
        matchesValid = false;
76
 
        pre = 0;
77
 
        substituted = 0;
 
76
        regex = 0;
78
77
}
79
78
 
80
79
Document::~Document() {
84
83
        delete []watchers;
85
84
        watchers = 0;
86
85
        lenWatchers = 0;
87
 
        delete pre;
88
 
        pre = 0;
89
 
        delete []substituted;
90
 
        substituted = 0;
 
86
        delete regex;
 
87
        regex = 0;
91
88
}
92
89
 
93
90
// Increase reference count and return its previous value.
173
170
int Document::VCHomePosition(int position) {
174
171
        int line = LineFromPosition(position);
175
172
        int startPosition = LineStart(line);
176
 
        int endLine = LineStart(line + 1) - 1;
 
173
        int endLine = LineEnd(line);
177
174
        int startText = startPosition;
178
175
        while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t' ) )
179
176
                startText++;
1015
1012
                return static_cast<char>(ch - 'A' + 'a');
1016
1013
}
1017
1014
 
1018
 
// Define a way for the Regular Expression code to access the document
1019
 
class DocumentIndexer : public CharacterIndexer {
1020
 
        Document *pdoc;
1021
 
        int end;
1022
 
public:
1023
 
        DocumentIndexer(Document *pdoc_, int end_) :
1024
 
                pdoc(pdoc_), end(end_) {
1025
 
        }
1026
 
 
1027
 
        virtual ~DocumentIndexer() {
1028
 
        }
1029
 
 
1030
 
        virtual char CharAt(int index) {
1031
 
                if (index < 0 || index >= end)
1032
 
                        return 0;
1033
 
                else
1034
 
                        return pdoc->CharAt(index);
1035
 
        }
1036
 
};
1037
 
 
1038
1015
/**
1039
1016
 * Find text in document, supporting both forward and backward
1040
1017
 * searches (just pass minPos > maxPos to do a backward search)
1041
1018
 * Has not been tested with backwards DBCS searches yet.
1042
1019
 */
1043
1020
long Document::FindText(int minPos, int maxPos, const char *s,
1044
 
                        bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix,
 
1021
                        bool caseSensitive, bool word, bool wordStart, bool regExp, int flags,
1045
1022
                        int *length) {
1046
1023
        if (regExp) {
1047
 
                if (!pre)
1048
 
                        pre = new RESearch(&charClass);
1049
 
                if (!pre)
1050
 
                        return -1;
1051
 
 
1052
 
                int increment = (minPos <= maxPos) ? 1 : -1;
1053
 
 
1054
 
                int startPos = minPos;
1055
 
                int endPos = maxPos;
1056
 
 
1057
 
                // Range endpoints should not be inside DBCS characters, but just in case, move them.
1058
 
                startPos = MovePositionOutsideChar(startPos, 1, false);
1059
 
                endPos = MovePositionOutsideChar(endPos, 1, false);
1060
 
 
1061
 
                const char *errmsg = pre->Compile(s, *length, caseSensitive, posix);
1062
 
                if (errmsg) {
1063
 
                        return -1;
1064
 
                }
1065
 
                // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
1066
 
                // Replace first '.' with '-' in each property file variable reference:
1067
 
                //     Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
1068
 
                //     Replace: $(\1-\2)
1069
 
                int lineRangeStart = LineFromPosition(startPos);
1070
 
                int lineRangeEnd = LineFromPosition(endPos);
1071
 
                if ((increment == 1) &&
1072
 
                        (startPos >= LineEnd(lineRangeStart)) &&
1073
 
                        (lineRangeStart < lineRangeEnd)) {
1074
 
                        // the start position is at end of line or between line end characters.
1075
 
                        lineRangeStart++;
1076
 
                        startPos = LineStart(lineRangeStart);
1077
 
                }
1078
 
                int pos = -1;
1079
 
                int lenRet = 0;
1080
 
                char searchEnd = s[*length - 1];
1081
 
                int lineRangeBreak = lineRangeEnd + increment;
1082
 
                for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
1083
 
                        int startOfLine = LineStart(line);
1084
 
                        int endOfLine = LineEnd(line);
1085
 
                        if (increment == 1) {
1086
 
                                if (line == lineRangeStart) {
1087
 
                                        if ((startPos != startOfLine) && (s[0] == '^'))
1088
 
                                                continue;       // Can't match start of line if start position after start of line
1089
 
                                        startOfLine = startPos;
1090
 
                                }
1091
 
                                if (line == lineRangeEnd) {
1092
 
                                        if ((endPos != endOfLine) && (searchEnd == '$'))
1093
 
                                                continue;       // Can't match end of line if end position before end of line
1094
 
                                        endOfLine = endPos;
1095
 
                                }
1096
 
                        } else {
1097
 
                                if (line == lineRangeEnd) {
1098
 
                                        if ((endPos != startOfLine) && (s[0] == '^'))
1099
 
                                                continue;       // Can't match start of line if end position after start of line
1100
 
                                        startOfLine = endPos;
1101
 
                                }
1102
 
                                if (line == lineRangeStart) {
1103
 
                                        if ((startPos != endOfLine) && (searchEnd == '$'))
1104
 
                                                continue;       // Can't match end of line if start position before end of line
1105
 
                                        endOfLine = startPos;
1106
 
                                }
1107
 
                        }
1108
 
 
1109
 
                        DocumentIndexer di(this, endOfLine);
1110
 
                        int success = pre->Execute(di, startOfLine, endOfLine);
1111
 
                        if (success) {
1112
 
                                pos = pre->bopat[0];
1113
 
                                lenRet = pre->eopat[0] - pre->bopat[0];
1114
 
                                if (increment == -1) {
1115
 
                                        // Check for the last match on this line.
1116
 
                                        int repetitions = 1000; // Break out of infinite loop
1117
 
                                        while (success && (pre->eopat[0] <= endOfLine) && (repetitions--)) {
1118
 
                                                success = pre->Execute(di, pos+1, endOfLine);
1119
 
                                                if (success) {
1120
 
                                                        if (pre->eopat[0] <= minPos) {
1121
 
                                                                pos = pre->bopat[0];
1122
 
                                                                lenRet = pre->eopat[0] - pre->bopat[0];
1123
 
                                                        } else {
1124
 
                                                                success = 0;
1125
 
                                                        }
1126
 
                                                }
1127
 
                                        }
1128
 
                                }
1129
 
                                break;
1130
 
                        }
1131
 
                }
1132
 
                *length = lenRet;
1133
 
                return pos;
1134
 
 
 
1024
                if (!regex)
 
1025
                        regex = CreateRegexSearch(&charClass);
 
1026
                return regex->FindText(this, minPos, maxPos, s, caseSensitive, word, wordStart, flags, length);
1135
1027
        } else {
1136
1028
 
1137
1029
                bool forward = minPos <= maxPos;
1201
1093
}
1202
1094
 
1203
1095
const char *Document::SubstituteByPosition(const char *text, int *length) {
1204
 
        if (!pre)
1205
 
                return 0;
1206
 
        delete []substituted;
1207
 
        substituted = 0;
1208
 
        DocumentIndexer di(this, Length());
1209
 
        if (!pre->GrabMatches(di))
1210
 
                return 0;
1211
 
        unsigned int lenResult = 0;
1212
 
        for (int i = 0; i < *length; i++) {
1213
 
                if (text[i] == '\\') {
1214
 
                        if (text[i + 1] >= '1' && text[i + 1] <= '9') {
1215
 
                                unsigned int patNum = text[i + 1] - '0';
1216
 
                                lenResult += pre->eopat[patNum] - pre->bopat[patNum];
1217
 
                                i++;
1218
 
                        } else {
1219
 
                                switch (text[i + 1]) {
1220
 
                                case 'a':
1221
 
                                case 'b':
1222
 
                                case 'f':
1223
 
                                case 'n':
1224
 
                                case 'r':
1225
 
                                case 't':
1226
 
                                case 'v':
1227
 
                                        i++;
1228
 
                                }
1229
 
                                lenResult++;
1230
 
                        }
1231
 
                } else {
1232
 
                        lenResult++;
1233
 
                }
1234
 
        }
1235
 
        substituted = new char[lenResult + 1];
1236
 
        if (!substituted)
1237
 
                return 0;
1238
 
        char *o = substituted;
1239
 
        for (int j = 0; j < *length; j++) {
1240
 
                if (text[j] == '\\') {
1241
 
                        if (text[j + 1] >= '1' && text[j + 1] <= '9') {
1242
 
                                unsigned int patNum = text[j + 1] - '0';
1243
 
                                unsigned int len = pre->eopat[patNum] - pre->bopat[patNum];
1244
 
                                if (pre->pat[patNum])   // Will be null if try for a match that did not occur
1245
 
                                        memcpy(o, pre->pat[patNum], len);
1246
 
                                o += len;
1247
 
                                j++;
1248
 
                        } else {
1249
 
                                j++;
1250
 
                                switch (text[j]) {
1251
 
                                case 'a':
1252
 
                                        *o++ = '\a';
1253
 
                                        break;
1254
 
                                case 'b':
1255
 
                                        *o++ = '\b';
1256
 
                                        break;
1257
 
                                case 'f':
1258
 
                                        *o++ = '\f';
1259
 
                                        break;
1260
 
                                case 'n':
1261
 
                                        *o++ = '\n';
1262
 
                                        break;
1263
 
                                case 'r':
1264
 
                                        *o++ = '\r';
1265
 
                                        break;
1266
 
                                case 't':
1267
 
                                        *o++ = '\t';
1268
 
                                        break;
1269
 
                                case 'v':
1270
 
                                        *o++ = '\v';
1271
 
                                        break;
1272
 
                                default:
1273
 
                                        *o++ = '\\';
1274
 
                                        j--;
1275
 
                                }
1276
 
                        }
1277
 
                } else {
1278
 
                        *o++ = text[j];
1279
 
                }
1280
 
        }
1281
 
        *o = '\0';
1282
 
        *length = lenResult;
1283
 
        return substituted;
 
1096
        return regex->SubstituteByPosition(this, text, length);
1284
1097
}
1285
1098
 
1286
1099
int Document::LinesTotal() const {
1380
1193
        }
1381
1194
}
1382
1195
 
1383
 
int Document::SetLineState(int line, int state) { 
 
1196
int Document::SetLineState(int line, int state) {
1384
1197
        int statePrevious = cb.SetLineState(line, state);
1385
1198
        if (state != statePrevious) {
1386
1199
                DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
1630
1443
        }
1631
1444
        return - 1;
1632
1445
}
 
1446
 
 
1447
/**
 
1448
 * Implementation of RegexSearchBase for the default built-in regular expression engine
 
1449
 */
 
1450
class BuiltinRegex : public RegexSearchBase {
 
1451
public:
 
1452
        BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {}
 
1453
 
 
1454
        virtual ~BuiltinRegex() {
 
1455
                delete substituted;
 
1456
        }
 
1457
 
 
1458
        virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
 
1459
                        bool caseSensitive, bool word, bool wordStart, int flags,
 
1460
                        int *length);
 
1461
 
 
1462
        virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length);
 
1463
 
 
1464
private:
 
1465
        RESearch search;
 
1466
        char *substituted;
 
1467
};
 
1468
 
 
1469
// Define a way for the Regular Expression code to access the document
 
1470
class DocumentIndexer : public CharacterIndexer {
 
1471
        Document *pdoc;
 
1472
        int end;
 
1473
public:
 
1474
        DocumentIndexer(Document *pdoc_, int end_) :
 
1475
                pdoc(pdoc_), end(end_) {
 
1476
        }
 
1477
 
 
1478
        virtual ~DocumentIndexer() {
 
1479
        }
 
1480
 
 
1481
        virtual char CharAt(int index) {
 
1482
                if (index < 0 || index >= end)
 
1483
                        return 0;
 
1484
                else
 
1485
                        return pdoc->CharAt(index);
 
1486
        }
 
1487
};
 
1488
 
 
1489
long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s,
 
1490
                        bool caseSensitive, bool, bool, int flags,
 
1491
                        int *length) {
 
1492
        bool posix = (flags & SCFIND_POSIX) != 0;
 
1493
        int increment = (minPos <= maxPos) ? 1 : -1;
 
1494
 
 
1495
        int startPos = minPos;
 
1496
        int endPos = maxPos;
 
1497
 
 
1498
        // Range endpoints should not be inside DBCS characters, but just in case, move them.
 
1499
        startPos = doc->MovePositionOutsideChar(startPos, 1, false);
 
1500
        endPos = doc->MovePositionOutsideChar(endPos, 1, false);
 
1501
 
 
1502
        const char *errmsg = search.Compile(s, *length, caseSensitive, posix);
 
1503
        if (errmsg) {
 
1504
                return -1;
 
1505
        }
 
1506
        // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
 
1507
        // Replace first '.' with '-' in each property file variable reference:
 
1508
        //     Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
 
1509
        //     Replace: $(\1-\2)
 
1510
        int lineRangeStart = doc->LineFromPosition(startPos);
 
1511
        int lineRangeEnd = doc->LineFromPosition(endPos);
 
1512
        if ((increment == 1) &&
 
1513
                (startPos >= doc->LineEnd(lineRangeStart)) &&
 
1514
                (lineRangeStart < lineRangeEnd)) {
 
1515
                // the start position is at end of line or between line end characters.
 
1516
                lineRangeStart++;
 
1517
                startPos = doc->LineStart(lineRangeStart);
 
1518
        }
 
1519
        int pos = -1;
 
1520
        int lenRet = 0;
 
1521
        char searchEnd = s[*length - 1];
 
1522
        int lineRangeBreak = lineRangeEnd + increment;
 
1523
        for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
 
1524
                int startOfLine = doc->LineStart(line);
 
1525
                int endOfLine = doc->LineEnd(line);
 
1526
                if (increment == 1) {
 
1527
                        if (line == lineRangeStart) {
 
1528
                                if ((startPos != startOfLine) && (s[0] == '^'))
 
1529
                                        continue;       // Can't match start of line if start position after start of line
 
1530
                                startOfLine = startPos;
 
1531
                        }
 
1532
                        if (line == lineRangeEnd) {
 
1533
                                if ((endPos != endOfLine) && (searchEnd == '$'))
 
1534
                                        continue;       // Can't match end of line if end position before end of line
 
1535
                                endOfLine = endPos;
 
1536
                        }
 
1537
                } else {
 
1538
                        if (line == lineRangeEnd) {
 
1539
                                if ((endPos != startOfLine) && (s[0] == '^'))
 
1540
                                        continue;       // Can't match start of line if end position after start of line
 
1541
                                startOfLine = endPos;
 
1542
                        }
 
1543
                        if (line == lineRangeStart) {
 
1544
                                if ((startPos != endOfLine) && (searchEnd == '$'))
 
1545
                                        continue;       // Can't match end of line if start position before end of line
 
1546
                                endOfLine = startPos;
 
1547
                        }
 
1548
                }
 
1549
 
 
1550
                DocumentIndexer di(doc, endOfLine);
 
1551
                int success = search.Execute(di, startOfLine, endOfLine);
 
1552
                if (success) {
 
1553
                        pos = search.bopat[0];
 
1554
                        lenRet = search.eopat[0] - search.bopat[0];
 
1555
                        if (increment == -1) {
 
1556
                                // Check for the last match on this line.
 
1557
                                int repetitions = 1000; // Break out of infinite loop
 
1558
                                while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
 
1559
                                        success = search.Execute(di, pos+1, endOfLine);
 
1560
                                        if (success) {
 
1561
                                                if (search.eopat[0] <= minPos) {
 
1562
                                                        pos = search.bopat[0];
 
1563
                                                        lenRet = search.eopat[0] - search.bopat[0];
 
1564
                                                } else {
 
1565
                                                        success = 0;
 
1566
                                                }
 
1567
                                        }
 
1568
                                }
 
1569
                        }
 
1570
                        break;
 
1571
                }
 
1572
        }
 
1573
        *length = lenRet;
 
1574
        return pos;
 
1575
}
 
1576
 
 
1577
const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, int *length) {
 
1578
        delete []substituted;
 
1579
        substituted = 0;
 
1580
        DocumentIndexer di(doc, doc->Length());
 
1581
        if (!search.GrabMatches(di))
 
1582
                return 0;
 
1583
        unsigned int lenResult = 0;
 
1584
        for (int i = 0; i < *length; i++) {
 
1585
                if (text[i] == '\\') {
 
1586
                        if (text[i + 1] >= '1' && text[i + 1] <= '9') {
 
1587
                                unsigned int patNum = text[i + 1] - '0';
 
1588
                                lenResult += search.eopat[patNum] - search.bopat[patNum];
 
1589
                                i++;
 
1590
                        } else {
 
1591
                                switch (text[i + 1]) {
 
1592
                                case 'a':
 
1593
                                case 'b':
 
1594
                                case 'f':
 
1595
                                case 'n':
 
1596
                                case 'r':
 
1597
                                case 't':
 
1598
                                case 'v':
 
1599
                                        i++;
 
1600
                                }
 
1601
                                lenResult++;
 
1602
                        }
 
1603
                } else {
 
1604
                        lenResult++;
 
1605
                }
 
1606
        }
 
1607
        substituted = new char[lenResult + 1];
 
1608
        if (!substituted)
 
1609
                return 0;
 
1610
        char *o = substituted;
 
1611
        for (int j = 0; j < *length; j++) {
 
1612
                if (text[j] == '\\') {
 
1613
                        if (text[j + 1] >= '1' && text[j + 1] <= '9') {
 
1614
                                unsigned int patNum = text[j + 1] - '0';
 
1615
                                unsigned int len = search.eopat[patNum] - search.bopat[patNum];
 
1616
                                if (search.pat[patNum]) // Will be null if try for a match that did not occur
 
1617
                                        memcpy(o, search.pat[patNum], len);
 
1618
                                o += len;
 
1619
                                j++;
 
1620
                        } else {
 
1621
                                j++;
 
1622
                                switch (text[j]) {
 
1623
                                case 'a':
 
1624
                                        *o++ = '\a';
 
1625
                                        break;
 
1626
                                case 'b':
 
1627
                                        *o++ = '\b';
 
1628
                                        break;
 
1629
                                case 'f':
 
1630
                                        *o++ = '\f';
 
1631
                                        break;
 
1632
                                case 'n':
 
1633
                                        *o++ = '\n';
 
1634
                                        break;
 
1635
                                case 'r':
 
1636
                                        *o++ = '\r';
 
1637
                                        break;
 
1638
                                case 't':
 
1639
                                        *o++ = '\t';
 
1640
                                        break;
 
1641
                                case 'v':
 
1642
                                        *o++ = '\v';
 
1643
                                        break;
 
1644
                                default:
 
1645
                                        *o++ = '\\';
 
1646
                                        j--;
 
1647
                                }
 
1648
                        }
 
1649
                } else {
 
1650
                        *o++ = text[j];
 
1651
                }
 
1652
        }
 
1653
        *o = '\0';
 
1654
        *length = lenResult;
 
1655
        return substituted;
 
1656
}
 
1657
 
 
1658
#ifndef SCI_OWNREGEX
 
1659
 
 
1660
RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) {
 
1661
        return new BuiltinRegex(charClassTable);
 
1662
}
 
1663
 
 
1664
#endif