X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxfind.cpp;h=45cbbd96f6c12df151b919a8129a663871e5aa39;hb=762ba6a3c811584673090bab6268c4738e4377f5;hp=9fbc13f25a77b7b83d24d587c025842eb1421bc4;hpb=9d6b71c6b3db62f0d1fe6338379c2bf226bedfa5;p=lyx.git diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index 9fbc13f25a..45cbbd96f6 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -32,6 +32,7 @@ #include "ParIterator.h" #include "TexRow.h" #include "Text.h" +#include "Encoding.h" #include "frontends/Application.h" #include "frontends/alert.h" @@ -161,7 +162,7 @@ IgnoreFormats ignoreFormats; void setIgnoreFormat(string type, bool value) { - ignoreFormats.setIgnoreFormat(type, value); + ignoreFormats.setIgnoreFormat(type, value); } @@ -910,11 +911,12 @@ private: static docstring buffer_to_latex(Buffer & buffer) { - OutputParams runparams(&buffer.params().encoding()); + //OutputParams runparams(&buffer.params().encoding()); + OutputParams runparams(encodings.fromLyXName("utf8")); odocstringstream ods; otexstream os(ods); runparams.nice = true; - runparams.flavor = OutputParams::LATEX; + runparams.flavor = OutputParams::XETEX; runparams.linelen = 10000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; @@ -934,9 +936,10 @@ static docstring stringifySearchBuffer(Buffer & buffer, FindAndReplaceOptions co if (!opt.ignoreformat) { str = buffer_to_latex(buffer); } else { - OutputParams runparams(&buffer.params().encoding()); + // OutputParams runparams(&buffer.params().encoding()); + OutputParams runparams(encodings.fromLyXName("utf8")); runparams.nice = true; - runparams.flavor = OutputParams::LATEX; + runparams.flavor = OutputParams::XETEX; runparams.linelen = 10000; //lyxrc.plaintext_linelen; runparams.dryrun = true; runparams.for_search = true; @@ -1020,7 +1023,7 @@ static Features identifyFeatures(string const & s) } } } - return(info); + return info; } /* @@ -1108,18 +1111,22 @@ class Border { #define MAXOPENED 30 class Intervall { - bool isPatternString; - public: - explicit Intervall(bool isPattern) : - isPatternString(isPattern), - ignoreidx(-1), - actualdeptindex(0) { depts[0] = 0; closes[0] = 0;}; + bool isPatternString_; +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 borders; int depts[MAXOPENED]; int closes[MAXOPENED]; int actualdeptindex; - Border borders[2*MAXOPENED]; int previousNotIgnored(int); int nextNotIgnored(int); void handleOpenP(int i); @@ -1127,6 +1134,7 @@ class Intervall { void resetOpenedP(int openPos); void addIntervall(int upper); void addIntervall(int low, int upper); /* if explicit */ + void removeAccents(); void setForDefaultLang(KeyInfo &defLang); int findclosing(int start, int end, char up, char down, int repeat); void handleParentheses(int lastpos, bool closingAllowed); @@ -1137,6 +1145,8 @@ class Intervall { // string show(int lastpos); }; +vector Intervall::borders = vector(30); + int Intervall::isOpeningPar(int pos) { if ((pos < 0) || (size_t(pos) >= par.size())) @@ -1169,20 +1179,28 @@ void Intervall::setForDefaultLang(KeyInfo &defLang) 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 @@ -1199,9 +1217,14 @@ void Intervall::addIntervall(int low, int upper) } 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 { @@ -1209,12 +1232,18 @@ void Intervall::addIntervall(int low, int upper) // 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 @@ -1244,6 +1273,141 @@ void Intervall::addIntervall(int low, int upper) } } +typedef map AccentsMap; +static AccentsMap accents = map(); + +static void buildaccent(string n, string param, string values) +{ + stringstream s(n); + string name; + const char delim = '|'; + while (getline(s, name, delim)) { + size_t start = 0; + for (size_t i = 0; i < param.size(); i++) { + string key = name + "{" + param[i] + "}"; + // 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); + // LYXERR0("" << key << "=" << accents[key]); + } + start++; + continue; + } + for (int j = 1; ;j++) { + if (start + j >= values.size()) { + accents[key] = values.substr(start, j); + start = values.size() - 1; + break; + } + else if ((values[start+j] & 0xc0) != 0x80) { + // This is the first byte of following utf8 char + accents[key] = values.substr(start, j); + start += j; + // LYXERR0("" << key << "=" << accents[key]); + break; + } + } + } + } +} + +static void buildAccentsMap() +{ + accents["imath"] = "ı"; + accents["i"] = "ı"; + accents["jmath"] = "ȷ"; + accents["lyxmathsym{ß}"] = "ß"; + accents["text{ß}"] = "ß"; + accents["ddot{\\imath}"] = "ï"; + buildaccent("ddot", "aAeEhHiIioOtuUwWxXyY", + "äÄëËḧḦïÏïöÖẗüÜẅẄẍẌÿŸ"); // umlaut + buildaccent("dot|.", "aAbBcCdDeEfFGghHIimMnNoOpPrRsStTwWxXyYzZ", + "ȧȦḃḂċĊḋḊėĖḟḞĠġḣḢİİṁṀṅṄȯȮṗṖṙṘṡṠṫṪẇẆẋẊẏẎżŻ"); // dot{i} can only happen if ignoring case, but there is no lowercase of 'İ' + accents["acute{\\imath}"] = "í"; + buildaccent("acute", "aAcCeEgGkKlLmMoOnNpPrRsSuUwWyYzZiI", + "áÁćĆéÉǵǴḱḰĺĹḿḾóÓńŃṕṔŕŔśŚúÚẃẂýÝźŹíÍ"); + buildaccent("dacute|H|h", "oOuU", "őŐűŰ"); // double acute + buildaccent("mathring|r", "aAuUwy", + "åÅůŮẘẙ"); // ring + accents["check{\\imath}"] = "ǐ"; + accents["check{\\jmath}"] = "ǰ"; + buildaccent("check|v", "cCdDaAeEiIoOuUgGkKhHlLnNrRsSTtzZ", + "čČďĎǎǍěĚǐǏǒǑǔǓǧǦǩǨȟȞľĽňŇřŘšŠŤťžŽ"); // caron + accents["hat{\\imath}"] = "î"; + accents["hat{\\jmath}"] = "ĵ"; + buildaccent("hat|^", "aAcCeEgGhHiIjJoOsSuUwWyYzZ", + "âÂĉĈêÊĝĜĥĤîÎĵĴôÔŝŜûÛŵŴŷŶẑẐ"); // circ + accents["bar{\\imath}"] = "ī"; + buildaccent("bar|=", "aAeEiIoOuUyY", + "āĀēĒīĪōŌūŪȳȲ"); // macron + accents["tilde{\\imath}"] = "ĩ"; + buildaccent("tilde", "aAeEiInNoOuUvVyY", + "ãÃẽẼĩĨñÑõÕũŨṽṼỹỸ"); // tilde + accents["breve{\\imath}"] = "ĭ"; + buildaccent("breve|u", "aAeEgGiIoOuU", + "ăĂĕĔğĞĭĬŏŎŭŬ"); // breve + accents["grave{\\imath}"] = "ì"; + buildaccent("grave|`", "aAeEiIoOuUnNwWyY", + "àÀèÈìÌòÒùÙǹǸẁẀỳỲ"); // grave + buildaccent("subdot|d", "BbDdHhKkLlMmNnRrSsTtVvWwZzAaEeIiOoUuYy", + "ḄḅḌḍḤḥḲḳḶḷṂṃṆṇṚṛṢṣṬṭṾṿẈẉẒẓẠạẸẹỊịỌọỤụỴỵ"); // 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 + buildaccent("slashed", "oO", + "øØ"); // slashed +} + +/* + * Created accents in math or regexp environment + * are macros, but we need the utf8 equivalent + */ +void Intervall::removeAccents() +{ + if (accents.empty()) + buildAccentsMap(); + 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|slashed)\\{[^\\{\\}]+\\}|(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(size_t(0)); + for (size_t i = 0; i < val.size(); i++) { + par[pos+i] = val[i]; + } + addIntervall(pos+val.size(), pos + sub.str(0).size()); + for (size_t i = pos+val.size(); i < pos + sub.str(0).size(); i++) { + // remove traces of any remaining chars + par[i] = ' '; + } + } + else { + LYXERR0("Not added accent for \"" << key << "\""); + } + } +} + void Intervall::handleOpenP(int i) { actualdeptindex++; @@ -1304,9 +1468,9 @@ static KeysMap keys = map(); class LatexInfo { private: - int entidx; - Entries entries; - Intervall interval; + int entidx_; + Entries entries_; + Intervall interval_; void buildKeys(bool); void buildEntries(bool); void makeKey(const string &, KeyInfo, bool isPatternString); @@ -1314,48 +1478,46 @@ class LatexInfo { 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(); + entries_ = vector(); buildEntries(isPatternString); }; int getFirstKey() { - entidx = 0; - if (entries.empty()) { - return (-1); + entidx_ = 0; + if (entries_.empty()) { + return -1; } - if (entries[0].keytype == KeyInfo::isTitle) { - if (! entries[0].disabled) { - interval.hasTitle = true; - interval.titleValue = entries[0].head; + if (entries_[0].keytype == KeyInfo::isTitle) { + if (! entries_[0].disabled) { + interval_.hasTitle = true; + interval_.titleValue = entries_[0].head; } else { - interval.hasTitle = false; - interval.titleValue = ""; + interval_.hasTitle = false; + interval_.titleValue = ""; } - removeHead(entries[0]); - if (entries.size() > 1) - return (1); + removeHead(entries_[0]); + if (entries_.size() > 1) + return 1; else - return (-1); + return -1; } return 0; }; int getNextKey() { - entidx++; - if (int(entries.size()) > entidx) { - return entidx; + entidx_++; + if (int(entries_.size()) > entidx_) { + return entidx_; } else { - return (-1); + return -1; } }; bool setNextKey(int idx) { - if ((idx == entidx) && (entidx >= 0)) { - entidx--; + if ((idx == entidx_) && (entidx_ >= 0)) { + entidx_--; return true; } else @@ -1363,28 +1525,28 @@ class LatexInfo { }; int find(int start, KeyInfo::KeyType keytype) { if (start < 0) - return (-1); + return -1; int tmpIdx = start; - while (tmpIdx < int(entries.size())) { - if (entries[tmpIdx].keytype == keytype) + while (tmpIdx < int(entries_.size())) { + if (entries_[tmpIdx].keytype == keytype) return tmpIdx; tmpIdx++; } - return(-1); + return -1; }; int process(ostringstream &os, KeyInfo &actual); int dispatch(ostringstream &os, int previousStart, KeyInfo &actual); // string show(int lastpos) { return interval.show(lastpos);}; - int nextNotIgnored(int start) { return interval.nextNotIgnored(start);}; + int nextNotIgnored(int start) { return interval_.nextNotIgnored(start);}; KeyInfo &getKeyInfo(int keyinfo) { static KeyInfo invalidInfo = KeyInfo(); - if ((keyinfo < 0) || ( keyinfo >= int(entries.size()))) + if ((keyinfo < 0) || ( keyinfo >= int(entries_.size()))) return invalidInfo; else - return entries[keyinfo]; + return entries_[keyinfo]; }; - void setForDefaultLang(KeyInfo &defLang) {interval.setForDefaultLang(defLang);}; - void addIntervall(int low, int up) { interval.addIntervall(low, up); }; + void setForDefaultLang(KeyInfo &defLang) {interval_.setForDefaultLang(defLang);}; + void addIntervall(int low, int up) { interval_.addIntervall(low, up); }; }; @@ -1420,11 +1582,11 @@ class MathInfo { size_t mathStart; size_t mathSize; }; - size_t actualIdx; - vector entries; + size_t actualIdx_; + vector entries_; public: MathInfo() { - actualIdx = 0; + actualIdx_ = 0; } void insert(string wait, size_t start, size_t end) { MathEntry m = MathEntry(); @@ -1432,32 +1594,32 @@ class MathInfo { m.mathStart = start; m.mathEnd = end; m.mathSize = end - start; - entries.push_back(m); + entries_.push_back(m); } - bool empty() { return entries.empty(); }; + bool empty() { return entries_.empty(); }; size_t getEndPos() { - if (entries.empty() || (actualIdx >= entries.size())) { + if (entries_.empty() || (actualIdx_ >= entries_.size())) { return 0; } - return entries[actualIdx].mathEnd; + return entries_[actualIdx_].mathEnd; } size_t getStartPos() { - if (entries.empty() || (actualIdx >= entries.size())) { + if (entries_.empty() || (actualIdx_ >= entries_.size())) { return 100000; /* definitely enough? */ } - return entries[actualIdx].mathStart; + return entries_[actualIdx_].mathStart; } size_t getFirstPos() { - actualIdx = 0; + actualIdx_ = 0; return getStartPos(); } size_t getSize() { - if (entries.empty() || (actualIdx >= entries.size())) { + if (entries_.empty() || (actualIdx_ >= entries_.size())) { return size_t(0); } - return entries[actualIdx].mathSize; + return entries_[actualIdx_].mathSize; } - void incrEntry() { actualIdx++; }; + void incrEntry() { actualIdx_++; }; }; void LatexInfo::buildEntries(bool isPatternString) @@ -1479,13 +1641,15 @@ void LatexInfo::buildEntries(bool isPatternString) size_t math_pos = 10000; string math_end; - for (sregex_iterator itmath(interval.par.begin(), interval.par.end(), rmath), end; itmath != end; ++itmath) { + interval_.removeAccents(); + + for (sregex_iterator itmath(interval_.par.begin(), interval_.par.end(), rmath), end; itmath != end; ++itmath) { submath = *itmath; if (math_end_waiting) { size_t pos = submath.position(size_t(0)); if ((math_end == "$") && (submath.str(0) == "$") && - (interval.par[pos-1] != '\\')) { + (interval_.par[pos-1] != '\\')) { mi.insert("$", math_pos, pos + 1); math_end_waiting = false; } @@ -1515,7 +1679,7 @@ void LatexInfo::buildEntries(bool isPatternString) } else if (submath.str(0) == "$") { size_t pos = submath.position(size_t(0)); - if ((pos == 0) || (interval.par[pos-1] != '\\')) { + if ((pos == 0) || (interval_.par[pos-1] != '\\')) { math_end_waiting = true; math_end = "$"; math_pos = pos; @@ -1539,7 +1703,7 @@ void LatexInfo::buildEntries(bool isPatternString) } } math_pos = mi.getFirstPos(); - for (sregex_iterator it(interval.par.begin(), interval.par.end(), rkeys), end; it != end; ++it) { + for (sregex_iterator it(interval_.par.begin(), interval_.par.end(), rkeys), end; it != end; ++it) { sub = *it; string key = sub.str(3); if (key == "") { @@ -1549,7 +1713,7 @@ void LatexInfo::buildEntries(bool isPatternString) key = sub.str(0); if (key == "$") { size_t k_pos = sub.position(size_t(0)); - if ((k_pos > 0) && (interval.par[k_pos - 1] == '\\')) { + if ((k_pos > 0) && (interval_.par[k_pos - 1] == '\\')) { // Escaped '$', ignoring continue; } @@ -1564,10 +1728,11 @@ void LatexInfo::buildEntries(bool isPatternString) found._dataStart = found._dataEnd; found._tokensize = found._dataEnd - found._tokenstart; found.parenthesiscount = 0; - found.head = interval.par.substr(found._tokenstart, found._tokensize); + found.head = interval_.par.substr(found._tokenstart, found._tokensize); } - else + else { continue; + } } else { if (evaluatingMath) { @@ -1606,7 +1771,7 @@ void LatexInfo::buildEntries(bool isPatternString) found._dataEnd = found._tokenstart + found._tokensize; found._dataStart = found._dataEnd; found.parenthesiscount = 0; - found.head = interval.par.substr(found._tokenstart, found._tokensize); + found.head = interval_.par.substr(found._tokenstart, found._tokensize); evaluatingMath = true; } else { @@ -1633,7 +1798,7 @@ void LatexInfo::buildEntries(bool isPatternString) int pos = sub.position(size_t(0)); int count; for (count = 0; pos - count > 0; count++) { - char c = interval.par[pos-count-1]; + char c = interval_.par[pos-count-1]; if (discardComment) { if ((c != ' ') && (c != '%')) break; @@ -1645,25 +1810,25 @@ void LatexInfo::buildEntries(bool isPatternString) if (sub.str(1).compare(0, 5, "begin") == 0) { size_t pos1 = pos + sub.str(0).length(); if (sub.str(5).compare("cjk") == 0) { - pos1 = interval.findclosing(pos1+1, interval.par.length()) + 1; - if ((interval.par[pos1] == '{') && (interval.par[pos1+1] == '}')) + pos1 = interval_.findclosing(pos1+1, interval_.par.length()) + 1; + if ((interval_.par[pos1] == '{') && (interval_.par[pos1+1] == '}')) pos1 += 2; found.keytype = KeyInfo::isMain; found._dataStart = pos1; - found._dataEnd = interval.par.length(); + found._dataEnd = interval_.par.length(); found.disabled = keys["foreignlanguage"].disabled; found.used = keys["foreignlanguage"].used; found._tokensize = pos1 - found._tokenstart; - found.head = interval.par.substr(found._tokenstart, found._tokensize); + found.head = interval_.par.substr(found._tokenstart, found._tokensize); } else { // Swallow possible optional params - while (interval.par[pos1] == '[') { - pos1 = interval.findclosing(pos1+1, interval.par.length(), '[', ']')+1; + while (interval_.par[pos1] == '[') { + pos1 = interval_.findclosing(pos1+1, interval_.par.length(), '[', ']')+1; } // Swallow also the eventual parameter - if (interval.par[pos1] == '{') { - found._dataEnd = interval.findclosing(pos1+1, interval.par.length()) + 1; + if (interval_.par[pos1] == '{') { + found._dataEnd = interval_.findclosing(pos1+1, interval_.par.length()) + 1; } else { found._dataEnd = pos1; @@ -1671,7 +1836,7 @@ void LatexInfo::buildEntries(bool isPatternString) found._dataStart = found._dataEnd; found._tokensize = count + found._dataEnd - pos; found.parenthesiscount = 0; - found.head = interval.par.substr(found._tokenstart, found._tokensize); + found.head = interval_.par.substr(found._tokenstart, found._tokensize); found.disabled = true; } } @@ -1681,7 +1846,7 @@ void LatexInfo::buildEntries(bool isPatternString) found._dataEnd = found._dataStart; found._tokensize = count + found._dataEnd - pos; found.parenthesiscount = 0; - found.head = interval.par.substr(found._tokenstart, found._tokensize); + found.head = interval_.par.substr(found._tokenstart, found._tokensize); found.disabled = true; } } @@ -1691,7 +1856,7 @@ void LatexInfo::buildEntries(bool isPatternString) if (found.parenthesiscount == 0) { // Probably to be discarded size_t following_pos = sub.position(size_t(0)) + sub.str(3).length() + 1; - char following = interval.par[following_pos]; + char following = interval_.par[following_pos]; if (following == ' ') found.head = "\\" + sub.str(3) + " "; else if (following == '=') { @@ -1715,12 +1880,12 @@ void LatexInfo::buildEntries(bool isPatternString) } } int optend = params; - while (interval.par[optend] == '[') { + while (interval_.par[optend] == '[') { // discard optional parameters - optend = interval.findclosing(optend+1, interval.par.length(), '[', ']') + 1; + optend = interval_.findclosing(optend+1, interval_.par.length(), '[', ']') + 1; } if (optend > params) { - key += interval.par.substr(params, optend-params); + key += interval_.par.substr(params, optend-params); evaluatingOptional = true; optionalEnd = optend; } @@ -1740,10 +1905,10 @@ void LatexInfo::buildEntries(bool isPatternString) } found._tokensize = found.head.length(); found._dataStart = found._tokenstart + found.head.length(); - if (interval.par.substr(found._dataStart-1, 15).compare("\\endarguments{}") == 0) { + if (interval_.par.substr(found._dataStart-1, 15).compare("\\endarguments{}") == 0) { found._dataStart += 15; } - size_t endpos = interval.findclosing(found._dataStart, interval.par.length(), '{', '}', closings); + size_t endpos = interval_.findclosing(found._dataStart, interval_.par.length(), '{', '}', closings); if (found.keytype == KeyInfo::isList) { // Check if it really is list env static regex const listre("^([a-z]+)$"); @@ -1765,18 +1930,18 @@ void LatexInfo::buildEntries(bool isPatternString) // Disable this key, treate it as standard found.keytype = KeyInfo::isStandard; found.disabled = true; - if ((codeEnd == interval.par.length()) && + if ((codeEnd == interval_.par.length()) && (found._tokenstart == codeStart)) { // trickery, because the code inset starts // with \selectlanguage ... codeEnd = endpos; - if (entries.size() > 1) { - entries[entries.size()-1]._dataEnd = codeEnd; + if (entries_.size() > 1) { + entries_[entries_.size()-1]._dataEnd = codeEnd; } } } } - if ((endpos == interval.par.length()) && + if ((endpos == interval_.par.length()) && (found.keytype == KeyInfo::doRemove)) { // Missing closing => error in latex-input? // therefore do not delete remaining data @@ -1790,7 +1955,7 @@ void LatexInfo::buildEntries(bool isPatternString) keys[key].used = true; } } - entries.push_back(found); + entries_.push_back(found); } } @@ -1967,7 +2132,7 @@ string Intervall::show(int lastpos) if (lastpos > i) { s += par.substr(i, lastpos-i); } - return (s); + return s; } #endif @@ -2013,7 +2178,7 @@ void Intervall::output(ostringstream &os, int lastpos) } if (hasTitle && (printed > 0)) os << "}"; - if (! isPatternString) + if (! isPatternString_) os << "\n"; handleParentheses(lastpos, true); /* extra closings '}' allowed here */ } @@ -2021,16 +2186,16 @@ void Intervall::output(ostringstream &os, int lastpos) void LatexInfo::processRegion(int start, int region_end) { while (start < region_end) { /* Let {[} and {]} survive */ - int cnt = interval.isOpeningPar(start); + int cnt = interval_.isOpeningPar(start); if (cnt == 1) { // Closing is allowed past the region - int closing = interval.findclosing(start+1, interval.par.length()); - interval.addIntervall(start, start+1); - interval.addIntervall(closing, closing+1); + int closing = interval_.findclosing(start+1, interval_.par.length()); + interval_.addIntervall(start, start+1); + interval_.addIntervall(closing, closing+1); } else if (cnt == 3) start += 2; - start = interval.nextNotIgnored(start+1); + start = interval_.nextNotIgnored(start+1); } } @@ -2038,12 +2203,12 @@ void LatexInfo::removeHead(KeyInfo &actual, int count) { if (actual.parenthesiscount == 0) { // "{\tiny{} ...}" ==> "{{} ...}" - interval.addIntervall(actual._tokenstart-count, actual._tokenstart + actual._tokensize); + interval_.addIntervall(actual._tokenstart-count, actual._tokenstart + actual._tokensize); } else { // Remove header hull, that is "\url{abcd}" ==> "abcd" - interval.addIntervall(actual._tokenstart - count, actual._dataStart); - interval.addIntervall(actual._dataEnd, actual._dataEnd+1); + interval_.addIntervall(actual._tokenstart - count, actual._dataStart); + interval_.addIntervall(actual._dataEnd, actual._dataEnd+1); } } @@ -2064,23 +2229,23 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) int tmpIdx = find(nextKeyIdx, KeyInfo::endArguments); if (tmpIdx > 0) { for (int i = nextKeyIdx; i <= tmpIdx; i++) { - entries[i].disabled = true; + entries_[i].disabled = true; } - actual._dataEnd = entries[tmpIdx]._dataEnd; + actual._dataEnd = entries_[tmpIdx]._dataEnd; } - while (interval.par[actual._dataEnd] == ' ') + while (interval_.par[actual._dataEnd] == ' ') actual._dataEnd++; - interval.addIntervall(0, actual._dataEnd+1); - interval.actualdeptindex = 0; - interval.depts[0] = actual._dataEnd+1; - interval.closes[0] = -1; + interval_.addIntervall(0, actual._dataEnd+1); + interval_.actualdeptindex = 0; + interval_.depts[0] = actual._dataEnd+1; + interval_.closes[0] = -1; break; } case KeyInfo::noContent: { /* char like "\hspace{2cm}" */ if (actual.disabled) - interval.addIntervall(actual._tokenstart, actual._dataEnd); + interval_.addIntervall(actual._tokenstart, actual._dataEnd); else - interval.addIntervall(actual._dataStart, actual._dataEnd); + interval_.addIntervall(actual._dataStart, actual._dataEnd); } // fall through case KeyInfo::isChar: { @@ -2088,29 +2253,29 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) break; } case KeyInfo::isSize: { - if (actual.disabled || (interval.par[actual._dataStart] != '{') || (interval.par[actual._dataStart-1] == ' ')) { + if (actual.disabled || (interval_.par[actual._dataStart] != '{') || (interval_.par[actual._dataStart-1] == ' ')) { processRegion(actual._dataEnd, actual._dataEnd+1); /* remove possibly following {} */ - interval.addIntervall(actual._tokenstart, actual._dataEnd+1); + interval_.addIntervall(actual._tokenstart, actual._dataEnd+1); nextKeyIdx = getNextKey(); } else { // Here _dataStart points to '{', so correct it actual._dataStart += 1; actual._tokensize += 1; actual.parenthesiscount = 1; - if (interval.par[actual._dataStart] == '}') { + if (interval_.par[actual._dataStart] == '}') { // Determine the end if used like '{\tiny{}...}' - actual._dataEnd = interval.findclosing(actual._dataStart+1, interval.par.length()) + 1; - interval.addIntervall(actual._dataStart, actual._dataStart+1); + actual._dataEnd = interval_.findclosing(actual._dataStart+1, interval_.par.length()) + 1; + interval_.addIntervall(actual._dataStart, actual._dataStart+1); } else { // Determine the end if used like '\tiny{...}' - actual._dataEnd = interval.findclosing(actual._dataStart, interval.par.length()) + 1; + actual._dataEnd = interval_.findclosing(actual._dataStart, interval_.par.length()) + 1; } // Split on this key if not at start - int start = interval.nextNotIgnored(previousStart); + int start = interval_.nextNotIgnored(previousStart); if (start < actual._tokenstart) { - interval.output(os, actual._tokenstart); - interval.addIntervall(start, actual._tokenstart); + interval_.output(os, actual._tokenstart); + interval_.addIntervall(start, actual._tokenstart); } // discard entry if at end of actual nextKeyIdx = process(os, actual); @@ -2121,7 +2286,7 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) // Remove trailing '{}' too actual._dataStart += 1; actual._dataEnd += 1; - interval.addIntervall(actual._tokenstart, actual._dataEnd+1); + interval_.addIntervall(actual._tokenstart, actual._dataEnd+1); nextKeyIdx = getNextKey(); break; case KeyInfo::noMain: @@ -2133,10 +2298,10 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) nextKeyIdx = getNextKey(); } else { // Split on this key if not at datastart of calling entry - int start = interval.nextNotIgnored(previousStart); + int start = interval_.nextNotIgnored(previousStart); if (start < actual._tokenstart) { - interval.output(os, actual._tokenstart); - interval.addIntervall(start, actual._tokenstart); + interval_.output(os, actual._tokenstart); + interval_.addIntervall(start, actual._tokenstart); } // discard entry if at end of actual nextKeyIdx = process(os, actual); @@ -2149,21 +2314,21 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) int tmpIdx = find(nextKeyIdx, KeyInfo::endArguments); if (tmpIdx > 0) { for (int i = nextKeyIdx; i <= tmpIdx; i++) { - entries[i].disabled = true; + entries_[i].disabled = true; } - actual._dataEnd = entries[tmpIdx]._dataEnd; + actual._dataEnd = entries_[tmpIdx]._dataEnd; } - interval.addIntervall(actual._tokenstart, actual._dataEnd+1); + interval_.addIntervall(actual._tokenstart, actual._dataEnd+1); break; } case KeyInfo::doRemove: { // Remove the key with all parameters and following spaces size_t pos; - for (pos = actual._dataEnd+1; pos < interval.par.length(); pos++) { - if ((interval.par[pos] != ' ') && (interval.par[pos] != '%')) + for (pos = actual._dataEnd+1; pos < interval_.par.length(); pos++) { + if ((interval_.par[pos] != ' ') && (interval_.par[pos] != '%')) break; } - interval.addIntervall(actual._tokenstart, pos); + interval_.addIntervall(actual._tokenstart, pos); nextKeyIdx = getNextKey(); break; } @@ -2171,7 +2336,7 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) // Discard space before _tokenstart int count; for (count = 0; count < actual._tokenstart; count++) { - if (interval.par[actual._tokenstart-count-1] != ' ') + if (interval_.par[actual._tokenstart-count-1] != ' ') break; } nextKeyIdx = getNextKey(); @@ -2181,44 +2346,44 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) // with arguments // How else can we catch this one? for (int i = nextKeyIdx; i <= tmpIdx; i++) { - entries[i].disabled = true; + entries_[i].disabled = true; } - actual._dataEnd = entries[tmpIdx]._dataEnd; + actual._dataEnd = entries_[tmpIdx]._dataEnd; } else if (nextKeyIdx > 0) { // Ignore any lang entries inside data region - for (int i = nextKeyIdx; i < int(entries.size()) && entries[i]._tokenstart < actual._dataEnd; i++) { - if (entries[i].keytype == KeyInfo::isMain) - entries[i].disabled = true; + for (int i = nextKeyIdx; i < int(entries_.size()) && entries_[i]._tokenstart < actual._dataEnd; i++) { + if (entries_[i].keytype == KeyInfo::isMain) + entries_[i].disabled = true; } } if (actual.disabled) { - interval.addIntervall(actual._tokenstart-count, actual._dataEnd+1); + interval_.addIntervall(actual._tokenstart-count, actual._dataEnd+1); } else { - interval.addIntervall(actual._tokenstart-count, actual._tokenstart); + interval_.addIntervall(actual._tokenstart-count, actual._tokenstart); } - if (interval.par[actual._dataEnd+1] == '[') { - int posdown = interval.findclosing(actual._dataEnd+2, interval.par.length(), '[', ']'); - if ((interval.par[actual._dataEnd+2] == '{') && - (interval.par[posdown-1] == '}')) { - interval.addIntervall(actual._dataEnd+1,actual._dataEnd+3); - interval.addIntervall(posdown-1, posdown+1); + if (interval_.par[actual._dataEnd+1] == '[') { + int posdown = interval_.findclosing(actual._dataEnd+2, interval_.par.length(), '[', ']'); + if ((interval_.par[actual._dataEnd+2] == '{') && + (interval_.par[posdown-1] == '}')) { + interval_.addIntervall(actual._dataEnd+1,actual._dataEnd+3); + interval_.addIntervall(posdown-1, posdown+1); } else { - interval.addIntervall(actual._dataEnd+1, actual._dataEnd+2); - interval.addIntervall(posdown, posdown+1); + interval_.addIntervall(actual._dataEnd+1, actual._dataEnd+2); + interval_.addIntervall(posdown, posdown+1); } - int blk = interval.nextNotIgnored(actual._dataEnd+1); + int blk = interval_.nextNotIgnored(actual._dataEnd+1); if (blk > posdown) { // Discard at most 1 space after empty item int count; for (count = 0; count < 1; count++) { - if (interval.par[blk+count] != ' ') + if (interval_.par[blk+count] != ' ') break; } if (count > 0) - interval.addIntervall(blk, blk+count); + interval_.addIntervall(blk, blk+count); } } break; @@ -2228,8 +2393,8 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) int count; int val = actual._tokenstart; for (count = 0; count < actual._tokenstart;) { - val = interval.previousNotIgnored(val-1); - if (interval.par[val] != ' ') + val = interval_.previousNotIgnored(val-1); + if (interval_.par[val] != ' ') break; else { count = actual._tokenstart - val; @@ -2239,7 +2404,7 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) removeHead(actual, count); nextKeyIdx = getNextKey(); } else { - interval.addIntervall(actual._tokenstart-count, actual._tokenstart); + interval_.addIntervall(actual._tokenstart-count, actual._tokenstart); nextKeyIdx = process(os, actual); } break; @@ -2261,19 +2426,19 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) break; } case KeyInfo::isMain: { - if (interval.par.substr(actual._dataStart, 2) == "% ") - interval.addIntervall(actual._dataStart, actual._dataStart+2); + if (interval_.par.substr(actual._dataStart, 2) == "% ") + interval_.addIntervall(actual._dataStart, actual._dataStart+2); if (actual._tokenstart > 0) { - int prev = interval.previousNotIgnored(actual._tokenstart - 1); - if ((prev >= 0) && interval.par[prev] == '%') - interval.addIntervall(prev, prev+1); + int prev = interval_.previousNotIgnored(actual._tokenstart - 1); + if ((prev >= 0) && interval_.par[prev] == '%') + interval_.addIntervall(prev, prev+1); } if (actual.disabled) { removeHead(actual); - if ((interval.par.substr(actual._dataStart, 3) == " \\[") || - (interval.par.substr(actual._dataStart, 8) == " \\begin{")) { + if ((interval_.par.substr(actual._dataStart, 3) == " \\[") || + (interval_.par.substr(actual._dataStart, 8) == " \\begin{")) { // Discard also the space before math-equation - interval.addIntervall(actual._dataStart, actual._dataStart+1); + interval_.addIntervall(actual._dataStart, actual._dataStart+1); } nextKeyIdx = getNextKey(); // interval.resetOpenedP(actual._dataStart-1); @@ -2281,9 +2446,9 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) else { if (actual._tokenstart < 26) { // for the first (and maybe dummy) language - interval.setForDefaultLang(actual); + interval_.setForDefaultLang(actual); } - interval.resetOpenedP(actual._dataStart-1); + interval_.resetOpenedP(actual._dataStart-1); } break; } @@ -2301,13 +2466,13 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual) int LatexInfo::process(ostringstream &os, KeyInfo &actual ) { - int end = interval.nextNotIgnored(actual._dataEnd); + int end = interval_.nextNotIgnored(actual._dataEnd); int oldStart = actual._dataStart; int nextKeyIdx = getNextKey(); while (true) { if ((nextKeyIdx < 0) || - (entries[nextKeyIdx]._tokenstart >= actual._dataEnd) || - (entries[nextKeyIdx].keytype == KeyInfo::invalid)) { + (entries_[nextKeyIdx]._tokenstart >= actual._dataEnd) || + (entries_[nextKeyIdx].keytype == KeyInfo::invalid)) { if (oldStart <= end) { processRegion(oldStart, end); oldStart = end+1; @@ -2331,7 +2496,7 @@ int LatexInfo::process(ostringstream &os, KeyInfo &actual ) if (oldStart <= end) { processRegion(oldStart, end); } - if (interval.par[end] == '}') { + if (interval_.par[end] == '}') { end += 1; // This is the normal case. // But if using the firstlanguage, the closing may be missing @@ -2339,23 +2504,23 @@ int LatexInfo::process(ostringstream &os, KeyInfo &actual ) // get minimum of 'end' and 'actual._dataEnd' in case that the nextKey.keytype was 'KeyInfo::isMain' int output_end; if (actual._dataEnd < end) - output_end = interval.nextNotIgnored(actual._dataEnd); + output_end = interval_.nextNotIgnored(actual._dataEnd); else - output_end = interval.nextNotIgnored(end); + output_end = interval_.nextNotIgnored(end); if ((actual.keytype == KeyInfo::isMain) && actual.disabled) { - interval.addIntervall(actual._tokenstart, actual._tokenstart+actual._tokensize); + interval_.addIntervall(actual._tokenstart, actual._tokenstart+actual._tokensize); } // Remove possible empty data - int dstart = interval.nextNotIgnored(actual._dataStart); - while (interval.isOpeningPar(dstart) == 1) { - interval.addIntervall(dstart, dstart+1); - int dend = interval.findclosing(dstart+1, output_end); - interval.addIntervall(dend, dend+1); - dstart = interval.nextNotIgnored(dstart+1); + int dstart = interval_.nextNotIgnored(actual._dataStart); + while (interval_.isOpeningPar(dstart) == 1) { + interval_.addIntervall(dstart, dstart+1); + int dend = interval_.findclosing(dstart+1, output_end); + interval_.addIntervall(dend, dend+1); + dstart = interval_.nextNotIgnored(dstart+1); } if (dstart < output_end) - interval.output(os, output_end); - interval.addIntervall(actual._tokenstart, end); + interval_.output(os, output_end); + interval_.addIntervall(actual._tokenstart, end); return nextKeyIdx; } @@ -2468,14 +2633,14 @@ static string correctlanguagesetting(string par, bool isPatternString, bool with missed = 0; if (withformat) { regex_f = identifyFeatures(result); - string features = ""; + string features = ""; for (auto it = regex_f.cbegin(); it != regex_f.cend(); ++it) { string a = it->first; regex_with_format = true; - features += " " + a; + features += " " + a; // LYXERR0("Identified regex format:" << a); } - LYXERR(Debug::FIND, "Identified Features" << features); + LYXERR(Debug::FIND, "Identified Features" << features); } } else if (regex_with_format) { @@ -2486,14 +2651,14 @@ static string correctlanguagesetting(string par, bool isPatternString, bool with if (b && ! info[a]) { missed++; LYXERR(Debug::FIND, "Missed(" << missed << " " << a <<", srclen = " << parlen ); - return(""); + return ""; } } } else { // LYXERR0("No regex formats"); } - return(result); + return result; } @@ -2518,6 +2683,8 @@ static int identifyClosing(string & t) 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) @@ -2525,6 +2692,14 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & 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; @@ -2741,7 +2916,7 @@ MatchResult MatchStringAdv::findAux(DocIterator const & cur, int len, bool at_be // 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 @@ -2793,7 +2968,8 @@ MatchResult MatchStringAdv::findAux(DocIterator const & cur, int len, bool at_be 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; @@ -2915,9 +3091,10 @@ docstring stringifyFromCursor(DocIterator const & cur, int len) // TODO Try adding a AS_STR_INSERTS as last arg pos_type end = ( len == -1 || cur.pos() + len > int(par.size()) ) ? int(par.size()) : cur.pos() + len; - OutputParams runparams(&cur.buffer()->params().encoding()); + // OutputParams runparams(&cur.buffer()->params().encoding()); + OutputParams runparams(encodings.fromLyXName("utf8")); runparams.nice = true; - runparams.flavor = OutputParams::LATEX; + runparams.flavor = OutputParams::XETEX; runparams.linelen = 10000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; @@ -2960,9 +3137,10 @@ docstring latexifyFromCursor(DocIterator const & cur, int len) odocstringstream ods; otexstream os(ods); - OutputParams runparams(&buf.params().encoding()); + //OutputParams runparams(&buf.params().encoding()); + OutputParams runparams(encodings.fromLyXName("utf8")); runparams.nice = false; - runparams.flavor = OutputParams::LATEX; + runparams.flavor = OutputParams::XETEX; runparams.linelen = 8000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; @@ -3146,7 +3324,9 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match) DocIterator old_cur = cur; for (int i = 0; i < increment && cur; cur.forwardPos(), i++) { } - if (! cur) { + if (! cur || (cur.pit() > old_cur.pit())) { + // Are we outside of the paragraph? + // This can happen if moving past some UTF8-encoded chars cur = old_cur; increment /= 2; } @@ -3313,10 +3493,10 @@ FindAndReplaceOptions::FindAndReplaceOptions( 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) { } @@ -3378,29 +3558,29 @@ static void changeFirstCase(Buffer & buffer, TextCase first_case, TextCase other } // 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); @@ -3409,7 +3589,7 @@ static void findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, M 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()) { @@ -3434,9 +3614,10 @@ static void findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, M } else if (cur.inMathed()) { odocstringstream ods; otexstream os(ods); - OutputParams runparams(&repl_buffer.params().encoding()); + // OutputParams runparams(&repl_buffer.params().encoding()); + OutputParams runparams(encodings.fromLyXName("utf8")); runparams.nice = false; - runparams.flavor = OutputParams::LATEX; + runparams.flavor = OutputParams::XETEX; runparams.linelen = 8000; //lyxrc.plaintext_linelen; runparams.dryrun = true; TeXOnePar(repl_buffer, repl_buffer.text(), 0, os, runparams); @@ -3461,6 +3642,7 @@ static void findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, M 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; } @@ -3480,7 +3662,7 @@ bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt) 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); @@ -3493,11 +3675,31 @@ bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt) } 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); @@ -3514,6 +3716,7 @@ ostringstream & operator<<(ostringstream & os, FindAndReplaceOptions const & opt << opt.forward << ' ' << opt.expandmacros << ' ' << opt.ignoreformat << ' ' + << opt.replace_all << ' ' << to_utf8(opt.repl_buf_name) << "\nEOSS\n" << opt.keep_case << ' ' << int(opt.scope) << ' ' @@ -3541,7 +3744,7 @@ istringstream & operator>>(istringstream & is, FindAndReplaceOptions & opt) } 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);