X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxfind.cpp;h=93e454fcf10d058a9c86a15a97485cb2a8f1b4e7;hb=3a1b19c5c363428f424180270e32bc8b468ea54f;hp=053f19ab71eb783768c5f289061134aa2482a65a;hpb=d81673ecf0836b77fb7ddd38f6eaceddc1511581;p=lyx.git diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index 053f19ab71..93e454fcf1 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -31,6 +31,7 @@ #include "Paragraph.h" #include "Text.h" #include "Encoding.h" +#include "Language.h" #include "frontends/Application.h" #include "frontends/alert.h" @@ -49,7 +50,7 @@ #include "support/lstrings.h" #include "support/textutils.h" -#include +#include #include //#define ResultsDebug @@ -71,8 +72,9 @@ using namespace lyx::support; namespace lyx { -typedef map AccentsMap; -static AccentsMap accents = map(); +typedef unordered_map AccentsMap; +typedef unordered_map::const_iterator AccentsIterator; +static AccentsMap accents = unordered_map(); // Helper class for deciding what should be ignored class IgnoreFormats { @@ -100,6 +102,10 @@ class IgnoreFormats { /// bool getLanguage() const { return ignoreLanguage_; } /// + bool getDeleted() const { return ignoreDeleted_; } + /// + void setIgnoreDeleted(bool value); + /// void setIgnoreFormat(string const & type, bool value); private: @@ -123,9 +129,10 @@ private: bool ignoreColor_ = false; /// bool ignoreLanguage_ = false; + /// + bool ignoreDeleted_ = true; }; - void IgnoreFormats::setIgnoreFormat(string const & type, bool value) { if (type == "color") { @@ -161,6 +168,9 @@ void IgnoreFormats::setIgnoreFormat(string const & type, bool value) else if (type == "strike") { ignoreStrikeOut_ = value; } + else if (type == "deleted") { + ignoreDeleted_ = value; + } } // The global variable that can be changed from outside @@ -897,7 +907,10 @@ static docstring buffer_to_latex(Buffer & buffer) runparams.linelen = 10000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; - runparams.for_search = true; + if (ignoreFormats.getDeleted()) + runparams.for_searchAdv = OutputParams::SearchWithoutDeleted; + else + runparams.for_searchAdv = OutputParams::SearchWithDeleted; pit_type const endpit = buffer.paragraphs().size(); for (pit_type pit = 0; pit != endpit; ++pit) { TeXOnePar(buffer, buffer.text(), pit, os, runparams); @@ -919,16 +932,23 @@ static docstring stringifySearchBuffer(Buffer & buffer, FindAndReplaceOptions co runparams.flavor = Flavor::XeTeX; runparams.linelen = 10000; //lyxrc.plaintext_linelen; runparams.dryrun = true; - runparams.for_search = true; + int option = AS_STR_INSETS |AS_STR_PLAINTEXT; + if (ignoreFormats.getDeleted()) { + option |= AS_STR_SKIPDELETE; + runparams.for_searchAdv = OutputParams::SearchWithoutDeleted; + } + else { + runparams.for_searchAdv = OutputParams::SearchWithDeleted; + } for (pos_type pit = pos_type(0); pit < (pos_type)buffer.paragraphs().size(); ++pit) { Paragraph const & par = buffer.paragraphs().at(pit); LYXERR(Debug::FIND, "Adding to search string: '" << par.asString(pos_type(0), par.size(), - AS_STR_INSETS | AS_STR_SKIPDELETE | AS_STR_PLAINTEXT, + option, &runparams) << "'"); str += par.asString(pos_type(0), par.size(), - AS_STR_INSETS | AS_STR_SKIPDELETE | AS_STR_PLAINTEXT, + option, &runparams); } // Even in ignore-format we have to remove "\text{}, \lyxmathsym{}" parts @@ -1433,8 +1453,9 @@ void Intervall::removeAccents() 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]; + AccentsIterator it_ac = accents.find(key); + if (it_ac != accents.end()) { + string val = it_ac->second; size_t pos = sub.position(size_t(0)); for (size_t i = 0; i < val.size(); i++) { par[pos+i] = val[i]; @@ -1509,9 +1530,10 @@ int Intervall::nextNotIgnored(int start) const return start; } -typedef map KeysMap; +typedef unordered_map KeysMap; +typedef unordered_map::const_iterator KeysIterator; typedef vector< KeyInfo> Entries; -static KeysMap keys = map(); +static KeysMap keys = unordered_map(); class LatexInfo { private: @@ -1771,9 +1793,10 @@ void LatexInfo::buildEntries(bool isPatternString) key = sub.str(2); } } - if (keys.find(key) != keys.end()) { - if (keys[key].keytype == KeyInfo::headRemove) { - KeyInfo found1 = keys[key]; + KeysIterator it_key = keys.find(key); + if (it_key != keys.end()) { + if (it_key->second.keytype == KeyInfo::headRemove) { + KeyInfo found1 = it_key->second; found1.disabled = true; found1.head = "\\" + key + "{"; found1._tokenstart = sub.position(size_t(2)); @@ -1807,7 +1830,7 @@ void LatexInfo::buildEntries(bool isPatternString) mi.incrEntry(); math_pos = mi.getStartPos(); } - if (keys.find(key) == keys.end()) { + if (it_key == keys.end()) { found = KeyInfo(KeyInfo::isStandard, 0, true); LYXERR(Debug::INFO, "Undefined key " << key << " ==> will be used as text"); found = KeyInfo(KeyInfo::isText, 0, false); @@ -2751,7 +2774,7 @@ string splitOnKnownMacros(string par, bool isPatternString) * Resulting modified string is set to "", if * the searched tex does not contain all the features in the search pattern */ -static string correctlanguagesetting(string par, bool isPatternString, bool withformat) +static string correctlanguagesetting(string par, bool isPatternString, bool withformat, lyx::Buffer *pbuf = nullptr) { static Features regex_f; static int missed = 0; @@ -2771,6 +2794,22 @@ static string correctlanguagesetting(string par, bool isPatternString, bool with // Split the latex input into pieces which // can be digested by our search engine LYXERR(Debug::FIND, "input: \"" << par << "\""); + if (isPatternString && (pbuf != nullptr)) { // Check if we should disable/enable test for language + // We check for polyglossia, because in runparams.flavor we use Flavor::XeTeX + string doclang = pbuf->params().language->polyglossia(); + static regex langre("\\\\(foreignlanguage)\\{([^\\}]+)\\}"); + smatch sub; + bool toIgnoreLang = true; + for (sregex_iterator it(par.begin(), par.end(), langre), end; it != end; ++it) { + sub = *it; + if (sub.str(2) != doclang) { + toIgnoreLang = false; + break; + } + } + setIgnoreFormat("language", toIgnoreLang); + + } result = splitOnKnownMacros(par.substr(0,parlen), isPatternString); LYXERR(Debug::FIND, "After splitOnKnownMacros:\n\"" << result << "\""); } @@ -2938,8 +2977,8 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt) size_t lead_size = 0; // correct the language settings - par_as_string = correctlanguagesetting(par_as_string, true, !opt.ignoreformat); - opt.matchstart = false; + par_as_string = correctlanguagesetting(par_as_string, true, !opt.ignoreformat, &buf); + opt.matchAtStart = false; if (!use_regexp) { identifyClosing(par_as_string); // Removes math closings ($, ], ...) at end of string if (opt.ignoreformat) { @@ -3012,7 +3051,7 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt) if ((lng > 0) && (par_as_string[0] == '^')) { par_as_string = par_as_string.substr(1); --lng; - opt.matchstart = true; + opt.matchAtStart = true; } // LYXERR(Debug::FIND, "par_as_string now is '" << par_as_string << "'"); // LYXERR(Debug::FIND, "Open braces: " << open_braces); @@ -3211,9 +3250,9 @@ MatchResult MatchStringAdv::operator()(DocIterator const & cur, int len, bool at int res = mres.match_len; LYXERR(Debug::FIND, "res=" << res << ", at_begin=" << at_begin - << ", matchstart=" << opt.matchstart + << ", matchAtStart=" << opt.matchAtStart << ", inTexted=" << cur.inTexted()); - if (opt.matchstart) { + if (opt.matchAtStart) { if (cur.pos() != 0) mres.match_len = 0; else if (mres.match_prefix > 0) @@ -3310,11 +3349,18 @@ docstring stringifyFromCursor(DocIterator const & cur, int len) runparams.linelen = 10000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; - runparams.for_search = true; + int option = AS_STR_INSETS | AS_STR_PLAINTEXT; + if (ignoreFormats.getDeleted()) { + option |= AS_STR_SKIPDELETE; + runparams.for_searchAdv = OutputParams::SearchWithoutDeleted; + } + else { + runparams.for_searchAdv = OutputParams::SearchWithDeleted; + } LYXERR(Debug::FIND, "Stringifying with cur: " << cur << ", from pos: " << cur.pos() << ", end: " << end); return par.asString(cur.pos(), end, - AS_STR_INSETS | AS_STR_SKIPDELETE | AS_STR_PLAINTEXT, + option, &runparams); } else if (cur.inMathed()) { CursorSlice cs = cur.top(); @@ -3358,7 +3404,12 @@ docstring latexifyFromCursor(DocIterator const & cur, int len) runparams.linelen = 8000; //lyxrc.plaintext_linelen; // No side effect of file copying and image conversion runparams.dryrun = true; - runparams.for_search = true; + if (ignoreFormats.getDeleted()) { + runparams.for_searchAdv = OutputParams::SearchWithoutDeleted; + } + else { + runparams.for_searchAdv = OutputParams::SearchWithDeleted; + } if (cur.inTexted()) { // @TODO what about searching beyond/across paragraph breaks ? @@ -3622,10 +3673,10 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match) else { // match_len > 0 // Try to find the begin of searched string int increment; - int firstInvalid = 100000; + int firstInvalid = cur.lastpos() - cur.pos(); { int incrmatch = (mres.match_prefix + mres.pos - mres.leadsize + 1)*3/4; - int incrcur = (cur.lastpos() - cur.pos() + 1 )*3/4; + int incrcur = (firstInvalid + 1 )*3/4; if (incrcur < incrmatch) increment = incrcur; else @@ -3636,54 +3687,44 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match) LYXERR(Debug::FIND, "Set increment to " << increment); while (increment > 0) { DocIterator old_cur = cur; - size_t skipping = cur.depth(); - for (int i = 0; i < increment && cur; i++) { - cur.forwardPos(); - while (cur && cur.depth() > skipping) { - cur.pos() = cur.lastpos(); - cur.forwardPos(); - } - } - 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; + if (cur.pos() + increment >= cur.lastpos()) { increment /= 2; + continue; } - else { - MatchResult mres2 = match(cur, -1, false); - displayMres(mres2, "findForwardAdv loop", cur) - switch (interpretMatch(mres, mres2)) { + cur.pos() = cur.pos() + increment; + MatchResult mres2 = match(cur, -1, false); + displayMres(mres2, "findForwardAdv loop", cur) + switch (interpretMatch(mres, mres2)) { case MatchResult::newIsTooFar: - // behind the expected match - firstInvalid = increment; - cur = old_cur; - increment /= 2; - break; + // behind the expected match + firstInvalid = increment; + cur = old_cur; + increment /= 2; + break; case MatchResult::newIsBetter: - // not reached yet, but cur.pos()+increment is bettert - mres = mres2; - firstInvalid -= increment; - if (increment > firstInvalid*3/4) - increment = firstInvalid*3/4; - if ((mres2.pos == mres2.leadsize) && (increment >= mres2.match_prefix)) { - if (increment >= mres2.match_prefix) - increment = (mres2.match_prefix+1)*3/4; - } - break; + // not reached yet, but cur.pos()+increment is bettert + mres = mres2; + firstInvalid -= increment; + if (increment > firstInvalid*3/4) + increment = firstInvalid*3/4; + if ((mres2.pos == mres2.leadsize) && (increment >= mres2.match_prefix)) { + if (increment >= mres2.match_prefix) + increment = (mres2.match_prefix+1)*3/4; + } + break; default: - // Todo@ - // Handle not like MatchResult::newIsTooFar - LYXERR0( "Probably too far: Increment = " << increment << " match_prefix = " << mres.match_prefix); - firstInvalid--; - increment = increment*3/4; - cur = old_cur; - break; - } + // Todo@ + // Handle not like MatchResult::newIsTooFar + LYXERR0( "Probably too far: Increment = " << increment << " match_prefix = " << mres.match_prefix); + firstInvalid--; + increment = increment*3/4; + cur = old_cur; + break; } } if (mres.match_len > 0) { if (mres.match_prefix + mres.pos - mres.leadsize > 0) { + // The match seems to indicate some deeper level repeat = true; orig_cur = cur; orig_mres = mres; @@ -3692,7 +3733,7 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match) } } else if (repeat) { - // seems to never be reached. + // should never be reached. cur = orig_cur; mres = orig_mres; } @@ -3700,15 +3741,15 @@ int findForwardAdv(DocIterator & cur, MatchStringAdv & match) LYXERR(Debug::FIND, "Finalizing 1"); MatchResult found_match = findAdvFinalize(cur, match, mres); if (found_match.match_len > 0) { - LASSERT(found_match.pos_len > 0, /**/); - match.FillResults(found_match); - return found_match.pos_len; + LASSERT(found_match.pos_len > 0, /**/); + match.FillResults(found_match); + return found_match.pos_len; } else { - // try next possible match - cur.forwardPos(); - repeat = false; - continue; + // try next possible match + cur.forwardPos(); + repeat = false; + continue; } } }