Hi, please, find attached a preliminary replace functionality (just try the "ReplaceNext button"), made while traveling, as usual :-). Like with find, there are some stability issues if you search (and replace) backwards, but hopefully I'll find the time to fix that as well.
Bye, T.
Index: src/frontends/qt4/FindAndReplace.cpp =================================================================== --- src/frontends/qt4/FindAndReplace.cpp (revisione 28060) +++ src/frontends/qt4/FindAndReplace.cpp (copia locale) @@ -80,30 +80,32 @@ return QWidget::eventFilter(obj, event); } +static docstring buffer_to_latex(Buffer & buffer) { + OutputParams runparams(&buffer.params().encoding()); + odocstringstream os; + runparams.nice = true; + runparams.flavor = OutputParams::LATEX; + runparams.linelen = 80; //lyxrc.plaintext_linelen; + // No side effect of file copying and image conversion + runparams.dryrun = true; + buffer.texrow().reset(); + ParagraphList::const_iterator pit = buffer.paragraphs().begin(); + ParagraphList::const_iterator const end = buffer.paragraphs().end(); + for (; pit != end; ++pit) { + TeXOnePar(buffer, buffer.text(), pit, os, buffer.texrow(), runparams); + LYXERR(Debug::DEBUG, "searchString up to here: " << os.str()); + } + return os.str(); +} -void FindAndReplaceWidget::findAdv(bool casesensitive, - bool matchword, bool backwards, - bool expandmacros, bool ignoreformat) +void FindAndReplaceWidget::findAndReplace( + bool casesensitive, bool matchword, bool backwards, + bool expandmacros, bool ignoreformat, bool replace) { Buffer & buffer = find_work_area_->bufferView().buffer(); docstring searchString; if (!ignoreformat) { - OutputParams runparams(&buffer.params().encoding()); - odocstringstream os; - runparams.nice = true; - runparams.flavor = OutputParams::LATEX; - runparams.linelen = 80; //lyxrc.plaintext_linelen; - // No side effect of file copying and image conversion - runparams.dryrun = true; - buffer.texrow().reset(); -// latexParagraphs(buffer, buffer.paragraphs(), os, buffer.texrow(), runparams); - ParagraphList::const_iterator pit = buffer.paragraphs().begin(); - ParagraphList::const_iterator const end = buffer.paragraphs().end(); - for (; pit != end; ++pit) { - TeXOnePar(buffer, buffer.text(), pit, os, buffer.texrow(), runparams); - LYXERR0("searchString up to here: " << os.str()); - } - searchString = os.str(); + searchString = buffer_to_latex(buffer); } else { ParIterator it = buffer.par_iterator_begin(); ParIterator end = buffer.par_iterator_end(); @@ -124,8 +126,15 @@ return; } bool const regexp = to_utf8(searchString).find("\\regexp") != std::string::npos; - FindAdvOptions opt(searchString, casesensitive, matchword, ! backwards, - expandmacros, ignoreformat, regexp); + docstring replaceString; + if (replace) { + Buffer & replace_buffer = replace_work_area_->bufferView().buffer(); + replaceString = buffer_to_latex(replace_buffer); + } else { + replaceString = from_utf8(LYX_FR_NULL_STRING); + } + FindAndReplaceOptions opt(searchString, casesensitive, matchword, ! backwards, + expandmacros, ignoreformat, regexp, replaceString); LYXERR(Debug::DEBUG, "Dispatching LFUN_WORD_FINDADV" << std::endl); std::ostringstream oss; oss << opt; @@ -137,16 +146,17 @@ } -void FindAndReplaceWidget::find(bool backwards) +void FindAndReplaceWidget::findAndReplace(bool backwards, bool replace) { // FIXME: create a Dialog::returnFocus() or something instead of this: view_.setCurrentWorkArea(view_.currentMainWorkArea()); // FIXME: This should be an LFUN. - findAdv(caseCB->isChecked(), - wordsCB->isChecked(), - backwards, - expandMacrosCB->isChecked(), - ignoreFormatCB->isChecked()); + findAndReplace(caseCB->isChecked(), + wordsCB->isChecked(), + backwards, + expandMacrosCB->isChecked(), + ignoreFormatCB->isChecked(), + replace); view_.currentMainWorkArea()->redraw(); find_work_area_->setFocus(); } @@ -176,20 +186,27 @@ void FindAndReplaceWidget::on_findNextPB_clicked() { - find(false); + findAndReplace(false, false); } void FindAndReplaceWidget::on_findPrevPB_clicked() { - find(true); + findAndReplace(true, false); } -void FindAndReplaceWidget::on_replacePB_clicked() +void FindAndReplaceWidget::on_replaceNextPB_clicked() { + findAndReplace(false, true); } +void FindAndReplaceWidget::on_replacePrevPB_clicked() +{ + findAndReplace(true, true); +} + + void FindAndReplaceWidget::on_replaceallPB_clicked() { } Index: src/frontends/qt4/FindAndReplace.h =================================================================== --- src/frontends/qt4/FindAndReplace.h (revisione 28060) +++ src/frontends/qt4/FindAndReplace.h (copia locale) @@ -44,16 +44,14 @@ // add a string to the combo if needed void remember(std::string const & find, QComboBox & combo); - void findAdv(bool casesensitive, - bool matchword, bool backwards, - bool expandmacros, bool ignoreformat); + void findAndReplace( + bool casesensitive, bool matchword, bool backwards, + bool expandmacros, bool ignoreformat, bool replace + ); void find(docstring const & str, int len, bool casesens, bool words, bool backwards, bool expandmacros); - void find(bool backwards); + void findAndReplace(bool backwards, bool replace); - void replace(docstring const & findstr, - docstring const & replacestr, - bool casesens, bool words, bool backwards, bool expandmacros, bool all); bool eventFilter(QObject *obj, QEvent *event); void virtual showEvent(QShowEvent *ev); @@ -62,7 +60,8 @@ protected Q_SLOTS: void on_findNextPB_clicked(); void on_findPrevPB_clicked(); - void on_replacePB_clicked(); + void on_replaceNextPB_clicked(); + void on_replacePrevPB_clicked(); void on_replaceallPB_clicked(); void on_closePB_clicked(); void on_regexpInsertCombo_currentIndexChanged(int index); Index: src/frontends/qt4/ui/FindAndReplaceUi.ui =================================================================== --- src/frontends/qt4/ui/FindAndReplaceUi.ui (revisione 28060) +++ src/frontends/qt4/ui/FindAndReplaceUi.ui (copia locale) @@ -66,7 +66,7 @@ <rect> <x>0</x> <y>0</y> - <width>227</width> + <width>221</width> <height>351</height> </rect> </property> @@ -90,8 +90,8 @@ <rect> <x>0</x> <y>0</y> - <width>221</width> - <height>85</height> + <width>215</width> + <height>89</height> </rect> </property> </widget> @@ -123,7 +123,7 @@ <item row="5" column="0" > <widget class="QPushButton" name="replaceNextPB" > <property name="enabled" > - <bool>false</bool> + <bool>true</bool> </property> <property name="text" > <string>Replace Ne&xt</string> @@ -163,8 +163,8 @@ <rect> <x>0</x> <y>0</y> - <width>221</width> - <height>85</height> + <width>215</width> + <height>89</height> </rect> </property> </widget> @@ -186,7 +186,7 @@ <item row="5" column="1" > <widget class="QPushButton" name="replacePrevPB" > <property name="enabled" > - <bool>false</bool> + <bool>true</bool> </property> <property name="text" > <string>Replace P&rev</string> Index: src/lyxfind.cpp =================================================================== --- src/lyxfind.cpp (revisione 28060) +++ src/lyxfind.cpp (copia locale) @@ -30,6 +30,8 @@ #include "ParIterator.h" #include "TexRow.h" #include "Text.h" +#include "FuncRequest.h" +#include "LyXFunc.h" #include "mathed/InsetMath.h" #include "mathed/InsetMathGrid.h" @@ -531,7 +533,7 @@ **/ class MatchStringAdv { public: - MatchStringAdv(lyx::Buffer const & buf, FindAdvOptions const & opt); + MatchStringAdv(lyx::Buffer const & 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. @@ -549,7 +551,7 @@ /// buffer lyx::Buffer const & buf; /// options - FindAdvOptions const & opt; + FindAndReplaceOptions const & opt; private: /** Normalize a stringified or latexified LyX paragraph. @@ -580,7 +582,7 @@ }; -MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAdvOptions const & opt) +MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAndReplaceOptions const & opt) : buf(buf), opt(opt) { par_as_string = normalize(opt.search); @@ -943,7 +945,7 @@ } // anonym namespace -docstring stringifyFromForSearch(FindAdvOptions const & opt, +docstring stringifyFromForSearch(FindAndReplaceOptions const & opt, DocIterator const & cur, int len) { if (!opt.ignoreformat) @@ -953,17 +955,17 @@ } -lyx::FindAdvOptions::FindAdvOptions(docstring const & search, bool casesensitive, +lyx::FindAndReplaceOptions::FindAndReplaceOptions(docstring const & search, bool casesensitive, bool matchword, bool forward, bool expandmacros, bool ignoreformat, - bool regexp) + bool regexp, docstring const & replace) : search(search), casesensitive(casesensitive), matchword(matchword), forward(forward), expandmacros(expandmacros), ignoreformat(ignoreformat), - regexp(regexp) + regexp(regexp), replace(replace) { } /// Perform a FindAdv operation. -bool findAdv(BufferView * bv, FindAdvOptions const & opt) +bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt) { DocIterator cur = bv->cursor(); int match_len = 0; @@ -997,7 +999,9 @@ LYXERR(Debug::DEBUG, "Putting selection at " << cur << " with len: " << match_len); bv->putSelectionAt(cur, match_len, ! opt.forward); bv->message(_("Match found!")); - //bv->update(); + if (opt.replace != docstring(from_utf8(LYX_FR_NULL_STRING))) { + dispatch(FuncRequest(LFUN_SELF_INSERT, opt.replace)); + } return true; } @@ -1008,14 +1012,14 @@ if (!bv || ev.action != LFUN_WORD_FINDADV) return; - FindAdvOptions opt; + FindAndReplaceOptions opt; istringstream iss(to_utf8(ev.argument())); iss >> opt; findAdv(bv, opt); } -ostringstream & operator<<(ostringstream & os, lyx::FindAdvOptions const & opt) +ostringstream & operator<<(ostringstream & os, lyx::FindAndReplaceOptions const & opt) { os << to_utf8(opt.search) << "\nEOSS\n" << opt.casesensitive << ' ' @@ -1023,14 +1027,15 @@ << opt.forward << ' ' << opt.expandmacros << ' ' << opt.ignoreformat << ' ' - << opt.regexp; + << opt.regexp << ' ' + << to_utf8(opt.replace) << "\nEOSS\n"; LYXERR(Debug::DEBUG, "built: " << os.str()); return os; } -istringstream & operator>>(istringstream & is, lyx::FindAdvOptions & opt) +istringstream & operator>>(istringstream & is, lyx::FindAndReplaceOptions & opt) { LYXERR(Debug::DEBUG, "parsing"); string s; @@ -1047,8 +1052,21 @@ LYXERR(Debug::DEBUG, "searching for: '" << s << "'"); opt.search = from_utf8(s); is >> opt.casesensitive >> opt.matchword >> opt.forward >> opt.expandmacros >> opt.ignoreformat >> opt.regexp; + is.get(); // Waste space before replace string + s = ""; + getline(is, line); + while (line != "EOSS") { + if (! s.empty()) + s = s + "\n"; + s = s + line; + if (is.eof()) // Tolerate malformed request + break; + getline(is, line); + } LYXERR(Debug::DEBUG, "parsed: " << opt.casesensitive << ' ' << opt.matchword << ' ' << opt.forward << ' ' << opt.expandmacros << ' ' << opt.ignoreformat << ' ' << opt.regexp); + LYXERR(Debug::DEBUG, "replacing with: '" << s << "'"); + opt.replace = from_utf8(s); return is; } Index: src/lyxfind.h =================================================================== --- src/lyxfind.h (revisione 28060) +++ src/lyxfind.h (copia locale) @@ -66,18 +66,22 @@ /// find the next change in the buffer bool findNextChange(BufferView * bv); -class FindAdvOptions { +// Hopefully, nobody will ever replace with something like this +#define LYX_FR_NULL_STRING "__LYX__F&R__NULL__STRING__" + +class FindAndReplaceOptions { public: - FindAdvOptions( + FindAndReplaceOptions( docstring const & search, bool casesensitive, bool matchword, bool forward, bool expandmacros, bool ignoreformat, - bool regexp + bool regexp, + docstring const & replace ); - FindAdvOptions() { } + FindAndReplaceOptions() { } docstring search; bool casesensitive; bool matchword; @@ -85,19 +89,20 @@ bool expandmacros; bool ignoreformat; bool regexp; + docstring replace; }; /// Write a FindAdvOptions instance to a stringstream -std::ostringstream & operator<<(std::ostringstream & os, lyx::FindAdvOptions const & opt); +std::ostringstream & operator<<(std::ostringstream & os, lyx::FindAndReplaceOptions const & opt); /// Read a FindAdvOptions instance from a stringstream -std::istringstream & operator>>(std::istringstream & is, lyx::FindAdvOptions & opt); +std::istringstream & operator>>(std::istringstream & is, lyx::FindAndReplaceOptions & opt); /// Dispatch a LFUN_WORD_FINDADV command request void findAdv(BufferView * bv, FuncRequest const & ev); /// Perform a FindAdv operation. -bool findAdv(BufferView * bv, FindAdvOptions const & opt); +bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt); /** Computes the simple-text or LaTeX export (depending on opt) of buf starting ** from cur and ending len positions after cur, if len is positive, or at the @@ -107,7 +112,7 @@ ** Ideally, this should not be needed, and the opt.search field should become a Text const &. **/ docstring stringifyFromForSearch( - FindAdvOptions const & opt, + FindAndReplaceOptions const & opt, DocIterator const & cur, int len = -1);