diff options
author | nyamatongwe <unknown> | 2013-01-10 10:08:01 +1100 |
---|---|---|
committer | nyamatongwe <unknown> | 2013-01-10 10:08:01 +1100 |
commit | 32776d4e53abbe0a1a41e811798bbc9dcd569b11 (patch) | |
tree | 28937d7071c1d1a92a33e22e960e2bf96b0ae90a | |
parent | 62c08fe0cd0c4e06902a47f6dda0c7849b7d23fc (diff) | |
download | scintilla-mirror-32776d4e53abbe0a1a41e811798bbc9dcd569b11.tar.gz |
Add a replace method and a parameter for backwards search.
From Mike Lischke.
-rw-r--r-- | cocoa/ScintillaView.h | 15 | ||||
-rw-r--r-- | cocoa/ScintillaView.mm | 189 |
2 files changed, 180 insertions, 24 deletions
diff --git a/cocoa/ScintillaView.h b/cocoa/ScintillaView.h index d5f500df3..29bf5591d 100644 --- a/cocoa/ScintillaView.h +++ b/cocoa/ScintillaView.h @@ -144,10 +144,23 @@ extern NSString *SCIUpdateUINotification; - (void) setInfoBar: (NSView <InfoBarCommunicator>*) aView top: (BOOL) top; - (void) setStatusText: (NSString*) text; -- (void) findAndHighlightText: (NSString*) searchText +- (BOOL) findAndHighlightText: (NSString*) searchText matchCase: (BOOL) matchCase wholeWord: (BOOL) wholeWord scrollTo: (BOOL) scrollTo wrap: (BOOL) wrap; +- (BOOL) findAndHighlightText: (NSString*) searchText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + scrollTo: (BOOL) scrollTo + wrap: (BOOL) wrap + backwards: (BOOL) backwards; + +- (int) findAndReplaceText: (NSString*) searchText + byText: (NSString*) newText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + doAll: (BOOL) doAll; + @end diff --git a/cocoa/ScintillaView.mm b/cocoa/ScintillaView.mm index 40a410a87..0d3bb4540 100644 --- a/cocoa/ScintillaView.mm +++ b/cocoa/ScintillaView.mm @@ -1548,49 +1548,192 @@ static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wPa //-------------------------------------------------------------------------------------------------- /** - * Searches and marks the first occurance of the given text and optionally scrolls it into view. + * For backwards compatibility. */ -- (void) findAndHighlightText: (NSString*) searchText +- (BOOL) findAndHighlightText: (NSString*) searchText matchCase: (BOOL) matchCase wholeWord: (BOOL) wholeWord scrollTo: (BOOL) scrollTo wrap: (BOOL) wrap { - // The current position is where we start searching. That is either the end of the current - // (main) selection or the caret position. That ensures we do proper "search next" too. - long currentPosition = [self getGeneralProperty: SCI_GETCURRENTPOS parameter: 0]; - long length = [self getGeneralProperty: SCI_GETTEXTLENGTH parameter: 0]; + return [self findAndHighlightText: searchText + matchCase: matchCase + wholeWord: wholeWord + scrollTo: scrollTo + wrap: wrap + backwards: NO]; +} + +//-------------------------------------------------------------------------------------------------- +/** + * Searches and marks the first occurance of the given text and optionally scrolls it into view. + * + * @result YES if something was found, NO otherwise. + */ +- (BOOL) findAndHighlightText: (NSString*) searchText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + scrollTo: (BOOL) scrollTo + wrap: (BOOL) wrap + backwards: (BOOL) backwards +{ int searchFlags= 0; if (matchCase) searchFlags |= SCFIND_MATCHCASE; if (wholeWord) searchFlags |= SCFIND_WHOLEWORD; - Sci_TextToFind ttf; - ttf.chrg.cpMin = currentPosition; - ttf.chrg.cpMax = length; - ttf.lpstrText = (char*) [searchText UTF8String]; - long position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); + int selectionStart = [self getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0]; + int selectionEnd = [self getGeneralProperty: SCI_GETSELECTIONEND parameter: 0]; - if (position < 0 && wrap) + // Sets the start point for the comming search to the begin of the current selection. + // For forward searches we have therefore to set the selection start to the current selection end + // for proper incremental search. This does not harm as we either get a new selection if something + // is found or the previous selection is restored. + if (!backwards) + [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: selectionEnd]; + [self setGeneralProperty: SCI_SEARCHANCHOR value: 0]; + sptr_t result; + const char* textToSearch = [searchText UTF8String]; + + // The following call will also set the selection if something was found. + if (backwards) { - ttf.chrg.cpMin = 0; - ttf.chrg.cpMax = currentPosition; - position = mBackend->WndProc(SCI_FINDTEXT, searchFlags, (sptr_t) &ttf); + result = [ScintillaView directCall: self + message: SCI_SEARCHPREV + wParam: searchFlags + lParam: (sptr_t) textToSearch]; + if (result < 0 && wrap) + { + // Try again from the end of the document if nothing could be found so far and + // wrapped search is set. + [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: [self getGeneralProperty: SCI_GETTEXTLENGTH parameter: 0]]; + [self setGeneralProperty: SCI_SEARCHANCHOR value: 0]; + result = [ScintillaView directCall: self + message: SCI_SEARCHNEXT + wParam: searchFlags + lParam: (sptr_t) textToSearch]; + } } - - if (position >= 0) + else + { + result = [ScintillaView directCall: self + message: SCI_SEARCHNEXT + wParam: searchFlags + lParam: (sptr_t) textToSearch]; + if (result < 0 && wrap) + { + // Try again from the start of the document if nothing could be found so far and + // wrapped search is set. + [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: 0]; + [self setGeneralProperty: SCI_SEARCHANCHOR value: 0]; + result = [ScintillaView directCall: self + message: SCI_SEARCHNEXT + wParam: searchFlags + lParam: (sptr_t) textToSearch]; + } + } + + if (result >= 0) { - // Highlight the found text. - [self setGeneralProperty: SCI_SETSELECTIONSTART - value: position]; - [self setGeneralProperty: SCI_SETSELECTIONEND - value: position + [searchText length]]; - if (scrollTo) [self setGeneralProperty: SCI_SCROLLCARET value: 0]; } + else + { + // Restore the former selection if we did not find anything. + [self setGeneralProperty: SCI_SETSELECTIONSTART value: selectionStart]; + [self setGeneralProperty: SCI_SETSELECTIONEND value: selectionEnd]; + } + return (result >= 0) ? YES : NO; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Searches the given text and replaces + * + * @result Number of entries replaced, 0 if none. + */ +- (int) findAndReplaceText: (NSString*) searchText + byText: (NSString*) newText + matchCase: (BOOL) matchCase + wholeWord: (BOOL) wholeWord + doAll: (BOOL) doAll +{ + // The current position is where we start searching for single occurences. Otherwise we start at + // the beginning of the document. + int startPosition; + if (doAll) + startPosition = 0; // Start at the beginning of the text if we replace all occurrences. + else + // For a signle replacement we start at the current caret position. + startPosition = [self getGeneralProperty: SCI_GETCURRENTPOS]; + int endPosition = [self getGeneralProperty: SCI_GETTEXTLENGTH]; + + int searchFlags= 0; + if (matchCase) + searchFlags |= SCFIND_MATCHCASE; + if (wholeWord) + searchFlags |= SCFIND_WHOLEWORD; + [self setGeneralProperty: SCI_SETSEARCHFLAGS value: searchFlags]; + [self setGeneralProperty: SCI_SETTARGETSTART value: startPosition]; + [self setGeneralProperty: SCI_SETTARGETEND value: endPosition]; + + const char* textToSearch = [searchText UTF8String]; + int sourceLength = strlen(textToSearch); // Length in bytes. + const char* replacement = [newText UTF8String]; + int targetLength = strlen(replacement); // Length in bytes. + sptr_t result; + + int replaceCount = 0; + if (doAll) + { + while (true) + { + result = [ScintillaView directCall: self + message: SCI_SEARCHINTARGET + wParam: sourceLength + lParam: (sptr_t) textToSearch]; + if (result < 0) + break; + + replaceCount++; + result = [ScintillaView directCall: self + message: SCI_REPLACETARGET + wParam: targetLength + lParam: (sptr_t) replacement]; + + // The replacement changes the target range to the replaced text. Continue after that til the end. + // The text length might be changed by the replacement so make sure the target end is the actual + // text end. + [self setGeneralProperty: SCI_SETTARGETSTART value: [self getGeneralProperty: SCI_GETTARGETEND]]; + [self setGeneralProperty: SCI_SETTARGETEND value: [self getGeneralProperty: SCI_GETTEXTLENGTH]]; + } + } + else + { + result = [ScintillaView directCall: self + message: SCI_SEARCHINTARGET + wParam: sourceLength + lParam: (sptr_t) textToSearch]; + replaceCount = (result < 0) ? 0 : 1; + + if (replaceCount > 0) + { + result = [ScintillaView directCall: self + message: SCI_REPLACETARGET + wParam: targetLength + lParam: (sptr_t) replacement]; + + // For a single replace we set the new selection to the replaced text. + [self setGeneralProperty: SCI_SETSELECTIONSTART value: [self getGeneralProperty: SCI_GETTARGETSTART]]; + [self setGeneralProperty: SCI_SETSELECTIONEND value: [self getGeneralProperty: SCI_GETTARGETEND]]; + } + } + + return replaceCount; } //-------------------------------------------------------------------------------------------------- |