diff options
author | nyamatongwe <unknown> | 2001-04-03 12:45:38 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2001-04-03 12:45:38 +0000 |
commit | 4a76af5c71efaf28a34e9399d985d74d23649ac2 (patch) | |
tree | 9af75d238ed93765984a8d5c3663c6b88ffac1f5 /src | |
parent | 447b7052109f27609f2f89d031a76ad368b20946 (diff) | |
download | scintilla-mirror-4a76af5c71efaf28a34e9399d985d74d23649ac2.tar.gz |
Regular expression find support.
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.cxx | 155 | ||||
-rw-r--r-- | src/Document.h | 4 | ||||
-rw-r--r-- | src/Editor.cxx | 30 |
3 files changed, 124 insertions, 65 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 6be928cf7..babe25bcf 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -16,6 +16,7 @@ #include "SVector.h" #include "CellBuffer.h" #include "Document.h" +#include "PosRegExp.h" // This is ASCII specific but is safe with chars >= 0x80 inline bool isspacechar(unsigned char ch) { @@ -742,70 +743,118 @@ bool Document::IsWordAt(int start, int end) { return IsWordStartAt(start) && IsWordEndAt(end); } +char Document::DocCharAt(int pos, void *param) { + return reinterpret_cast<Document*>(param)->CharAt(pos); +} + // 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 forward = minPos <= maxPos; - int increment = forward ? 1 : -1; - - // Range endpoints should not be inside DBCS characters, but just in case, move them. - int startPos = MovePositionOutsideChar(minPos, increment, false); - int endPos = MovePositionOutsideChar(maxPos, increment, false); - - // Compute actual search ranges needed - int lengthFind = strlen(s); - int endSearch = endPos; - if (startPos <= endPos) { - endSearch = endPos - lengthFind + 1; - } - //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); - char firstChar = s[0]; - if (!caseSensitive) - firstChar = static_cast<char>(toupper(firstChar)); - int pos = startPos; - while (forward ? (pos < endSearch) : (pos >= endSearch)) { - char ch = CharAt(pos); - if (caseSensitive) { - if (ch == firstChar) { - bool found = true; - for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { - ch = CharAt(pos + posMatch); - if (ch != s[posMatch]) - found = false; - } - if (found) { - if ((!word && !wordStart) || - word && IsWordAt(pos, pos + lengthFind) || - wordStart && IsWordStartAt(pos)) - return pos; - } - } + bool caseSensitive, bool word, bool wordStart, bool regExp, + int *length) { + if (regExp) { + char *pat = new char[strlen(s) + 4]; + if (!pat) + return -1; + + strcpy(pat, "/"); + int startPos; + int endPos; + + if (minPos <= maxPos) { + startPos = minPos; + endPos = maxPos; } else { - if (toupper(ch) == firstChar) { - bool found = true; - for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { - ch = CharAt(pos + posMatch); - if (toupper(ch) != toupper(s[posMatch])) - found = false; + startPos = maxPos; + endPos = minPos; + } + + // Range endpoints should not be inside DBCS characters, but just in case, move them. + startPos = MovePositionOutsideChar(startPos, 1, false); + endPos = MovePositionOutsideChar(endPos, 1, false); + + strcat(pat, s); + strcat(pat, "/"); + PosRegExp re; + if (!caseSensitive) + strcat(pat, "i"); + if (!re.SetExpr(pat)) { + delete []pat; + return -1; + } + re.param = this; + re.CharAt = DocCharAt; + SMatches matches; + if (!re.Parse(startPos, 0, endPos, &matches)) { + delete []pat; + return -1; + } + *length = matches.e[0] - matches.s[0]; + delete []pat; + return matches.s[0]; + } else { + + bool forward = minPos <= maxPos; + int increment = forward ? 1 : -1; + + // Range endpoints should not be inside DBCS characters, but just in case, move them. + int startPos = MovePositionOutsideChar(minPos, increment, false); + int endPos = MovePositionOutsideChar(maxPos, increment, false); + + // Compute actual search ranges needed + int lengthFind = strlen(s); + int endSearch = endPos; + if (startPos <= endPos) { + endSearch = endPos - lengthFind + 1; + } + //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); + char firstChar = s[0]; + if (!caseSensitive) + firstChar = static_cast<char>(toupper(firstChar)); + int pos = startPos; + while (forward ? (pos < endSearch) : (pos >= endSearch)) { + char ch = CharAt(pos); + if (caseSensitive) { + if (ch == firstChar) { + bool found = true; + for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { + ch = CharAt(pos + posMatch); + if (ch != s[posMatch]) + found = false; + } + if (found) { + if ((!word && !wordStart) || + word && IsWordAt(pos, pos + lengthFind) || + wordStart && IsWordStartAt(pos)) + return pos; + } } - if (found) { - if ((!word && !wordStart) || - word && IsWordAt(pos, pos + lengthFind) || - wordStart && IsWordStartAt(pos)) - return pos; + } else { + if (toupper(ch) == firstChar) { + bool found = true; + for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { + ch = CharAt(pos + posMatch); + if (toupper(ch) != toupper(s[posMatch])) + found = false; + } + if (found) { + if ((!word && !wordStart) || + word && IsWordAt(pos, pos + lengthFind) || + wordStart && IsWordStartAt(pos)) + return pos; + } } } - } - pos += increment; - if (dbcsCodePage) { - // Ensure trying to match from start of character - pos = MovePositionOutsideChar(pos, increment, false); + pos += increment; + if (dbcsCodePage) { + // Ensure trying to match from start of character + pos = MovePositionOutsideChar(pos, increment, false); + } } } //Platform::DebugPrintf("Not found\n"); - return - 1; + return -1; } int Document::LinesTotal() { diff --git a/src/Document.h b/src/Document.h index 4b0b9b1db..cfb131608 100644 --- a/src/Document.h +++ b/src/Document.h @@ -173,7 +173,7 @@ public: int NextWordStart(int pos, int delta); int Length() { return cb.Length(); } long FindText(int minPos, int maxPos, const char *s, - bool caseSensitive, bool word, bool wordStart); + bool caseSensitive, bool word, bool wordStart, bool regExp, int *length); long FindText(int iMessage, unsigned long wParam, long lParam); int LinesTotal(); @@ -196,6 +196,8 @@ public: const WatcherWithUserData *GetWatchers() const { return watchers; } int GetLenWatchers() const { return lenWatchers; } + static char DocCharAt(int pos, void *param); + bool IsWordPartSeparator(char ch); int WordPartLeft(int pos); int WordPartRight(int pos); diff --git a/src/Editor.cxx b/src/Editor.cxx index afc127c07..479157e39 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2458,13 +2458,17 @@ void Editor::Indent(bool forwards) { long Editor::FindText(unsigned int iMessage, unsigned long wParam, long lParam) { TextToFind *ft = reinterpret_cast<TextToFind *>(lParam); + int lengthFound = strlen(ft->lpstrText); int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, - wParam & SCFIND_MATCHCASE, wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART); + wParam & SCFIND_MATCHCASE, + wParam & SCFIND_WHOLEWORD, + wParam & SCFIND_WORDSTART, + wParam & SCFIND_REGEXP, + &lengthFound); if (pos != -1) { if (iMessage != EM_FINDTEXT) { ft->chrgText.cpMin = pos; - ft->chrgText.cpMax = pos + strlen(ft->lpstrText); + ft->chrgText.cpMax = pos + lengthFound; } } return pos; @@ -2489,21 +2493,25 @@ void Editor::SearchAnchor() { long Editor::SearchText(unsigned int iMessage, unsigned long wParam, long lParam) { const char *txt = reinterpret_cast<char *>(lParam); int pos; - + int lengthFound = strlen(txt); if (iMessage == SCI_SEARCHNEXT) { pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, - wParam & SCFIND_MATCHCASE, - wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART); + wParam & SCFIND_MATCHCASE, + wParam & SCFIND_WHOLEWORD, + wParam & SCFIND_WORDSTART, + wParam & SCFIND_REGEXP, + &lengthFound); } else { pos = pdoc->FindText(searchAnchor, 0, txt, - wParam & SCFIND_MATCHCASE, - wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART); + wParam & SCFIND_MATCHCASE, + wParam & SCFIND_WHOLEWORD, + wParam & SCFIND_WORDSTART, + wParam & SCFIND_REGEXP, + &lengthFound); } if (pos != -1) { - SetSelection(pos, pos + strlen(txt)); + SetSelection(pos, pos + lengthFound); } return pos; |