]> git.lyx.org Git - lyx.git/blobdiff - src/lyxfind.cpp
FindAdv: Optimization
[lyx.git] / src / lyxfind.cpp
index 053f19ab71eb783768c5f289061134aa2482a65a..93e454fcf10d058a9c86a15a97485cb2a8f1b4e7 100644 (file)
@@ -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 <map>
+#include <unordered_map>
 #include <regex>
 
 //#define ResultsDebug
@@ -71,8 +72,9 @@ using namespace lyx::support;
 
 namespace lyx {
 
-typedef map<string, string> AccentsMap;
-static AccentsMap accents = map<string, string>();
+typedef unordered_map<string, string> AccentsMap;
+typedef unordered_map<string,string>::const_iterator AccentsIterator;
+static AccentsMap accents = unordered_map<string, string>();
 
 // 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<string, KeyInfo> KeysMap;
+typedef unordered_map<string, KeyInfo> KeysMap;
+typedef unordered_map<string, KeyInfo>::const_iterator KeysIterator;
 typedef vector< KeyInfo> Entries;
-static KeysMap keys = map<string, KeyInfo>();
+static KeysMap keys = unordered_map<string, KeyInfo>();
 
 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;
                        }
                }
        }