if (!cur.inTexted())
// bail in math
return make_pair(false, 0);
- // select current word and treat it as the search string
+ // select current word and treat it as the search string.
+ // This causes a minor bug as undo will restore this selection,
+ // which the user did not create (#8986).
cur.innerText()->selectWord(cur, WHOLE_WORD);
searchstr = cur.selectionAsString(false);
}
// of this function). This will avoid changes to be selected half.
bool search_both_sides = false;
Cursor tmpcur = cur;
- // Leave math first
+ // Find enclosing text cursor
while (tmpcur.inMathed())
tmpcur.pop_back();
Change change_next_pos
= tmpcur.paragraph().lookupChange(tmpcur.pos());
- if (change_next_pos.changed() && cur.inMathed()) {
- cur = tmpcur;
- search_both_sides = true;
- } else if (tmpcur.pos() > 0 && tmpcur.inTexted()) {
- Change change_prev_pos
- = tmpcur.paragraph().lookupChange(tmpcur.pos() - 1);
- if (change_next_pos.isSimilarTo(change_prev_pos))
+ if (change_next_pos.changed()) {
+ if (cur.inMathed()) {
+ cur = tmpcur;
search_both_sides = true;
+ } else if (tmpcur.pos() > 0 && tmpcur.inTexted()) {
+ Change change_prev_pos
+ = tmpcur.paragraph().lookupChange(tmpcur.pos() - 1);
+ if (change_next_pos.isSimilarTo(change_prev_pos))
+ search_both_sides = true;
+ }
}
+ // find the next change
if (!findChange(cur, next))
return false;
CursorSlice & tip = cur.top();
- if (!next)
+ if (!next && tip.pos() > 0)
// take a step into the change
tip.backwardPos();
int MatchStringAdv::findAux(DocIterator const & cur, int len, bool at_begin) const
{
+ if (at_begin &&
+ (opt.restr == FindAndReplaceOptions::R_ONLY_MATHS && !cur.inMathed()) )
+ return 0;
docstring docstr = stringifyFromForSearch(opt, cur, len);
LYXERR(Debug::FIND, "Matching against '" << lyx::to_utf8(docstr) << "'");
string str = normalize(docstr, true);
docstring const & find_buf_name, bool casesensitive,
bool matchword, bool forward, bool expandmacros, bool ignoreformat,
docstring const & repl_buf_name, bool keep_case,
- SearchScope scope)
+ SearchScope scope, SearchRestriction restr)
: find_buf_name(find_buf_name), casesensitive(casesensitive), matchword(matchword),
forward(forward), expandmacros(expandmacros), ignoreformat(ignoreformat),
- repl_buf_name(repl_buf_name), keep_case(keep_case), scope(scope)
+ repl_buf_name(repl_buf_name), keep_case(keep_case), scope(scope), restr(restr)
{
}
/** Check if 'len' letters following cursor are all non-lowercase */
-static bool allNonLowercase(DocIterator const & cur, int len)
+static bool allNonLowercase(Cursor const & cur, int len)
{
- pos_type end_pos = cur.pos() + len;
- for (pos_type pos = cur.pos(); pos != end_pos; ++pos)
+ pos_type beg_pos = cur.selectionBegin().pos();
+ pos_type end_pos = cur.selectionBegin().pos() + len;
+ if (len > cur.lastpos() + 1 - beg_pos) {
+ LYXERR(Debug::FIND, "This should not happen, more debug needed");
+ len = cur.lastpos() + 1 - beg_pos;
+ }
+ for (pos_type pos = beg_pos; pos != end_pos; ++pos)
if (isLowerCase(cur.paragraph().getChar(pos)))
return false;
return true;
/** Check if first letter is upper case and second one is lower case */
-static bool firstUppercase(DocIterator const & cur)
+static bool firstUppercase(Cursor const & cur)
{
char_type ch1, ch2;
- if (cur.pos() >= cur.lastpos() - 1) {
+ pos_type pos = cur.selectionBegin().pos();
+ if (pos >= cur.lastpos() - 1) {
LYXERR(Debug::FIND, "No upper-case at cur: " << cur);
return false;
}
- ch1 = cur.paragraph().getChar(cur.pos());
- ch2 = cur.paragraph().getChar(cur.pos()+1);
+ ch1 = cur.paragraph().getChar(pos);
+ ch2 = cur.paragraph().getChar(pos + 1);
bool result = isUpperCase(ch1) && isLowerCase(ch2);
LYXERR(Debug::FIND, "firstUppercase(): "
<< "ch1=" << ch1 << "(" << char(ch1) << "), ch2="
static void changeFirstCase(Buffer & buffer, TextCase first_case, TextCase others_case)
{
ParagraphList::iterator pit = buffer.paragraphs().begin();
+ LASSERT(pit->size() >= 1, /**/);
pos_type right = pos_type(1);
pit->changeCase(buffer.params(), pos_type(0), right, first_case);
- right = pit->size() + 1;
- pit->changeCase(buffer.params(), right, right, others_case);
+ right = pit->size();
+ pit->changeCase(buffer.params(), pos_type(1), right, others_case);
}
} // anon namespace
repl_buffer.setUnnamed(true);
LASSERT(repl_buffer.readString(lyx), return);
if (opt.keep_case && sel_len >= 2) {
+ LYXERR(Debug::FIND, "keep_case true: cur.pos()=" << cur.pos() << ", sel_len=" << sel_len);
if (cur.inTexted()) {
if (firstUppercase(cur))
changeFirstCase(repl_buffer, text_uppercase, text_lowercase);
<< opt.ignoreformat << ' '
<< to_utf8(opt.repl_buf_name) << "\nEOSS\n"
<< opt.keep_case << ' '
- << int(opt.scope);
+ << int(opt.scope) << ' '
+ << int(opt.restr);
LYXERR(Debug::FIND, "built: " << os.str());
int i;
is >> i;
opt.scope = FindAndReplaceOptions::SearchScope(i);
+ is >> i;
+ opt.restr = FindAndReplaceOptions::SearchRestriction(i);
+
LYXERR(Debug::FIND, "parsed: " << opt.casesensitive << ' ' << opt.matchword << ' ' << opt.forward << ' '
- << opt.expandmacros << ' ' << opt.ignoreformat << ' ' << opt.keep_case);
+ << opt.expandmacros << ' ' << opt.ignoreformat << ' ' << opt.keep_case << ' '
+ << opt.scope << ' ' << opt.restr);
return is;
}