void setIgnoreFormat(string type, bool value)
{
- ignoreFormats.setIgnoreFormat(type, value);
+ ignoreFormats.setIgnoreFormat(type, value);
}
#define MAXOPENED 30
class Intervall {
bool isPatternString;
- public:
- explicit Intervall(bool isPattern) :
- isPatternString(isPattern),
- ignoreidx(-1),
- actualdeptindex(0) { depts[0] = 0; closes[0] = 0;};
+public:
+ explicit Intervall(bool isPattern, string const & p) :
+ isPatternString(isPattern), par(p), ignoreidx(-1), actualdeptindex(0),
+ hasTitle(false)
+ {
+ depts[0] = 0;
+ closes[0] = 0;
+ }
+
string par;
int ignoreidx;
+ static vector<Border> borders;
int depts[MAXOPENED];
int closes[MAXOPENED];
int actualdeptindex;
- Border borders[2*MAXOPENED];
int previousNotIgnored(int);
int nextNotIgnored(int);
void handleOpenP(int i);
// string show(int lastpos);
};
+vector<Border> Intervall::borders = vector<Border>(30);
+
int Intervall::isOpeningPar(int pos)
{
if ((pos < 0) || (size_t(pos) >= par.size()))
static void checkDepthIndex(int val)
{
static int maxdepthidx = MAXOPENED-2;
+ static int lastmaxdepth = 0;
+ if (val > lastmaxdepth) {
+ LYXERR0("Depth reached " << val);
+ lastmaxdepth = val;
+ }
if (val > maxdepthidx) {
maxdepthidx = val;
LYXERR0("maxdepthidx now " << val);
}
}
+#if 0
+// Not needed, because borders are now dynamically expanded
static void checkIgnoreIdx(int val)
{
- static int maxignoreidx = 2*MAXOPENED - 4;
- if (val > maxignoreidx) {
- maxignoreidx = val;
- LYXERR0("maxignoreidx now " << val);
+ static int lastmaxignore = -1;
+ if ((lastmaxignore < val) && (size_t(val+1) >= borders.size())) {
+ LYXERR0("IgnoreIdx reached " << val);
+ lastmaxignore = val;
}
}
+#endif
/*
* Expand the region of ignored parts of the input latex string
}
Border br(low, upper);
if (idx > ignoreidx) {
- borders[idx] = br;
+ if (borders.size() <= size_t(idx)) {
+ borders.push_back(br);
+ }
+ else {
+ borders[idx] = br;
+ }
ignoreidx = idx;
- checkIgnoreIdx(ignoreidx);
+ // checkIgnoreIdx(ignoreidx);
return;
}
else {
// We know here that br.low > borders[idx-1].upper
if (br.upper < borders[idx].low) {
// We have to insert at this pos
- for (int i = ignoreidx+1; i > idx; --i) {
+ if (size_t(ignoreidx+1) >= borders.size()) {
+ borders.push_back(borders[ignoreidx]);
+ }
+ else {
+ borders[ignoreidx+1] = borders[ignoreidx];
+ }
+ for (int i = ignoreidx; i > idx; --i) {
borders[i] = borders[i-1];
}
borders[idx] = br;
ignoreidx += 1;
- checkIgnoreIdx(ignoreidx);
+ // checkIgnoreIdx(ignoreidx);
return;
}
// Here we know, that we are overlapping
// get the corresponding utf8-value
if ((values[start] & 0xc0) != 0xc0) {
// should not happen, utf8 encoding starts at least with 11xxxxxx
- // but value for '\dot{i}' is 'i', which is ascii
- if ((values[start] & 0x80) == 0) {
- // is ascii
- accents[key] = values.substr(start, 1);
- }
- start++;
- continue;
+ // but value for '\dot{i}' is 'i', which is ascii
+ if ((values[start] & 0x80) == 0) {
+ // is ascii
+ accents[key] = values.substr(start, 1);
+ // LYXERR0("" << key << "=" << accents[key]);
+ }
+ start++;
+ continue;
}
for (int j = 1; ;j++) {
if (start + j >= values.size()) {
// This is the first byte of following utf8 char
accents[key] = values.substr(start, j);
start += j;
+ // LYXERR0("" << key << "=" << accents[key]);
break;
}
}
buildaccent("ddot", "aAeEiIioOuUyY",
"äÄëËïÏïöÖüÜÿŸ"); // umlaut
buildaccent("dot|.", "cCeEGgIizZaAoObBdDfFyY",
- "ċĊėĖĠġİİżŻȧȦȯȮḃḂḋḊḟḞẏẎ"); // dot{i} can only happen if ignoring case, but there is no lowercase of 'İ'
+ "ċĊėĖĠġİİżŻȧȦȯȮḃḂḋḊḟḞẏẎ"); // dot{i} can only happen if ignoring case, but there is no lowercase of 'İ'
accents["acute{\\imath}"] = "í";
buildaccent("acute", "aAcCeElLoOnNrRsSuUyYzZiI",
"áÁćĆéÉĺĹóÓńŃŕŔśŚúÚýÝźŹíÍ");
buildaccent("dacute|H|h", "oOuU", "őŐűŰ"); // double acute
buildaccent("mathring|r", "aAuUwy",
- "åÅůŮẘẙ"); // ring
+ "åÅůŮẘẙ"); // ring
accents["check{\\imath}"] = "ǐ";
accents["check{\\jmath}"] = "ǰ";
buildaccent("check|v", "cCdDaAeEiIoOuUgGkKhHlLnNrRsSTtzZ",
"ãÃñÑõÕĩĨũŨ"); // tilde
accents["breve{\\imath}"] = "ĭ";
buildaccent("breve|u", "aAeEgGiIoOuU",
- "ăĂĕĔğĞĭĬŏŎŭŬ"); // breve
+ "ăĂĕĔğĞĭĬŏŎŭŬ"); // breve
accents["grave{\\imath}"] = "ì";
buildaccent("grave|`", "aAeEiIoOuUnNwWyY",
- "àÀèÈìÌòÒùÙǹǸẁẀỳỲ"); // grave
+ "àÀèÈìÌòÒùÙǹǸẁẀỳỲ"); // grave
buildaccent("subdot|d", "BbDdHhKkLlMmNnRrSsTtVvWwZzAaEeIiOoUuYy",
- "ḄḅḌḍḤḥḲḳḶḷṂṃṆṇṚṛṢṣṬṭṾṿẈẉẒẓẠạẸẹỊịỌọỤụỴỵ"); // dot below
+ "ḄḅḌḍḤḥḲḳḶḷṂṃṆṇṚṛṢṣṬṭṾṿẈẉẒẓẠạẸẹỊịỌọỤụỴỵ"); // dot below
+ buildaccent("ogonek|k", "AaEeIiUuOo",
+ "ĄąĘęĮįŲųǪǫ"); // ogonek
+ buildaccent("cedilla|c", "CcGgKkLlNnRrSsTtEeDdHh",
+ "ÇçĢĢĶķĻļŅņŖŗŞşŢţȨȩḐḑḨḩ"); // cedilla
+ buildaccent("subring|textsubring", "Aa",
+ "Ḁḁ"); // subring
+ buildaccent("subhat|textsubcircum", "DdEeLlNnTtUu",
+ "ḒḓḘḙḼḽṊṋṰṱṶṷ"); // subcircum
+ buildaccent("subtilde|textsubtilde", "EeIiUu",
+ "ḚḛḬḭṴṵ"); // subtilde
+ accents["dgrave{\\imath}"] = "ȉ";
+ accents["textdoublegrave{\\i}"] = "ȉ";
+ buildaccent("dgrave|textdoublegrave", "AaEeIiOoRrUu",
+ "ȀȁȄȅȈȉȌȍȐȑȔȕ"); // double grave
+ accents["rcap{\\imath}"] = "ȉ";
+ accents["textroundcap{\\i}"] = "ȉ";
+ buildaccent("rcap|textroundcap", "AaEeIiOoRrUu",
+ "ȂȃȆȇȊȋȎȏȒȓȖȗ"); // inverted breve
}
/*
{
if (accents.empty())
buildAccentsMap();
- static regex const accre("\\\\((.|grave|breve|lyxmathsym|text|ddot|dot|acute|dacute|mathring|check|hat|bar|tilde|subdot)\\{[^\\{\\}]+\\}|(i|imath|jmath)(?![a-zA-Z]))");
+ static regex const accre("\\\\(([\\S]|grave|breve|lyxmathsym|text|ddot|dot|acute|dacute|mathring|check|hat|bar|tilde|subdot|ogonek|cedilla|subring|textsubring|subhat|textsubcircum|subtilde|textsubtilde|dgrave|textdoublegrave|rcap|textroundcap)\\{[^\\{\\}]+\\}|(i|imath|jmath)(?![a-zA-Z]))");
smatch sub;
for (sregex_iterator itacc(par.begin(), par.end(), accre), end; itacc != end; ++itacc) {
sub = *itacc;
string key = sub.str(1);
if (accents.find(key) != accents.end()) {
string val = accents[key];
- size_t pos = sub.position(0);
+ size_t pos = sub.position(size_t(0));
for (size_t i = 0; i < val.size(); i++) {
par[pos+i] = val[i];
}
void removeHead(KeyInfo&, int count=0);
public:
- LatexInfo(string par, bool isPatternString) : entidx(-1), interval(isPatternString) {
- interval.par = par;
- interval.hasTitle = false;
- interval.titleValue = "";
+ LatexInfo(string par, bool isPatternString) : entidx(-1), interval(isPatternString, par)
+ {
buildKeys(isPatternString);
entries = vector<KeyInfo>();
buildEntries(isPatternString);
return open_braces;
}
+static int num_replaced = 0;
+static bool previous_single_replace = true;
MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt)
: p_buf(&buf), p_first_buf(&buf), opt(opt)
Buffer & find_buf = *theBufferList().getBuffer(FileName(to_utf8(opt.find_buf_name)), true);
docstring const & ds = stringifySearchBuffer(find_buf, opt);
use_regexp = lyx::to_utf8(ds).find("\\regexp{") != std::string::npos;
+ if (opt.replace_all && previous_single_replace) {
+ previous_single_replace = false;
+ num_replaced = 0;
+ }
+ else if (!opt.replace_all) {
+ num_replaced = 0; // count number of replaced strings
+ previous_single_replace = true;
+ }
// When using regexp, braces are hacked already by escape_for_regex()
par_as_string = normalize(ds, !use_regexp);
open_braces = 0;
// Exclude from the returned match length any length
// due to close wildcards added at end of regexp
- // and also the length of the leading (e.g. '\emph{')
+ // and also the length of the leading (e.g. '\emph{}')
//
// Whole found string, including the leading: m[0].second - m[0].first
// Size of the leading string: m[1].second - m[1].first
return mres;
}
} else {
- size_t pos = str.find(par_as_string_nolead);
+ // Start the search _after_ the leading part
+ size_t pos = str.find(par_as_string_nolead, lead_as_string.size());
if (pos != string::npos) {
mres.match_len = par_as_string.size();
mres.match2end = str.size() - pos;
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, SearchRestriction restr)
+ SearchScope scope, SearchRestriction restr, bool replace_all)
: 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), restr(restr)
+ repl_buf_name(repl_buf_name), keep_case(keep_case), scope(scope), restr(restr), replace_all(replace_all)
{
}
} // namespace
///
-static void findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, MatchStringAdv & matchAdv)
+static int findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, MatchStringAdv & matchAdv)
{
Cursor & cur = bv->cursor();
if (opt.repl_buf_name == docstring()
|| theBufferList().getBuffer(FileName(to_utf8(opt.repl_buf_name)), true) == 0
|| theBufferList().getBuffer(FileName(to_utf8(opt.find_buf_name)), true) == 0)
- return;
+ return 0;
DocIterator sel_beg = cur.selectionBegin();
DocIterator sel_end = cur.selectionEnd();
if (&sel_beg.inset() != &sel_end.inset()
|| sel_beg.pit() != sel_end.pit()
|| sel_beg.idx() != sel_end.idx())
- return;
+ return 0;
int sel_len = sel_end.pos() - sel_beg.pos();
LYXERR(Debug::FIND, "sel_beg: " << sel_beg << ", sel_end: " << sel_end
<< ", sel_len: " << sel_len << endl);
if (sel_len == 0)
- return;
- LASSERT(sel_len > 0, return);
+ return 0;
+ LASSERT(sel_len > 0, return 0);
if (!matchAdv(sel_beg, sel_len).match_len)
- return;
+ return 0;
// Build a copy of the replace buffer, adapted to the KeepCase option
Buffer & repl_buffer_orig = *theBufferList().getBuffer(FileName(to_utf8(opt.repl_buf_name)), true);
string lyx = oss.str();
Buffer repl_buffer("", false);
repl_buffer.setUnnamed(true);
- LASSERT(repl_buffer.readString(lyx), return);
+ LASSERT(repl_buffer.readString(lyx), return 0);
if (opt.keep_case && sel_len >= 2) {
LYXERR(Debug::FIND, "keep_case true: cur.pos()=" << cur.pos() << ", sel_len=" << sel_len);
if (cur.inTexted()) {
LYXERR(Debug::FIND, "After pos adj cur=" << cur << " with depth: " << cur.depth() << " and len: " << sel_len);
bv->putSelectionAt(DocIterator(cur), sel_len, !opt.forward);
bv->processUpdateFlags(Update::Force);
+ return 1;
}
int length = bv->cursor().selectionEnd().pos() - bv->cursor().selectionBegin().pos();
if (length > 0)
bv->putSelectionAt(bv->cursor().selectionBegin(), length, !opt.forward);
- findAdvReplace(bv, opt, matchAdv);
+ num_replaced += findAdvReplace(bv, opt, matchAdv);
cur = bv->cursor();
if (opt.forward)
match_len = findForwardAdv(cur, matchAdv);
}
if (match_len == 0) {
- bv->message(_("Match not found!"));
+ if (num_replaced > 0) {
+ switch (num_replaced)
+ {
+ case 1:
+ bv->message(_("One match has been replaced."));
+ break;
+ case 2:
+ bv->message(_("Two matches have been replaced."));
+ break;
+ default:
+ bv->message(bformat(_("%1$d matches have been replaced."), num_replaced));
+ break;
+ }
+ num_replaced = 0;
+ }
+ else {
+ bv->message(_("Match not found."));
+ }
return false;
}
- bv->message(_("Match found!"));
+ if (num_replaced > 0)
+ bv->message(_("Match has been replaced."));
+ else
+ bv->message(_("Match found."));
LYXERR(Debug::FIND, "Putting selection at cur=" << cur << " with len: " << match_len);
bv->putSelectionAt(cur, match_len, !opt.forward);
<< opt.forward << ' '
<< opt.expandmacros << ' '
<< opt.ignoreformat << ' '
+ << opt.replace_all << ' '
<< to_utf8(opt.repl_buf_name) << "\nEOSS\n"
<< opt.keep_case << ' '
<< int(opt.scope) << ' '
}
LYXERR(Debug::FIND, "file_buf_name: '" << s << "'");
opt.find_buf_name = from_utf8(s);
- is >> opt.casesensitive >> opt.matchword >> opt.forward >> opt.expandmacros >> opt.ignoreformat;
+ is >> opt.casesensitive >> opt.matchword >> opt.forward >> opt.expandmacros >> opt.ignoreformat >> opt.replace_all;
is.get(); // Waste space before replace string
s = "";
getline(is, line);