#include "ParIterator.h"
#include "TexRow.h"
#include "Text.h"
+#include "FuncRequest.h"
+#include "LyXFunc.h"
#include "mathed/InsetMath.h"
#include "mathed/InsetMathGrid.h"
}
-bool findChange(DocIterator & cur)
+bool findChange(DocIterator & cur, bool next)
{
- for (; cur; cur.forwardPos())
- if (cur.inTexted() && !cur.paragraph().isUnchanged(cur.pos()))
+ if (!next)
+ cur.backwardPos();
+ for (; cur; next ? cur.forwardPos() : cur.backwardPos())
+ if (cur.inTexted() && !cur.paragraph().isUnchanged(cur.pos())) {
+ if (!next)
+ // if we search backwards, take a step forward
+ // to correctly set the anchor
+ cur.forwardPos();
return true;
+ }
+
return false;
}
bool findNextChange(BufferView * bv)
{
+ return findChange(bv, true);
+}
+
+
+bool findPreviousChange(BufferView * bv)
+{
+ return findChange(bv, false);
+}
+
+
+bool findChange(BufferView * bv, bool next)
+{
+ if (bv->cursor().selection()) {
+ // set the cursor at the beginning or at the end of the selection
+ // before searching. Otherwise, the current change will be found.
+ if (next != bv->cursor().top() > bv->cursor().anchor())
+ bv->cursor().setCursorToAnchor();
+ }
+
DocIterator cur = bv->cursor();
+
+ // Are we within a change ? Then first search forward (backward),
+ // clear the selection and search the other way around (see the end
+ // of this function). This will avoid changes to be selected half.
+ bool search_both_sides = false;
+ if (cur.pos() > 1) {
+ Change change_next_pos
+ = cur.paragraph().lookupChange(cur.pos());
+ Change change_prev_pos
+ = cur.paragraph().lookupChange(cur.pos() - 1);
+ if (change_next_pos.isSimilarTo(change_prev_pos))
+ search_both_sides = true;
+ }
- if (!findChange(cur))
+ if (!findChange(cur, next))
return false;
bv->cursor().setCursor(cur);
bv->cursor().resetAnchor();
+ if (!next)
+ // take a step into the change
+ cur.backwardPos();
+
Change orig_change = cur.paragraph().lookupChange(cur.pos());
CursorSlice & tip = cur.top();
- for (; !tip.at_end(); tip.forwardPos()) {
- Change change = tip.paragraph().lookupChange(tip.pos());
- if (change != orig_change)
- break;
+ if (next) {
+ for (; !tip.at_end(); tip.forwardPos()) {
+ Change change = tip.paragraph().lookupChange(tip.pos());
+ if (change != orig_change)
+ break;
+ }
+ } else {
+ for (; !tip.at_begin();) {
+ tip.backwardPos();
+ Change change = tip.paragraph().lookupChange(tip.pos());
+ if (change != orig_change) {
+ // take a step forward to correctly set the selection
+ tip.forwardPos();
+ break;
+ }
+ }
}
// Now put cursor to end of selection:
bv->cursor().setCursor(cur);
bv->cursor().setSelection();
+ if (search_both_sides) {
+ bv->cursor().setSelection(false);
+ findChange(bv, !next);
+ }
+
return true;
}
**/
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.
/// buffer
lyx::Buffer const & buf;
/// options
- FindAdvOptions const & opt;
+ FindAndReplaceOptions const & opt;
private:
/** Normalize a stringified or latexified LyX paragraph.
};
-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);
} // anonym namespace
-docstring stringifyFromForSearch(FindAdvOptions const & opt,
+docstring stringifyFromForSearch(FindAndReplaceOptions const & opt,
DocIterator const & cur, int len)
{
if (!opt.ignoreformat)
}
-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;
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;
}
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 << ' '
<< 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;
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;
}