Browse files

Go to next/previous match

  • Loading branch information...
1 parent abfdd87 commit 32783f5a31a7cadc2d40f7df747ce8fd3dd13339 Alexander Stigsen committed Jan 1, 2010
Showing with 146 additions and 1 deletion.
  1. +116 −1 src/CommandHandler.cpp
  2. +2 −0 src/CommandHandler.h
  3. +26 −0 src/EditorCtrl.cpp
  4. +1 −0 src/EditorCtrl.h
  5. +1 −0 src/FindFlags.h
View
117 src/CommandHandler.cpp
@@ -214,6 +214,14 @@ bool CommandHandler::ProcessCommand(const wxKeyEvent& evt) {
case '%':
DoMovement(count, mem_fun_ref(&EditorCtrl::GotoMatchingBracket));
break;
+ case 'n':
+ NextMatch(count, true);
+ EndMovement();
+ break;
+ case 'N':
+ NextMatch(count, false);
+ EndMovement();
+ break;
// Selection
case ',':
@@ -396,7 +404,8 @@ void CommandHandler::DoSearch(size_t count, int keyCode, wxChar c) {
case '/':
// keep selection but move caret to end
if (m_editor.IsSelected()) {
- m_editor.SetPos(m_editor.GetSelections()[0].end);
+ m_lastSearchPos = m_editor.GetSelections()[0].end;
+ m_editor.SetPos(m_lastSearchPos);
}
Clear();
return;
@@ -416,11 +425,117 @@ void CommandHandler::DoSearch(size_t count, int keyCode, wxChar c) {
if (startpos == m_searchPos) return; // no matches
+ m_lastSearchPos = startpos;
m_editor.SetPos(startpos);
m_editor.Select(startpos, endpos);
m_editor.SetSearchHighlight(m_search, FIND_USE_REGEX);
}
+void CommandHandler::NextMatch(size_t count, bool forward) {
+ wxString pattern;
+ bool regex = true;
+ bool select = true;
+ bool usesel = false;
+ size_t pos = m_editor.GetPos();
+
+ // Get pattern and startpos
+ if (m_editor.IsSelected()) {
+ if (!m_search.empty() && m_lastSearchPos == pos) {
+ pattern = m_search;
+ }
+ else {
+ // search for selection content
+ pattern = m_editor.GetFirstSelection();
+ usesel = true;
+ regex = false;
+ }
+ pos = m_editor.GetSelections()[0].end;
+ }
+ else if (!m_search.empty()) {
+ pattern = m_search;
+ select = false;
+ }
+ else return; // nothing to search after
+
+ // Set options
+ int options = FIND_MATCHCASE;
+ if (regex) options |= FIND_USE_REGEX;
+ if (!forward) options |= FIND_REVERSE;
+
+ if (m_editor.HasSearchRange()) {
+ const vector<interval>& ranges = m_editor.GetSearchRange();
+ const vector<unsigned int>& cursors = m_editor.GetSearchRangeCursors();
+
+ // Copy old selections before removing them
+ const vector<interval> selections = m_editor.GetSelections();
+ m_editor.RemoveAllSelections();
+
+ // Go to next match in each range
+ for (size_t i = 0; i < ranges.size(); ++i) {
+ const interval& iv = ranges[i];
+ const size_t cpos = cursors[i];
+
+ // Get pattern from selection if no search pattern
+ if (usesel) {
+ bool haspattern = false;
+ for (vector<interval>::const_iterator p = selections.begin(); p != selections.end(); ++p) {
+ if (p->start == cpos || p->end == cpos) {
+ pattern = m_editor.GetText(p->start, p->end);
+ haspattern = true;
+ break;
+ }
+ }
+ if (!haspattern) continue;
+ }
+
+ // Do the search
+ size_t startpos = cpos;
+ size_t endpos = cpos;
+ const size_t limit = forward ? iv.end : iv.start;
+ for (size_t n = 0; n < count; ++n) {
+ const size_t searchpos = forward ? endpos : startpos;
+ const search_result sr = m_editor.SearchDirect(pattern, options, searchpos, limit);
+ if (sr.error_code < 0) return; // no matches
+ if (!select && n == 0 && sr.start == pos) ++count; // avoid reselect
+
+ startpos = sr.start;
+ endpos = sr.end;
+ }
+
+ // Show result
+ if (select) m_editor.AddSelection(startpos, endpos);
+ const size_t newcpos = select ? endpos : startpos;
+ if (cpos == pos) {
+ m_editor.SetPos(newcpos);
+ m_lastSearchPos = newcpos;
+ }
+ m_editor.SetSearchRangeCursor(i, newcpos);
+ }
+ }
+ else {
+ // Do the search
+ size_t startpos = pos;
+ size_t endpos = pos;
+ for (size_t i = 0; i < count; ++i) {
+ const size_t searchpos = forward ? endpos : startpos;
+ const search_result sr = m_editor.SearchDirect(pattern, options, searchpos);
+ if (sr.error_code < 0) return; // no matches
+ if (!select && i == 0 && sr.start == pos) ++count; // avoid reselect
+
+ startpos = sr.start;
+ endpos = sr.end;
+ }
+
+ // Show result
+ if (select) m_editor.Select(startpos, endpos);
+ const size_t newcpos = select ? endpos : startpos;
+ m_editor.SetPos(newcpos);
+ m_lastSearchPos = newcpos;
+ }
+
+ m_editor.SetSearchHighlight(pattern, regex ? FIND_USE_REGEX : 0);
+}
+
template<class Op> void CommandHandler::DoMovement(size_t count, const Op& f) {
const unsigned int pos = m_editor.GetPos();
View
2 src/CommandHandler.h
@@ -45,6 +45,7 @@ class CommandHandler {
void EndMovement();
void DoSearch(size_t count, int keyCode, wxChar c);
+ void NextMatch(size_t count, bool forward=true);
void SelectRangeStart();
void SelectRangeEnd();
@@ -81,6 +82,7 @@ class CommandHandler {
bool m_select;
wxString m_cmd;
size_t m_searchPos;
+ size_t m_lastSearchPos;
wxString m_search;
std::vector<unsigned int> m_cursors;
bool m_reverse;
View
26 src/EditorCtrl.cpp
@@ -5088,6 +5088,32 @@ void EditorCtrl::SetSearchRangeCursor(size_t cursor, unsigned int pos) {
m_cursors[cursor] = pos;
}
+search_result EditorCtrl::SearchDirect(const wxString& pattern, int options, size_t startpos, size_t endpos) const {
+ const bool regex = (options & FIND_USE_REGEX) != 0;
+ const bool matchcase = (options & FIND_MATCHCASE) != 0;;
+ const bool forward = (options & FIND_REVERSE) == 0;
+
+ // Direct interface to document search
+ cxLOCKDOC_READ(m_doc)
+ if (regex) {
+ if (forward) return doc.RegExFind(pattern, startpos, matchcase, NULL, endpos);
+ else {
+ search_result sr = doc.RegExFindBackwards(pattern, startpos, matchcase);
+ if (sr.start < endpos) sr.error_code = -1;
+ return sr;
+ }
+ }
+ else {
+ if (forward) return doc.Find(pattern, startpos, matchcase, endpos);
+ else {
+ search_result sr = doc.FindBackwards(pattern, startpos, matchcase);
+ if (sr.start < endpos) sr.error_code = -1;
+ return sr;
+ }
+ }
+ cxENDLOCK
+}
+
bool EditorCtrl::DoFind(const wxString& text, unsigned int start_pos, int options, bool dir_forward) {
wxASSERT(start_pos >= 0 && start_pos <= m_lines.GetLength());
bool matchcase = options & FIND_MATCHCASE;
View
1 src/EditorCtrl.h
@@ -267,6 +267,7 @@ class EditorCtrl : public KeyHookable<wxControl>,
virtual void ClearSearchHighlight();
// SnippetHandler and EditorFrame use 3 of the following methods; may need some more refactoring here to capture that
+ search_result SearchDirect(const wxString& pattern, int options, size_t startpos, size_t endpos=0) const;
wxString ParseReplaceString(const wxString& replacetext, const map<unsigned int,interval>& captures, const vector<char>* source=NULL) const;
search_result RegExFind(const pcre* re, const pcre_extra* study, unsigned int start_pos, map<unsigned int,interval> *captures, unsigned int end_pos, int search_options=0) const;
search_result RegExFind(const wxString& searchtext, unsigned int start_pos, bool matchcase, map<unsigned int,interval> *captures=NULL, unsigned int end_pos=0) const;
View
1 src/FindFlags.h
@@ -6,6 +6,7 @@ static const unsigned int FIND_MATCHCASE = 1;
static const unsigned int FIND_USE_REGEX = 2;
static const unsigned int FIND_RESTART = 4;
static const unsigned int FIND_HIGHLIGHT = 8;
+static const unsigned int FIND_REVERSE = 16;
enum cxFindResult {
cxFOUND,

0 comments on commit 32783f5

Please sign in to comment.