From: Tommaso Cucinotta Date: Wed, 30 Dec 2009 18:40:18 +0000 (+0000) Subject: Implemented the "Current Buffer" & "Current (Master) Document" scopes in the Advanced... X-Git-Tag: 2.0.0~4675 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=5da4ccb93173750fc7ba311ebd3710ea84aec343;p=features.git Implemented the "Current Buffer" & "Current (Master) Document" scopes in the Advanced Find and Replace feature. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@32678 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/Buffer.cpp b/src/Buffer.cpp index aa12dbed67..794c2e29d4 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -2331,9 +2331,8 @@ DocIterator Buffer::firstChildPosition(Buffer const * child) } -std::vector Buffer::getChildren(bool grand_children) const +void Buffer::getChildren(std::vector & clist, bool grand_children) const { - std::vector clist; // loop over children Impl::BufferPositionMap::iterator it = d->children_positions.begin(); Impl::BufferPositionMap::iterator end = d->children_positions.end(); @@ -2348,7 +2347,14 @@ std::vector Buffer::getChildren(bool grand_children) const clist.push_back(*git); } } - return clist; +} + + +std::vector Buffer::getChildren(bool grand_children) const +{ + std::vector v; + getChildren(v, grand_children); + return v; } diff --git a/src/Buffer.h b/src/Buffer.h index 926a20de6c..59ee444805 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -321,6 +321,9 @@ public: /// return a vector with all children (and grandchildren) std::vector getChildren(bool grand_children = true) const; + /// Add all children (and grandchildren) to supplied vector + void getChildren(std::vector & children, bool grand_children = true) const; + /// Is buffer read-only? bool isReadonly() const; diff --git a/src/frontends/LyXView.h b/src/frontends/LyXView.h index 6813d759bd..342e4dd820 100644 --- a/src/frontends/LyXView.h +++ b/src/frontends/LyXView.h @@ -57,6 +57,10 @@ public: virtual BufferView const * documentBufferView() const = 0; //@} + /// Find or create buffer view and WorkArea for supplied document + /// buffer, and make it current. + virtual void selectDocumentBuffer(Buffer const * p_buf) = 0; + /// display a message in the view virtual void message(docstring const &) = 0; diff --git a/src/frontends/qt4/FindAndReplace.cpp b/src/frontends/qt4/FindAndReplace.cpp index 817a1d5b59..ca5e23f27d 100644 --- a/src/frontends/qt4/FindAndReplace.cpp +++ b/src/frontends/qt4/FindAndReplace.cpp @@ -162,6 +162,13 @@ void FindAndReplaceWidget::findAndReplace( } else { replaceString = from_utf8(LYX_FR_NULL_STRING); } + FindAndReplaceOptions::SearchScope scope = FindAndReplaceOptions::S_BUFFER; + if (CurrentDocument->isChecked()) + scope = FindAndReplaceOptions::S_BUFFER; + else if (MasterDocument->isChecked()) + scope = FindAndReplaceOptions::S_DOCUMENT; + else + LASSERT(false, /**/); LYXERR(Debug::FIND, "FindAndReplaceOptions: " << "searchstring=" << searchString << ", casesensitiv=" << casesensitive @@ -171,9 +178,10 @@ void FindAndReplaceWidget::findAndReplace( << ", ignoreformat=" << ignoreformat << ", regexp=" << regexp << ", replaceString" << replaceString - << ", keep_case=" << keep_case); + << ", keep_case=" << keep_case + << ", scope=" << scope); FindAndReplaceOptions opt(searchString, casesensitive, matchword, ! backwards, - expandmacros, ignoreformat, regexp, replaceString, keep_case); + expandmacros, ignoreformat, regexp, replaceString, keep_case, scope); LYXERR(Debug::FIND, "Dispatching LFUN_WORD_FINDADV"); std::ostringstream oss; oss << opt; diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index f6d38e216f..0644c7c0bc 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -3542,6 +3542,11 @@ Dialog * GuiView::build(string const & name) } +void GuiView::selectDocumentBuffer(Buffer const * p_buf) { + setBuffer(const_cast(p_buf)); +} + + } // namespace frontend } // namespace lyx diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index 44d491e80c..19f6b57051 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -283,6 +283,10 @@ public: /// void disconnectDialog(std::string const & name); + /// Find or create buffer view and WorkArea for supplied document + /// buffer and make it current. + void selectDocumentBuffer(Buffer const * p_buf); + private: /// void saveLayout() const; diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index ed700f7da4..ba28ad4be0 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -47,6 +47,9 @@ #include "support/lstrings.h" #include "support/lassert.h" +#include "frontends/Application.h" +#include "frontends/LyXView.h" + #include #include @@ -601,7 +604,7 @@ bool braces_match(string::const_iterator const & beg, **/ class MatchStringAdv { public: - MatchStringAdv(lyx::Buffer const & buf, FindAndReplaceOptions const & opt); + MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt); /** Tests if text starting at the supplied position matches with the one provided to the MatchStringAdv ** constructor as opt.search, under the opt.* options settings. @@ -617,7 +620,9 @@ public: public: /// buffer - lyx::Buffer const & buf; + lyx::Buffer * p_buf; + /// first buffer on which search was started + lyx::Buffer * const p_first_buf; /// options FindAndReplaceOptions const & opt; @@ -650,8 +655,8 @@ private: }; -MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAndReplaceOptions const & opt) - : buf(buf), opt(opt) +MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt) + : p_buf(&buf), p_first_buf(&buf), opt(opt) { par_as_string = normalize(opt.search); open_braces = 0; @@ -889,6 +894,7 @@ docstring latexifyFromCursor(DocIterator const & cur, int len) return ods.str(); } + /** Finalize an advanced find operation, advancing the cursor to the innermost ** position that matches, plus computing the length of the matching text to ** be selected @@ -929,8 +935,78 @@ int findAdvFinalize(DocIterator & cur, MatchStringAdv const & match) } +/** Switch p_buf to point to next document buffer. + ** + ** Return true if restarted from master-document buffer. + ** + ** @note + ** Not using p_buf->allRelatives() here, because I'm not sure + ** whether or not the returned order is independent of p_buf. + **/ +bool next_document_buffer(Buffer * & p_buf) { + Buffer *p_master = p_buf; + Buffer *p_old; + do { + p_old = p_master; + p_master = const_cast(p_master->masterBuffer()); + LYXERR(Debug::FIND, "p_old=" << p_old << ", p_master=" << p_master); + } while (p_master != p_old); + LASSERT(p_master != NULL, /**/); + std::vector v_children; + /* Root master added as first buffer in the vector */ + v_children.push_back(p_master); + p_master->getChildren(v_children, true); + LYXERR(Debug::FIND, "v_children.size()=" << v_children.size()); + std::vector::const_iterator it = std::find(v_children.begin(), v_children.end(), p_buf); + LASSERT(it != v_children.end(), /**/) + ++it; + if (it == v_children.end()) { + p_buf = *v_children.begin(); + return true; + } + p_buf = *it; + return false; +} + + +/** Switch p_buf to point to previous document buffer. + ** + ** Return true if restarted from last child buffer. + ** + ** @note + ** Not using p_buf->allRelatives() here, because I'm not sure + ** whether or not the returned order is independent of p_buf. + **/ +bool prev_document_buffer(Buffer * & p_buf) { + Buffer *p_master = p_buf; + Buffer *p_old; + do { + p_old = p_master; + p_master = const_cast(p_master->masterBuffer()); + LYXERR(Debug::FIND, "p_old=" << p_old << ", p_master=" << p_master); + } while (p_master != p_old); + LASSERT(p_master != NULL, /**/); + std::vector v_children; + /* Root master added as first buffer in the vector */ + v_children.push_back(p_master); + p_master->getChildren(v_children, true); + LYXERR(Debug::FIND, "v_children.size()=" << v_children.size()); + std::vector::const_iterator it = std::find(v_children.begin(), v_children.end(), p_buf); + LASSERT(it != v_children.end(), /**/) + if (it == v_children.begin()) { + it = v_children.end(); + --it; + p_buf = *it; + return true; + } + --it; + p_buf = *it; + return false; +} + + /// Finds forward -int findForwardAdv(DocIterator & cur, MatchStringAdv const & match) +int findForwardAdv(DocIterator & cur, MatchStringAdv & match) { if (!cur) return 0; @@ -947,17 +1023,29 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv const & match) if (match(cur)) return findAdvFinalize(cur, match); } - if (wrap_answer != -1) - break; - wrap_answer = frontend::Alert::prompt( - _("Wrap search?"), - _("End of document reached while searching forward.\n" - "\n" - "Continue searching from beginning?"), - 0, 1, _("&Yes"), _("&No")); + // No match has been found in current buffer + bool prompt = false; + if (match.opt.scope == FindAndReplaceOptions::S_BUFFER) { + prompt = true; + } else if (match.opt.scope == FindAndReplaceOptions::S_DOCUMENT) { + prompt = next_document_buffer(match.p_buf); + } else { + /* Unimplemented scope */ + LASSERT(false, /**/); + } + if (prompt) { + if (wrap_answer != -1) + break; + wrap_answer = frontend::Alert::prompt( + _("Wrap search?"), + _("End of document/scope reached while searching forward.\n" + "\n" + "Continue searching from beginning?"), + 0, 1, _("&Yes"), _("&No")); + } cur.clear(); - cur.push_back(CursorSlice(match.buf.inset())); - } while (wrap_answer == 0); + cur.push_back(CursorSlice(match.p_buf->inset())); + } while (wrap_answer != 1); return 0; } @@ -986,7 +1074,7 @@ void findMostBackwards(DocIterator & cur, MatchStringAdv const & match, int & le } /// Finds backwards -int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match) { +int findBackwardsAdv(DocIterator & cur, MatchStringAdv & match) { if (! cur) return 0; // Backup of original position (for restoring it in case match not found) @@ -1047,13 +1135,25 @@ int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match) { cur.backwardPos(); }; } - wrap_answer = frontend::Alert::prompt( - _("Wrap search?"), - _("Beginning of document reached while searching backwards\n" - "\n" - "Continue searching from end?"), - 0, 1, _("&Yes"), _("&No")); - cur = doc_iterator_end(&match.buf); + // No match has been found in current buffer + bool prompt = false; + if (match.opt.scope == FindAndReplaceOptions::S_BUFFER) { + prompt = true; + } else if (match.opt.scope == FindAndReplaceOptions::S_DOCUMENT) { + prompt = prev_document_buffer(match.p_buf); + } else { + /* Unimplemented scope */ + LASSERT(false, /**/); + } + if (prompt) { + wrap_answer = frontend::Alert::prompt( + _("Wrap search?"), + _("Beginning of document/scope reached while searching backwards\n" + "\n" + "Continue searching from end?"), + 0, 1, _("&Yes"), _("&No")); + } + cur = doc_iterator_end(match.p_buf); cur.backwardPos(); LYXERR(Debug::FIND, "findBackAdv5: cur: " << cur); cur_orig2 = cur; @@ -1062,6 +1162,7 @@ int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match) { return 0; } + } // anonym namespace @@ -1077,10 +1178,11 @@ docstring stringifyFromForSearch(FindAndReplaceOptions const & opt, FindAndReplaceOptions::FindAndReplaceOptions(docstring const & search, bool casesensitive, bool matchword, bool forward, bool expandmacros, bool ignoreformat, - bool regexp, docstring const & replace, bool keep_case) + bool regexp, docstring const & replace, bool keep_case, + SearchScope scope) : search(search), casesensitive(casesensitive), matchword(matchword), forward(forward), expandmacros(expandmacros), ignoreformat(ignoreformat), - regexp(regexp), replace(replace), keep_case(keep_case) + regexp(regexp), replace(replace), keep_case(keep_case), scope(scope) { } @@ -1153,8 +1255,8 @@ bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt) // return false; // } + MatchStringAdv matchAdv(bv->buffer(), opt); try { - MatchStringAdv const matchAdv(bv->buffer(), opt); if (opt.forward) match_len = findForwardAdv(cur, matchAdv); else @@ -1170,7 +1272,12 @@ bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt) return false; } - LYXERR(Debug::FIND, "Putting selection at " << cur << " with len: " << match_len); + LYXERR(Debug::FIND, "Putting selection at buf=" << matchAdv.p_buf + << "cur=" << cur << " with len: " << match_len); + + theApp()->currentWindow()->selectDocumentBuffer(matchAdv.p_buf); + bv = theApp()->currentWindow()->documentBufferView(); + bv->putSelectionAt(cur, match_len, ! opt.forward); if (opt.replace == docstring(from_utf8(LYX_FR_NULL_STRING))) { bv->message(_("Match found !")); @@ -1248,7 +1355,8 @@ ostringstream & operator<<(ostringstream & os, lyx::FindAndReplaceOptions const << opt.ignoreformat << ' ' << opt.regexp << ' ' << to_utf8(opt.replace) << "\nEOSS\n" - << opt.keep_case; + << opt.keep_case << ' ' + << int(opt.scope); LYXERR(Debug::FIND, "built: " << os.str()); @@ -1284,6 +1392,9 @@ istringstream & operator>>(istringstream & is, lyx::FindAndReplaceOptions & opt) getline(is, line); } is >> opt.keep_case; + int i; + is >> i; + opt.scope = FindAndReplaceOptions::SearchScope(i); LYXERR(Debug::FIND, "parsed: " << opt.casesensitive << ' ' << opt.matchword << ' ' << opt.forward << ' ' << opt.expandmacros << ' ' << opt.ignoreformat << ' ' << opt.regexp << ' ' << opt.keep_case); LYXERR(Debug::FIND, "replacing with: '" << s << "'"); diff --git a/src/lyxfind.h b/src/lyxfind.h index f8a77494f0..3a3e91013e 100644 --- a/src/lyxfind.h +++ b/src/lyxfind.h @@ -78,6 +78,12 @@ bool findChange(BufferView * bv, bool next); class FindAndReplaceOptions { public: + typedef enum { + S_BUFFER, + S_DOCUMENT, + S_OPEN_BUFFERS, + S_ALL_MANUALS + } SearchScope; FindAndReplaceOptions( docstring const & search, bool casesensitive, @@ -87,7 +93,8 @@ public: bool ignoreformat, bool regexp, docstring const & replace, - bool keep_case + bool keep_case, + SearchScope scope = S_BUFFER ); FindAndReplaceOptions() { } docstring search; @@ -99,6 +106,7 @@ public: bool regexp; docstring replace; bool keep_case; + SearchScope scope; }; /// Write a FindAdvOptions instance to a stringstream