diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.cxx | 44 | ||||
-rw-r--r-- | src/Document.h | 2 | ||||
-rw-r--r-- | src/Editor.cxx | 54 | ||||
-rw-r--r-- | src/Editor.h | 4 | ||||
-rw-r--r-- | src/RESearch.cxx | 120 | ||||
-rw-r--r-- | src/RESearch.h | 6 |
6 files changed, 154 insertions, 76 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 70ad061a5..ef9779016 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -826,7 +826,7 @@ long Document::FindText(int minPos, int maxPos, const char *s, startPos = MovePositionOutsideChar(startPos, 1, false); endPos = MovePositionOutsideChar(endPos, 1, false); - const char *errmsg = pre->Compile(s, caseSensitive); + const char *errmsg = pre->Compile(s, *length, caseSensitive); if (errmsg) { return -1; } @@ -841,6 +841,18 @@ long Document::FindText(int minPos, int maxPos, const char *s, char searchEnd = '\0'; if (*s) searchEnd = s[strlen(s) - 1]; + if (*length == 1) { + // These produce empty selections so nudge them on if needed + if (s[0] == '^') { + if (startPos == LineStart(lineRangeStart)) + startPos++; + } else if (s[0] == '$') { + if ((startPos == LineEnd(lineRangeStart)) && (lineRangeStart < lineRangeEnd)) + startPos = LineStart(lineRangeStart+1); + } + lineRangeStart = LineFromPosition(startPos); + lineRangeEnd = LineFromPosition(endPos); + } for (int line = lineRangeStart; line <= lineRangeEnd; line++) { int startOfLine = LineStart(line); int endOfLine = LineEnd(line); @@ -855,7 +867,7 @@ long Document::FindText(int minPos, int maxPos, const char *s, endOfLine = endPos; } DocumentIndexer di(this, endOfLine); - int success = pre->Execute(di, startOfLine); + int success = pre->Execute(di, startOfLine, endOfLine); if (success) { pos = pre->bopat[0]; lenRet = pre->eopat[0] - pre->bopat[0]; @@ -875,7 +887,9 @@ long Document::FindText(int minPos, int maxPos, const char *s, int endPos = MovePositionOutsideChar(maxPos, increment, false); // Compute actual search ranges needed - int lengthFind = strlen(s); + int lengthFind = *length; + if (lengthFind == -1) + lengthFind = strlen(s); int endSearch = endPos; if (startPos <= endPos) { endSearch = endPos - lengthFind + 1; @@ -929,7 +943,7 @@ long Document::FindText(int minPos, int maxPos, const char *s, return -1; } -const char *Document::SubstituteByPosition(const char *text) { +const char *Document::SubstituteByPosition(const char *text, int *length) { if (!pre) return 0; delete []substituted; @@ -938,11 +952,11 @@ const char *Document::SubstituteByPosition(const char *text) { if (!pre->GrabMatches(di)) return 0; unsigned int lenResult = 0; - for (const char *t = text; *t; t++) { - if ((*t == '\\') && (*(t + 1) >= '1' && *(t + 1) <= '9')) { - unsigned int patNum = *(t + 1) - '0'; + for (int i=0; i<*length; i++) { + if ((text[i] == '\\') && (text[i+1] >= '1' && text[i+1] <= '9')) { + unsigned int patNum = text[i+1] - '0'; lenResult += pre->eopat[patNum] - pre->bopat[patNum]; - t++; + i++; } else { lenResult++; } @@ -951,18 +965,20 @@ const char *Document::SubstituteByPosition(const char *text) { if (!substituted) return 0; char *o = substituted; - for (const char *s = text; *s; s++) { - if ((*s == '\\') && (*(s + 1) >= '1' && *(s + 1) <= '9')) { - unsigned int patNum = *(s + 1) - '0'; + for (int j=0; j<*length; j++) { + if ((text[j] == '\\') && (text[j+1] >= '1' && text[j+1] <= '9')) { + unsigned int patNum = text[j+1] - '0'; unsigned int len = pre->eopat[patNum] - pre->bopat[patNum]; - strcpy(o, pre->pat[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; - s++; + j++; } else { - *o++ = *s; + *o++ = text[j]; } } *o = '\0'; + *length = lenResult; return substituted; } diff --git a/src/Document.h b/src/Document.h index bfc1a6e57..aac0a971b 100644 --- a/src/Document.h +++ b/src/Document.h @@ -180,7 +180,7 @@ public: long FindText(int minPos, int maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, bool regExp, int *length); long FindText(int iMessage, unsigned long wParam, long lParam); - const char *SubstituteByPosition(const char *text); + const char *SubstituteByPosition(const char *text, int *length); int LinesTotal(); void ChangeCase(Range r, bool makeUpperCase); diff --git a/src/Editor.cxx b/src/Editor.cxx index e44fbc9f9..01eb02241 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -94,7 +94,8 @@ Editor::Editor() { targetStart = 0; targetEnd = 0; - + searchFlags = 0; + topLine = 0; posTopLine = 0; @@ -2541,6 +2542,25 @@ long Editor::SearchText( return pos; } +/** + * Search for text in the target range of the document. + * @return The position of the found text, -1 if not found. + */ +long Editor::SearchInTarget(const char *text, int length) { + int lengthFound = length; + int pos = pdoc->FindText(targetStart, targetEnd, text, + searchFlags & SCFIND_MATCHCASE, + searchFlags & SCFIND_WHOLEWORD, + searchFlags & SCFIND_WORDSTART, + searchFlags & SCFIND_REGEXP, + &lengthFound); + if (pos != -1) { + targetStart = pos; + targetEnd = pos + lengthFound; + } + return pos; +} + void Editor::GoToLine(int lineNo) { if (lineNo > pdoc->LinesTotal()) lineNo = pdoc->LinesTotal(); @@ -3267,21 +3287,22 @@ void Editor::EnsureLineVisible(int lineDoc) { } } -int Editor::ReplaceTarget(bool replacePatterns, const char *text) { +int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) { pdoc->BeginUndoAction(); + if (length == -1) + length = strlen(text); if (replacePatterns) { - text = pdoc->SubstituteByPosition(text); + text = pdoc->SubstituteByPosition(text, &length); if (!text) return 0; } if (targetStart != targetEnd) pdoc->DeleteChars(targetStart, targetEnd - targetStart); targetEnd = targetStart; - unsigned int len = strlen(text); - pdoc->InsertString(targetStart, text); - targetEnd = targetStart + len; + pdoc->InsertString(targetStart, text, length); + targetEnd = targetStart + length; pdoc->EndUndoAction(); - return len; + return length; } static bool ValidMargin(unsigned long wParam) { @@ -3619,6 +3640,25 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_REPLACETARGET: PLATFORM_ASSERT(lParam); return ReplaceTarget(wParam, reinterpret_cast<char *>(lParam)); + + case SCI_REPLACETARGETCOUNTED: + PLATFORM_ASSERT(lParam); + return ReplaceTarget(false, reinterpret_cast<char *>(lParam), wParam); + + case SCI_REPLACETARGETRECOUNTED: + PLATFORM_ASSERT(lParam); + return ReplaceTarget(true, reinterpret_cast<char *>(lParam), wParam); + + case SCI_SEARCHINTARGET: + PLATFORM_ASSERT(lParam); + return SearchInTarget(reinterpret_cast<char *>(lParam), wParam); + + case SCI_SETSEARCHFLAGS: + searchFlags = wParam; + break; + + case SCI_GETSEARCHFLAGS: + return searchFlags; case EM_LINESCROLL: case SCI_LINESCROLL: diff --git a/src/Editor.h b/src/Editor.h index c7c7b114e..7ed4868fe 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -118,6 +118,7 @@ protected: // ScintillaBase subclass needs access to much of Editor int anchor; int targetStart; int targetEnd; + int searchFlags; int topLine; int posTopLine; @@ -285,6 +286,7 @@ protected: // ScintillaBase subclass needs access to much of Editor long FindText(unsigned int iMessage, unsigned long wParam, long lParam); void SearchAnchor(); long SearchText(unsigned int iMessage, unsigned long wParam, long lParam); + long SearchInTarget(const char *text, int length); void GoToLine(int lineNo); char *CopyRange(int start, int end); @@ -320,7 +322,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void Expand(int &line, bool doExpand); void ToggleContraction(int line); void EnsureLineVisible(int lineDoc); - int ReplaceTarget(bool replacePatterns, const char *text); + int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; diff --git a/src/RESearch.cxx b/src/RESearch.cxx index 82f08b6e5..e0f821d31 100644 --- a/src/RESearch.cxx +++ b/src/RESearch.cxx @@ -30,6 +30,14 @@ * Modification history: * * $Log$ + * Revision 1.6 2001/04/29 13:32:10 nyamatongwe + * Addition of new target methods - versions of ReplaceTarget that take counted + * strings to allow for nulls, SearchInTarget and Get/SetSearchFlags to use a + * series of calls rather than a structure. + * Handling of \000 in search and replace. + * Handling of /escapes within character ranges of regular expressions. + * Some handling of bare ^ and $ regular expressions. + * * Revision 1.5 2001/04/20 07:36:09 nyamatongwe * Removed DEBUG code that failed to compile on GTK+. * @@ -214,8 +222,6 @@ #include "RESearch.h" -#define EXTEND - #define OKP 1 #define NOP 0 @@ -310,8 +316,20 @@ void RESearch::ChSetWithCase(char c, bool caseSensitive) { } } -const char *RESearch::Compile(const char *pat, bool caseSensitive) { - const char *p; /* pattern pointer */ +const char escapeValue(char ch) { + switch (ch) { + case 'a': return '\a'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + } + return 0; +} + +const char *RESearch::Compile(const char *pat, int length, bool caseSensitive) { char *mp=nfa; /* nfa pointer */ char *lp; /* saved pointer.. */ char *sp=nfa; /* another one.. */ @@ -323,14 +341,15 @@ const char *RESearch::Compile(const char *pat, bool caseSensitive) { char mask; /* xor mask -CCL/NCL */ int c1, c2; - if (!pat || !*pat) + if (!pat || !length) if (sta) return 0; else return badpat("No previous regular expression"); sta = NOP; - for (p = pat; *p; p++) { + const char *p=pat; /* pattern pointer */ + for (int i=0; i<length; i++, p++) { lp = mp; switch(*p) { @@ -359,34 +378,46 @@ const char *RESearch::Compile(const char *pat, bool caseSensitive) { case '[': /* match char class..*/ *mp++ = CCL; + i++; if (*++p == '^') { mask = '\377'; + i++; p++; - } - else + } else mask = 0; - if (*p == '-') /* real dash */ + if (*p == '-') { /* real dash */ + i++; ChSet(*p++); - if (*p == ']') /* real brac */ + } + if (*p == ']') { /* real brace */ + i++; ChSet(*p++); + } while (*p && *p != ']') { if (*p == '-' && *(p+1) && *(p+1) != ']') { + i++; p++; c1 = *(p-2) + 1; + i++; c2 = *p++; while (c1 <= c2) { ChSetWithCase(static_cast<char>(c1++), caseSensitive); } - } -#ifdef EXTEND - else if (*p == '\\' && *(p+1)) { + } else if (*p == '\\' && *(p+1)) { + i++; p++; + char escape = escapeValue(*p); + if (escape) + ChSetWithCase(escape, caseSensitive); + else + ChSetWithCase(*p, caseSensitive); + i++; + p++; + } else { + i++; ChSetWithCase(*p++, caseSensitive); } -#endif - else - ChSetWithCase(*p++, caseSensitive); } if (!*p) return badpat("Missing ]"); @@ -430,6 +461,7 @@ const char *RESearch::Compile(const char *pat, bool caseSensitive) { break; case '\\': /* tags, backrefs .. */ + i++; switch(*++p) { case '(': @@ -478,36 +510,16 @@ const char *RESearch::Compile(const char *pat, bool caseSensitive) { else return badpat("Undetermined reference"); break; -#ifdef EXTEND case 'a': - *mp++ = CHR; - *mp++ = '\a'; - break; case 'b': - *mp++ = CHR; - *mp++ = '\b'; - break; case 'n': - *mp++ = CHR; - *mp++ = '\n'; - break; case 'f': - *mp++ = CHR; - *mp++ = '\f'; - break; case 'r': - *mp++ = CHR; - *mp++ = '\r'; - break; case 't': - *mp++ = CHR; - *mp++ = '\t'; - break; case 'v': *mp++ = CHR; - *mp++ = '\v'; + *mp++ = escapeValue(*p); break; -#endif default: *mp++ = CHR; *mp++ = *p; @@ -558,7 +570,7 @@ const char *RESearch::Compile(const char *pat, bool caseSensitive) { * */ -int RESearch::Execute(CharacterIndexer &ci, int lp) { +int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) { char c; int ep = NOTFOUND; char *ap = nfa; @@ -571,17 +583,25 @@ int RESearch::Execute(CharacterIndexer &ci, int lp) { switch(*ap) { case BOL: /* anchored: match from BOL only */ - ep = PMatch(ci, lp, ap); + ep = PMatch(ci, lp, endp, ap); break; + case EOL: /* just searching for end of line normal path doesn't work */ + if (*(ap+1) == END) { + lp = endp; + ep = lp; + break; + } else { + return 0; + } case CHR: /* ordinary char: locate it fast */ c = *(ap+1); - while (ci.CharAt(lp) && ci.CharAt(lp) != c) + while ((lp < endp) && (ci.CharAt(lp) != c)) lp++; - if (!ci.CharAt(lp)) /* if EOS, fail, else fall thru. */ + if (lp >= endp) /* if EOS, fail, else fall thru. */ return 0; default: /* regular matching all the way. */ - while (ci.CharAt(lp)) { - ep = PMatch(ci, lp, ap); + while (lp < endp) { + ep = PMatch(ci, lp, endp, ap); if (ep != NOTFOUND) break; lp++; @@ -667,7 +687,7 @@ static char chrtyp[MAXCHR] = { #define CHRSKIP 3 /* [CLO] CHR chr END ... */ #define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */ -int RESearch::PMatch(CharacterIndexer &ci, int lp, char *ap) { +int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) { int op, c, n; int e; /* extra pointer for CLO */ int bp; /* beginning of subpat.. */ @@ -682,7 +702,7 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, char *ap) { return NOTFOUND; break; case ANY: - if (!ci.CharAt(lp++)) + if (lp++ >= endp) return NOTFOUND; break; case CCL: @@ -696,7 +716,7 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, char *ap) { return NOTFOUND; break; case EOL: - if (ci.CharAt(lp)) + if (lp < endp) return NOTFOUND; break; case BOT: @@ -726,18 +746,18 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, char *ap) { switch(*ap) { case ANY: - while (ci.CharAt(lp)) + while (lp < endp) lp++; n = ANYSKIP; break; case CHR: c = *(ap+1); - while (ci.CharAt(lp) && c == ci.CharAt(lp)) + while ((lp < endp) && (c == ci.CharAt(lp))) lp++; n = CHRSKIP; break; case CCL: - while (((c = ci.CharAt(lp)) != 0) && isinset(ap+1,c)) + while ((lp < endp) && isinset(ap+1,ci.CharAt(lp))) lp++; n = CCLSKIP; break; @@ -750,7 +770,7 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, char *ap) { ap += n; while (lp >= are) { - if ((e = PMatch(ci, lp, ap)) != NOTFOUND) + if ((e = PMatch(ci, lp, endp, ap)) != NOTFOUND) return e; --lp; } diff --git a/src/RESearch.h b/src/RESearch.h index 14a5471fd..28238bfb7 100644 --- a/src/RESearch.h +++ b/src/RESearch.h @@ -32,8 +32,8 @@ public: bool GrabMatches(CharacterIndexer &ci); void ChSet(char c); void ChSetWithCase(char c, bool caseSensitive); - const char *Compile(const char *pat, bool caseSensitive); - int Execute(CharacterIndexer &ci, int lp); + const char *Compile(const char *pat, int length, bool caseSensitive); + int Execute(CharacterIndexer &ci, int lp, int endp); void ModifyWord(char *s); int Substitute(CharacterIndexer &ci, char *src, char *dst); @@ -46,7 +46,7 @@ public: char *pat[MAXTAG]; private: - int PMatch(CharacterIndexer &ci, int lp, char *ap); + int PMatch(CharacterIndexer &ci, int lp, int endp, char *ap); int bol; int tagstk[MAXTAG]; /* subpat tag stack..*/ |