aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornyamatongwe <unknown>2001-04-03 12:45:38 +0000
committernyamatongwe <unknown>2001-04-03 12:45:38 +0000
commit4a76af5c71efaf28a34e9399d985d74d23649ac2 (patch)
tree9af75d238ed93765984a8d5c3663c6b88ffac1f5 /src
parent447b7052109f27609f2f89d031a76ad368b20946 (diff)
downloadscintilla-mirror-4a76af5c71efaf28a34e9399d985d74d23649ac2.tar.gz
Regular expression find support.
Diffstat (limited to 'src')
-rw-r--r--src/Document.cxx155
-rw-r--r--src/Document.h4
-rw-r--r--src/Editor.cxx30
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;