aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2008-06-29 09:18:49 +0000
committernyamatongwe <unknown>2008-06-29 09:18:49 +0000
commitc0e21edce865dad4431e8861cefa719f05d41baf (patch)
tree641f3e3b4b1237131a62c7089333109d3e4a80b8
parent9659de1f4d46343708afe84f05d54b019f55c315 (diff)
downloadscintilla-mirror-c0e21edce865dad4431e8861cefa719f05d41baf.tar.gz
Simon Steele's modification to allow replacing the regular
expression implementation.
-rw-r--r--src/Document.cxx422
-rw-r--r--src/Document.h24
-rw-r--r--src/Editor.cxx8
-rw-r--r--win32/PlatWin.cxx16
-rw-r--r--win32/ScintillaWin.cxx8
5 files changed, 271 insertions, 207 deletions
diff --git a/src/Document.cxx b/src/Document.cxx
index dba827c8d..bded3a32a 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -73,8 +73,7 @@ Document::Document() {
lenWatchers = 0;
matchesValid = false;
- pre = 0;
- substituted = 0;
+ regex = 0;
}
Document::~Document() {
@@ -84,10 +83,8 @@ Document::~Document() {
delete []watchers;
watchers = 0;
lenWatchers = 0;
- delete pre;
- pre = 0;
- delete []substituted;
- substituted = 0;
+ delete regex;
+ regex = 0;
}
// Increase reference count and return its previous value.
@@ -1015,123 +1012,18 @@ static inline char MakeLowerCase(char ch) {
return static_cast<char>(ch - 'A' + 'a');
}
-// Define a way for the Regular Expression code to access the document
-class DocumentIndexer : public CharacterIndexer {
- Document *pdoc;
- int end;
-public:
- DocumentIndexer(Document *pdoc_, int end_) :
- pdoc(pdoc_), end(end_) {
- }
-
- virtual ~DocumentIndexer() {
- }
-
- virtual char CharAt(int index) {
- if (index < 0 || index >= end)
- return 0;
- else
- return pdoc->CharAt(index);
- }
-};
-
/**
* Find text in document, supporting both forward and backward
* searches (just pass minPos > maxPos to do a backward search)
* Has not been tested with backwards DBCS searches yet.
*/
long Document::FindText(int minPos, int maxPos, const char *s,
- bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix,
+ bool caseSensitive, bool word, bool wordStart, bool regExp, int flags,
int *length) {
if (regExp) {
- if (!pre)
- pre = new RESearch(&charClass);
- if (!pre)
- return -1;
-
- int increment = (minPos <= maxPos) ? 1 : -1;
-
- int startPos = minPos;
- int endPos = maxPos;
-
- // Range endpoints should not be inside DBCS characters, but just in case, move them.
- startPos = MovePositionOutsideChar(startPos, 1, false);
- endPos = MovePositionOutsideChar(endPos, 1, false);
-
- const char *errmsg = pre->Compile(s, *length, caseSensitive, posix);
- if (errmsg) {
- return -1;
- }
- // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
- // Replace first '.' with '-' in each property file variable reference:
- // Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
- // Replace: $(\1-\2)
- int lineRangeStart = LineFromPosition(startPos);
- int lineRangeEnd = LineFromPosition(endPos);
- if ((increment == 1) &&
- (startPos >= LineEnd(lineRangeStart)) &&
- (lineRangeStart < lineRangeEnd)) {
- // the start position is at end of line or between line end characters.
- lineRangeStart++;
- startPos = LineStart(lineRangeStart);
- }
- int pos = -1;
- int lenRet = 0;
- char searchEnd = s[*length - 1];
- int lineRangeBreak = lineRangeEnd + increment;
- for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
- int startOfLine = LineStart(line);
- int endOfLine = LineEnd(line);
- if (increment == 1) {
- if (line == lineRangeStart) {
- if ((startPos != startOfLine) && (s[0] == '^'))
- continue; // Can't match start of line if start position after start of line
- startOfLine = startPos;
- }
- if (line == lineRangeEnd) {
- if ((endPos != endOfLine) && (searchEnd == '$'))
- continue; // Can't match end of line if end position before end of line
- endOfLine = endPos;
- }
- } else {
- if (line == lineRangeEnd) {
- if ((endPos != startOfLine) && (s[0] == '^'))
- continue; // Can't match start of line if end position after start of line
- startOfLine = endPos;
- }
- if (line == lineRangeStart) {
- if ((startPos != endOfLine) && (searchEnd == '$'))
- continue; // Can't match end of line if start position before end of line
- endOfLine = startPos;
- }
- }
-
- DocumentIndexer di(this, endOfLine);
- int success = pre->Execute(di, startOfLine, endOfLine);
- if (success) {
- pos = pre->bopat[0];
- lenRet = pre->eopat[0] - pre->bopat[0];
- if (increment == -1) {
- // Check for the last match on this line.
- int repetitions = 1000; // Break out of infinite loop
- while (success && (pre->eopat[0] <= endOfLine) && (repetitions--)) {
- success = pre->Execute(di, pos+1, endOfLine);
- if (success) {
- if (pre->eopat[0] <= minPos) {
- pos = pre->bopat[0];
- lenRet = pre->eopat[0] - pre->bopat[0];
- } else {
- success = 0;
- }
- }
- }
- }
- break;
- }
- }
- *length = lenRet;
- return pos;
-
+ if (!regex)
+ regex = CreateRegexSearch(&charClass);
+ return regex->FindText(this, minPos, maxPos, s, caseSensitive, word, wordStart, flags, length);
} else {
bool forward = minPos <= maxPos;
@@ -1201,86 +1093,7 @@ long Document::FindText(int minPos, int maxPos, const char *s,
}
const char *Document::SubstituteByPosition(const char *text, int *length) {
- if (!pre)
- return 0;
- delete []substituted;
- substituted = 0;
- DocumentIndexer di(this, Length());
- if (!pre->GrabMatches(di))
- return 0;
- unsigned int lenResult = 0;
- for (int i = 0; i < *length; i++) {
- if (text[i] == '\\') {
- if (text[i + 1] >= '1' && text[i + 1] <= '9') {
- unsigned int patNum = text[i + 1] - '0';
- lenResult += pre->eopat[patNum] - pre->bopat[patNum];
- i++;
- } else {
- switch (text[i + 1]) {
- case 'a':
- case 'b':
- case 'f':
- case 'n':
- case 'r':
- case 't':
- case 'v':
- i++;
- }
- lenResult++;
- }
- } else {
- lenResult++;
- }
- }
- substituted = new char[lenResult + 1];
- if (!substituted)
- return 0;
- char *o = substituted;
- for (int j = 0; j < *length; j++) {
- if (text[j] == '\\') {
- if (text[j + 1] >= '1' && text[j + 1] <= '9') {
- unsigned int patNum = text[j + 1] - '0';
- unsigned int len = pre->eopat[patNum] - pre->bopat[patNum];
- if (pre->pat[patNum]) // Will be null if try for a match that did not occur
- memcpy(o, pre->pat[patNum], len);
- o += len;
- j++;
- } else {
- j++;
- switch (text[j]) {
- case 'a':
- *o++ = '\a';
- break;
- case 'b':
- *o++ = '\b';
- break;
- case 'f':
- *o++ = '\f';
- break;
- case 'n':
- *o++ = '\n';
- break;
- case 'r':
- *o++ = '\r';
- break;
- case 't':
- *o++ = '\t';
- break;
- case 'v':
- *o++ = '\v';
- break;
- default:
- *o++ = '\\';
- j--;
- }
- }
- } else {
- *o++ = text[j];
- }
- }
- *o = '\0';
- *length = lenResult;
- return substituted;
+ return regex->SubstituteByPosition(this, text, length);
}
int Document::LinesTotal() const {
@@ -1630,3 +1443,222 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) {
}
return - 1;
}
+
+/**
+ * Implementation of RegexSearchBase for the default built-in regular expression engine
+ */
+class BuiltinRegex : public RegexSearchBase {
+public:
+ BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {}
+
+ virtual ~BuiltinRegex() {
+ delete substituted;
+ }
+
+ virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool word, bool wordStart, int flags,
+ int *length);
+
+ virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length);
+
+private:
+ RESearch search;
+ char *substituted;
+};
+
+// Define a way for the Regular Expression code to access the document
+class DocumentIndexer : public CharacterIndexer {
+ Document *pdoc;
+ int end;
+public:
+ DocumentIndexer(Document *pdoc_, int end_) :
+ pdoc(pdoc_), end(end_) {
+ }
+
+ virtual ~DocumentIndexer() {
+ }
+
+ virtual char CharAt(int index) {
+ if (index < 0 || index >= end)
+ return 0;
+ else
+ return pdoc->CharAt(index);
+ }
+};
+
+long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool, bool, int flags,
+ int *length) {
+ bool posix = (flags & SCFIND_POSIX) != 0;
+ int increment = (minPos <= maxPos) ? 1 : -1;
+
+ int startPos = minPos;
+ int endPos = maxPos;
+
+ // Range endpoints should not be inside DBCS characters, but just in case, move them.
+ startPos = doc->MovePositionOutsideChar(startPos, 1, false);
+ endPos = doc->MovePositionOutsideChar(endPos, 1, false);
+
+ const char *errmsg = search.Compile(s, *length, caseSensitive, posix);
+ if (errmsg) {
+ return -1;
+ }
+ // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
+ // Replace first '.' with '-' in each property file variable reference:
+ // Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
+ // Replace: $(\1-\2)
+ int lineRangeStart = doc->LineFromPosition(startPos);
+ int lineRangeEnd = doc->LineFromPosition(endPos);
+ if ((increment == 1) &&
+ (startPos >= doc->LineEnd(lineRangeStart)) &&
+ (lineRangeStart < lineRangeEnd)) {
+ // the start position is at end of line or between line end characters.
+ lineRangeStart++;
+ startPos = doc->LineStart(lineRangeStart);
+ }
+ int pos = -1;
+ int lenRet = 0;
+ char searchEnd = s[*length - 1];
+ int lineRangeBreak = lineRangeEnd + increment;
+ for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
+ int startOfLine = doc->LineStart(line);
+ int endOfLine = doc->LineEnd(line);
+ if (increment == 1) {
+ if (line == lineRangeStart) {
+ if ((startPos != startOfLine) && (s[0] == '^'))
+ continue; // Can't match start of line if start position after start of line
+ startOfLine = startPos;
+ }
+ if (line == lineRangeEnd) {
+ if ((endPos != endOfLine) && (searchEnd == '$'))
+ continue; // Can't match end of line if end position before end of line
+ endOfLine = endPos;
+ }
+ } else {
+ if (line == lineRangeEnd) {
+ if ((endPos != startOfLine) && (s[0] == '^'))
+ continue; // Can't match start of line if end position after start of line
+ startOfLine = endPos;
+ }
+ if (line == lineRangeStart) {
+ if ((startPos != endOfLine) && (searchEnd == '$'))
+ continue; // Can't match end of line if start position before end of line
+ endOfLine = startPos;
+ }
+ }
+
+ DocumentIndexer di(doc, endOfLine);
+ int success = search.Execute(di, startOfLine, endOfLine);
+ if (success) {
+ pos = search.bopat[0];
+ lenRet = search.eopat[0] - search.bopat[0];
+ if (increment == -1) {
+ // Check for the last match on this line.
+ int repetitions = 1000; // Break out of infinite loop
+ while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
+ success = search.Execute(di, pos+1, endOfLine);
+ if (success) {
+ if (search.eopat[0] <= minPos) {
+ pos = search.bopat[0];
+ lenRet = search.eopat[0] - search.bopat[0];
+ } else {
+ success = 0;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ *length = lenRet;
+ return pos;
+}
+
+const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, int *length) {
+ delete []substituted;
+ substituted = 0;
+ DocumentIndexer di(doc, doc->Length());
+ if (!search.GrabMatches(di))
+ return 0;
+ unsigned int lenResult = 0;
+ for (int i = 0; i < *length; i++) {
+ if (text[i] == '\\') {
+ if (text[i + 1] >= '1' && text[i + 1] <= '9') {
+ unsigned int patNum = text[i + 1] - '0';
+ lenResult += search.eopat[patNum] - search.bopat[patNum];
+ i++;
+ } else {
+ switch (text[i + 1]) {
+ case 'a':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'v':
+ i++;
+ }
+ lenResult++;
+ }
+ } else {
+ lenResult++;
+ }
+ }
+ substituted = new char[lenResult + 1];
+ if (!substituted)
+ return 0;
+ char *o = substituted;
+ for (int j = 0; j < *length; j++) {
+ if (text[j] == '\\') {
+ if (text[j + 1] >= '1' && text[j + 1] <= '9') {
+ unsigned int patNum = text[j + 1] - '0';
+ unsigned int len = search.eopat[patNum] - search.bopat[patNum];
+ if (search.pat[patNum]) // Will be null if try for a match that did not occur
+ memcpy(o, search.pat[patNum], len);
+ o += len;
+ j++;
+ } else {
+ j++;
+ switch (text[j]) {
+ case 'a':
+ *o++ = '\a';
+ break;
+ case 'b':
+ *o++ = '\b';
+ break;
+ case 'f':
+ *o++ = '\f';
+ break;
+ case 'n':
+ *o++ = '\n';
+ break;
+ case 'r':
+ *o++ = '\r';
+ break;
+ case 't':
+ *o++ = '\t';
+ break;
+ case 'v':
+ *o++ = '\v';
+ break;
+ default:
+ *o++ = '\\';
+ j--;
+ }
+ }
+ } else {
+ *o++ = text[j];
+ }
+ }
+ *o = '\0';
+ *length = lenResult;
+ return substituted;
+}
+
+#ifndef SCI_OWNREGEX
+
+RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) {
+ return new BuiltinRegex(charClassTable);
+}
+
+#endif
diff --git a/src/Document.h b/src/Document.h
index 04bbd5c74..0457b475b 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -74,7 +74,24 @@ public:
class DocWatcher;
class DocModification;
-class RESearch;
+class Document;
+
+/**
+ * Interface class for regular expression searching
+ */
+class RegexSearchBase {
+public:
+ virtual ~RegexSearchBase(){}
+
+ virtual long FindText(Document* doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0;
+
+ ///@return String with the substitutions, must remain valid until the next call or destruction
+ virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length) = 0;
+};
+
+/// Factory function for RegexSearchBase
+extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable);
/**
*/
@@ -109,8 +126,7 @@ private:
int lenWatchers;
bool matchesValid;
- RESearch *pre;
- char *substituted;
+ RegexSearchBase* regex;
public:
int stylingBits;
@@ -208,7 +224,7 @@ public:
int Length() const { return cb.Length(); }
void Allocate(int newSize) { cb.Allocate(newSize); }
long FindText(int minPos, int maxPos, const char *s,
- bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix, int *length);
+ bool caseSensitive, bool word, bool wordStart, bool regExp, int flags, int *length);
long FindText(int iMessage, unsigned long wParam, long lParam);
const char *SubstituteByPosition(const char *text, int *length);
int LinesTotal() const;
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 3b6e7a2c3..95664e2b1 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -4806,7 +4806,7 @@ long Editor::FindText(
(wParam & SCFIND_WHOLEWORD) != 0,
(wParam & SCFIND_WORDSTART) != 0,
(wParam & SCFIND_REGEXP) != 0,
- (wParam & SCFIND_POSIX) != 0,
+ wParam,
&lengthFound);
if (pos != -1) {
ft->chrgText.cpMin = pos;
@@ -4850,7 +4850,7 @@ long Editor::SearchText(
(wParam & SCFIND_WHOLEWORD) != 0,
(wParam & SCFIND_WORDSTART) != 0,
(wParam & SCFIND_REGEXP) != 0,
- (wParam & SCFIND_POSIX) != 0,
+ wParam,
&lengthFound);
} else {
pos = pdoc->FindText(searchAnchor, 0, txt,
@@ -4858,7 +4858,7 @@ long Editor::SearchText(
(wParam & SCFIND_WHOLEWORD) != 0,
(wParam & SCFIND_WORDSTART) != 0,
(wParam & SCFIND_REGEXP) != 0,
- (wParam & SCFIND_POSIX) != 0,
+ wParam,
&lengthFound);
}
@@ -4880,7 +4880,7 @@ long Editor::SearchInTarget(const char *text, int length) {
(searchFlags & SCFIND_WHOLEWORD) != 0,
(searchFlags & SCFIND_WORDSTART) != 0,
(searchFlags & SCFIND_REGEXP) != 0,
- (searchFlags & SCFIND_POSIX) != 0,
+ searchFlags,
&lengthFound);
if (pos != -1) {
targetStart = pos;
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index c818ab7fa..09d97917a 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -77,6 +77,10 @@ bool IsNT() {
return onNT;
}
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
Point Point::FromLong(long lpoint) {
return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
}
@@ -219,7 +223,7 @@ FontCached *FontCached::first = 0;
FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) :
next(0), usage(0), hash(0) {
- ::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
+ SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
hash = HashFont(faceName_, characterSet_, size_, bold_, italic_);
id = ::CreateFontIndirectA(&lf);
usage = 1;
@@ -296,7 +300,7 @@ void Font::Create(const char *faceName, int characterSet, int size,
Release();
#ifndef FONTS_CACHED
LOGFONT lf;
- ::SetLogFont(lf, faceName, characterSet, size, bold, italic);
+ SetLogFont(lf, faceName, characterSet, size, bold, italic);
id = ::CreateFontIndirect(&lf);
#else
id = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
@@ -314,6 +318,10 @@ void Font::Release() {
id = 0;
}
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
class SurfaceImpl : public Surface {
bool unicodeMode;
HDC hdc;
@@ -387,6 +395,10 @@ public:
void SetDBCSMode(int codePage_);
};
+#ifdef SCI_NAMESPACE
+} //namespace Scintilla
+#endif
+
SurfaceImpl::SurfaceImpl() :
unicodeMode(false),
hdc(0), hdcOwned(false),
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index e55892b62..9568aa85d 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -99,6 +99,10 @@ extern void Platform_Finalise();
const TCHAR scintillaClassName[] = TEXT("Scintilla");
const TCHAR callClassName[] = TEXT("CallTip");
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
class ScintillaWin; // Forward declaration for COM interface subobjects
/**
@@ -2247,7 +2251,7 @@ bool ScintillaWin::Register(HINSTANCE hInstance_) {
WNDCLASSEXW wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
+ wndclass.lpfnWndProc = ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;
@@ -2264,7 +2268,7 @@ bool ScintillaWin::Register(HINSTANCE hInstance_) {
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
+ wndclass.lpfnWndProc = ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;