]> git.lyx.org Git - lyx.git/blobdiff - src/lyxfind.cpp
Rename TextMetrics::dimension() to dim()
[lyx.git] / src / lyxfind.cpp
index cb42e4c71abcaef452b06129e559419b427ddf76..0e996dc1660d9da1875166469181ae60e42aa1f4 100644 (file)
@@ -880,7 +880,7 @@ private:
        string par_as_string;
        // regular expression to use for searching
        lyx::regex regexp;
-       // same as regexp, but prefixed with a ".*"
+       // same as regexp, but prefixed with a ".*?"
        lyx::regex regexp2;
        // leading format material as string
        string lead_as_string;
@@ -1034,20 +1034,36 @@ class KeyInfo {
     /* inputencoding, shortcut, ...
      * Discard also content, because they do not help in search */
     doRemove,
-    /* item */
+    /* twocolumns, ...
+     * like remove, but also all arguments */
+    removeWithArg,
+    /* item, listitem */
     isList,
     /* tex, latex, ... like isChar */
-    isIgnored
+    isIgnored,
+    /* like \lettrine[lines=5]{}{} */
+    cleanToStart,
+    /* End of arguments marker for lettrine,
+     * so that they can be ignored */
+    endArguments
   };
  KeyInfo()
    : keytype(invalid),
     head(""),
+    _tokensize(-1),
+    _tokenstart(-1),
+    _dataStart(-1),
+    _dataEnd(-1),
     parenthesiscount(1),
     disabled(false),
     used(false)
   {};
  KeyInfo(KeyType type, int parcount, bool disable)
    : keytype(type),
+    _tokensize(-1),
+    _tokenstart(-1),
+    _dataStart(-1),
+    _dataEnd(-1),
     parenthesiscount(parcount),
     disabled(disable),
     used(false) {};
@@ -1073,14 +1089,17 @@ class Border {
 class Intervall {
   bool isPatternString;
  public:
- Intervall(bool isPattern) : isPatternString(isPattern), ignoreidx(-1), actualdeptindex(0) { depts[0] = 0;};
+ explicit Intervall(bool isPattern) :
+  isPatternString(isPattern),
+    ignoreidx(-1),
+    actualdeptindex(0) { depts[0] = 0; closes[0] = 0;};
   string par;
   int ignoreidx;
   int depts[MAXOPENED];
   int closes[MAXOPENED];
   int actualdeptindex;
   Border borders[2*MAXOPENED];
-  // int previousNotIgnored(int);
+  int previousNotIgnored(int);
   int nextNotIgnored(int);
   void handleOpenP(int i);
   void handleCloseP(int i, bool closingAllowed);
@@ -1088,7 +1107,7 @@ class Intervall {
   void addIntervall(int upper);
   void addIntervall(int low, int upper); /* if explicit */
   void setForDefaultLang(int upTo);
-  int findclosing(int start, int end, char up, char down);
+  int findclosing(int start, int end, char up, char down, int repeat);
   void handleParentheses(int lastpos, bool closingAllowed);
   void output(ostringstream &os, int lastpos);
   // string show(int lastpos);
@@ -1213,7 +1232,6 @@ void Intervall::resetOpenedP(int openPos)
   closes[1] = -1;
 }
 
-#if 0
 int Intervall::previousNotIgnored(int start)
 {
     int idx = 0;                          /* int intervalls */
@@ -1225,7 +1243,6 @@ int Intervall::previousNotIgnored(int start)
     }
     return start;
 }
-#endif
 
 int Intervall::nextNotIgnored(int start)
 {
@@ -1255,7 +1272,7 @@ class LatexInfo {
   void removeHead(KeyInfo&, int count=0);
 
  public:
- LatexInfo(string par, bool isPatternString) : interval(isPatternString) {
+ LatexInfo(string par, bool isPatternString) : entidx(-1), interval(isPatternString) {
     interval.par = par;
     buildKeys(isPatternString);
     entries = vector<KeyInfo>();
@@ -1285,6 +1302,17 @@ class LatexInfo {
     else
       return false;
   };
+  int find(int start, KeyInfo::KeyType keytype) {
+    if (start < 0)
+      return (-1);
+    int tmpIdx = start;
+    while (tmpIdx < int(entries.size())) {
+      if (entries[tmpIdx].keytype == keytype)
+        return tmpIdx;
+      tmpIdx++;
+    }
+    return(-1);
+  };
   int process(ostringstream &os, KeyInfo &actual);
   int dispatch(ostringstream &os, int previousStart, KeyInfo &actual);
   // string show(int lastpos) { return interval.show(lastpos);};
@@ -1301,10 +1329,11 @@ class LatexInfo {
 };
 
 
-int Intervall::findclosing(int start, int end, char up = '{', char down = '}')
+int Intervall::findclosing(int start, int end, char up = '{', char down = '}', int repeat = 1)
 {
   int skip = 0;
   int depth = 0;
+  repeat--;
   for (int i = start; i < end; i += 1 + skip) {
     char c;
     c = par[i];
@@ -1314,7 +1343,10 @@ int Intervall::findclosing(int start, int end, char up = '{', char down = '}')
       depth++;
     }
     else if (c == down) {
-      if (depth == 0) return i;
+      if (depth == 0) {
+        if ((repeat <= 0) || (par[i+1] != up))
+          return i;
+      }
       --depth;
     }
   }
@@ -1343,16 +1375,6 @@ class MathInfo {
     m.mathSize = end - start;
     entries.push_back(m);
   }
-  bool evaluating(size_t pos) {
-    while (actualIdx < entries.size()) {
-      if (pos < entries[actualIdx].mathStart)
-        return false;
-      if (pos < entries[actualIdx].mathEnd)
-        return true;
-      actualIdx++;
-    }
-    return false;
-  }
   bool empty() { return entries.empty(); };
   size_t getEndPos() {
     if (entries.empty() || (actualIdx >= entries.size())) {
@@ -1390,6 +1412,8 @@ void LatexInfo::buildEntries(bool isPatternString)
   bool evaluatingMath = false;
   bool evaluatingCode = false;
   size_t codeEnd = 0;
+  bool evaluatingOptional = false;
+  size_t optionalEnd = 0;
   int codeStart = -1;
   KeyInfo found;
   bool math_end_waiting = false;
@@ -1492,10 +1516,16 @@ void LatexInfo::buildEntries(bool isPatternString)
         math_pos = mi.getStartPos();
       }
       if (keys.find(key) == keys.end()) {
-        LYXERR(Debug::FIND, "Found unknown key " << sub.str(0));
-        continue;
+        found = KeyInfo(KeyInfo::isStandard, 0, true);
+        if (isPatternString) {
+          found.keytype = KeyInfo::isChar;
+          found.disabled = false;
+          found.used = true;
+        }
+        keys[key] = found;
       }
-      found = keys[key];
+      else
+        found = keys[key];
       if (key.compare("regexp") == 0) {
         evaluatingRegexp = true;
         found._tokenstart = sub.position(size_t(0));
@@ -1521,13 +1551,21 @@ void LatexInfo::buildEntries(bool isPatternString)
         // First handle tables
         // longtable|tabular
         bool discardComment;
+        found = keys[key];
+        found.keytype = KeyInfo::doRemove;
         if ((sub.str(5).compare("longtable") == 0) ||
             (sub.str(5).compare("tabular") == 0)) {
           discardComment = true;        /* '%' */
         }
-        else
+        else {
           discardComment = false;
-        found = keys[key];
+          static regex const removeArgs("^(multicols|multipar|sectionbox|subsectionbox|tcolorbox)$");
+          smatch sub2;
+          string token = sub.str(5);
+          if (regex_match(token, sub2, removeArgs)) {
+            found.keytype = KeyInfo::removeWithArg;
+          }
+        }
         // discard spaces before pos(0)
         int pos = sub.position(size_t(0));
         int count;
@@ -1540,7 +1578,6 @@ void LatexInfo::buildEntries(bool isPatternString)
           else if (c != ' ')
             break;
         }
-        found.keytype = KeyInfo::doRemove;
         found._tokenstart = pos - count;
         if (sub.str(1).compare(0, 5, "begin") == 0) {
           size_t pos1 = pos + sub.str(0).length();
@@ -1557,7 +1594,7 @@ void LatexInfo::buildEntries(bool isPatternString)
             found.head = interval.par.substr(found._tokenstart, found._tokensize);
           }
           else {
-            if (interval.par[pos1] == '[') {
+            while (interval.par[pos1] == '[') {
               pos1 = interval.findclosing(pos1+1, interval.par.length(), '[', ']')+1;
             }
             if (interval.par[pos1] == '{') {
@@ -1601,15 +1638,53 @@ void LatexInfo::buildEntries(bool isPatternString)
         found._dataStart = found._dataEnd;
       }
       else {
+        int params = found._tokenstart + key.length() + 1;
+        if (evaluatingOptional) {
+          if (size_t(found._tokenstart) > optionalEnd) {
+            evaluatingOptional = false;
+          }
+          else {
+            found.disabled = true;
+          }
+        }
+        int optend = params;
+        while (interval.par[optend] == '[') {
+          // discard optional parameters
+          optend = interval.findclosing(optend+1, interval.par.length(), '[', ']') + 1;
+        }
+        if (optend > params) {
+          key += interval.par.substr(params, optend-params);
+          evaluatingOptional = true;
+          optionalEnd = optend;
+        }
+        string token = sub.str(5);
+        int closings = found.parenthesiscount;
         if (found.parenthesiscount == 1) {
           found.head = "\\" + key + "{";
         }
-        else if (found.parenthesiscount == 2) {
-          found.head = sub.str(0) + "{";
+        else if (found.parenthesiscount > 1) {
+          if (token != "") {
+            found.head = sub.str(0) + "{";
+            closings = found.parenthesiscount - 1;
+          }
+          else {
+            found.head = "\\" + key + "{";
+          }
         }
-        found._tokensize = found.head.length();
         found._dataStart = found._tokenstart + found.head.length();
-        size_t endpos = interval.findclosing(found._dataStart, interval.par.length());
+        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);
+        if (found.keytype == KeyInfo::isList) {
+          // Check if it really is list env
+          static regex const listre("^([a-z]+)$");
+          smatch sub2;
+          if (!regex_match(token, sub2, listre)) {
+            // Change the key of this entry. It is not in a list/item environment
+            found.keytype = KeyInfo::endArguments;
+          }
+        }
         if (found.keytype == KeyInfo::noMain) {
           evaluatingCode = true;
           codeEnd = endpos;
@@ -1701,14 +1776,14 @@ void LatexInfo::buildKeys(bool isPatternString)
   // No split
   makeKey("backslash|textbackslash|slash",  KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   makeKey("textasciicircum|textasciitilde", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
-  makeKey("textasciiacute",                 KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+  makeKey("textasciiacute|texemdash",       KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   makeKey("dots|ldots",                     KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   // Spaces
   makeKey("quad|qquad|hfill|dotfill",               KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   makeKey("textvisiblespace|nobreakspace",          KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   makeKey("negthickspace|negmedspace|negthinspace", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   // Skip
-  makeKey("enskip|smallskip|medskip|bigskip|vfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+  // makeKey("enskip|smallskip|medskip|bigskip|vfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   // Custom space/skip, remove the content (== length value)
   makeKey("vspace|hspace|mspace", KeyInfo(KeyInfo::noContent, 1, false), isPatternString);
   // Found in fr/UserGuide.lyx
@@ -1718,8 +1793,8 @@ void LatexInfo::buildKeys(bool isPatternString)
   makeKey("textquotedblleft|textquotedblright", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
   // Known macros to remove (including their parameter)
   // No split
-  makeKey("inputencoding|shortcut|label|ref|index", KeyInfo(KeyInfo::doRemove, 1, false), isPatternString);
-
+  makeKey("inputencoding|shortcut|label|ref|index|bibitem", KeyInfo(KeyInfo::doRemove, 1, false), isPatternString);
+  makeKey("addtocounter|setlength",                 KeyInfo(KeyInfo::noContent, 2, true), isPatternString);
   // handle like standard keys with 1 parameter.
   makeKey("url|href|vref|thanks", KeyInfo(KeyInfo::isStandard, 1, false), isPatternString);
 
@@ -1728,7 +1803,7 @@ void LatexInfo::buildKeys(bool isPatternString)
   makeKey("menuitem|textmd|textrm", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
 
   // Remove language spec from content of these insets
-  makeKey("code|footnote", KeyInfo(KeyInfo::noMain, 1, false), isPatternString);
+  makeKey("code", KeyInfo(KeyInfo::noMain, 1, false), isPatternString);
 
   // Same effect as previous, parameter will survive (because there is no one anyway)
   // No split
@@ -1740,21 +1815,27 @@ void LatexInfo::buildKeys(bool isPatternString)
   makeKey("trianglerightpar|hexagonpar|starpar",   KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
   makeKey("triangleuppar|triangledownpar|droppar", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
   makeKey("triangleleftpar|shapepar|dropuppar",    KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
+  makeKey("hphantom|footnote|includegraphics",     KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
   // like ('tiny{}' or '\tiny ' ... )
   makeKey("footnotesize|tiny|scriptsize|small|large|Large|LARGE|huge|Huge", KeyInfo(KeyInfo::isSize, 0, false), isPatternString);
 
   // Survives, like known character
-  makeKey("lyx|latex|latexe|tex", KeyInfo(KeyInfo::isIgnored, 0, false), isPatternString);
-  makeKey("item", KeyInfo(KeyInfo::isList, 1, false), isPatternString);
+  makeKey("lyx|LyX|latex|LaTeX|latexe|LaTeXe|tex|TeX", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+  makeKey("item|listitem", KeyInfo(KeyInfo::isList, 1, false), isPatternString);
 
   makeKey("begin|end", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
   makeKey("[|]", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
   makeKey("$", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
 
-  makeKey("par|uldepth|ULdepth|protect|nobreakdash", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
+  makeKey("par|uldepth|ULdepth|protect|nobreakdash|medskip|relax", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
   // Remove RTL/LTR marker
   makeKey("l|r|textlr|textfr|textar|beginl|endl", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
-
+  makeKey("lettrine", KeyInfo(KeyInfo::cleanToStart, 0, true), isPatternString);
+  makeKey("lyxslide", KeyInfo(KeyInfo::isSectioning, 1, true), isPatternString);
+  makeKey("endarguments", KeyInfo(KeyInfo::endArguments, 0, true), isPatternString);
+  makeKey("twocolumn", KeyInfo(KeyInfo::removeWithArg, 2, true), isPatternString);
+  makeKey("tnotetext|ead|fntext|cortext|address", KeyInfo(KeyInfo::removeWithArg, 0, true), isPatternString);
+  makeKey("lyxend", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
   if (isPatternString) {
     // Allow the first searched string to rebuild the keys too
     keysBuilt = false;
@@ -1790,7 +1871,6 @@ void Intervall::handleParentheses(int lastpos, bool closingAllowed)
 string Intervall::show(int lastpos)
 {
   int idx = 0;                          /* int intervalls */
-  int count = 0;
   string s;
   int i = 0;
   for (idx = 0; idx <= ignoreidx; idx++) {
@@ -1826,8 +1906,8 @@ void Intervall::output(ostringstream &os, int lastpos)
   int i = 0;
   for (idx = 0; idx <= ignoreidx; idx++) {
     if (i < lastpos) {
-      int printsize;
       if (i <= borders[idx].low) {
+        int printsize;
         if (borders[idx].low > lastpos)
           printsize = lastpos - i;
         else
@@ -1880,7 +1960,7 @@ void LatexInfo::removeHead(KeyInfo &actual, int count)
   }
   else {
     // Remove header hull, that is "\url{abcd}" ==> "abcd"
-    interval.addIntervall(actual._tokenstart, actual._dataStart);
+    interval.addIntervall(actual._tokenstart - count, actual._dataStart);
     interval.addIntervall(actual._dataEnd, actual._dataEnd+1);
   }
 }
@@ -1890,8 +1970,30 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
   int nextKeyIdx = 0;
   switch (actual.keytype)
   {
+    case KeyInfo::cleanToStart: {
+      actual._dataEnd = actual._dataStart;
+      nextKeyIdx = getNextKey();
+      // Search for end of arguments
+      int tmpIdx = find(nextKeyIdx, KeyInfo::endArguments);
+      if (tmpIdx > 0) {
+        for (int i = nextKeyIdx; i <= tmpIdx; i++) {
+          entries[i].disabled = true;
+        }
+        actual._dataEnd = entries[tmpIdx]._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;
+      break;
+    }
     case KeyInfo::noContent: {          /* char like "\hspace{2cm}" */
-      interval.addIntervall(actual._dataStart, actual._dataEnd);
+      if (actual.disabled)
+        interval.addIntervall(actual._tokenstart, actual._dataEnd);
+      else
+        interval.addIntervall(actual._dataStart, actual._dataEnd);
     }
       // fall through
     case KeyInfo::isChar: {
@@ -1899,17 +2001,23 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
       break;
     }
     case KeyInfo::isSize: {
-      if (actual.disabled || (interval.par[actual._dataStart] != '{')) {
+      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);
         nextKeyIdx = getNextKey();
       } else {
-        // Determine the end if used like '{\tiny{}...}'
-        if (interval.par[actual._dataStart+1] == '}') {
-          actual._dataStart += 1;
-          interval.addIntervall(actual._dataStart, actual._dataStart+1);
+        // Here _dataStart points to '{', so correct it
+        actual._dataStart += 1;
+        actual._tokensize += 1;
+        actual.parenthesiscount = 1;
+        if (interval.par[actual._dataStart] == '}') {
+          // Determine the end if used like '{\tiny{}...}'
           actual._dataEnd = interval.findclosing(actual._dataStart+1, interval.par.length()) + 1;
-          actual.parenthesiscount = 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;
         }
         // Split on this key if not at start
         int start = interval.nextNotIgnored(previousStart);
@@ -1922,6 +2030,13 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
       }
       break;
     }
+    case KeyInfo::endArguments:
+      // Remove trailing '{}' too
+      actual._dataStart += 2;
+      actual._dataEnd += 2;
+      interval.addIntervall(actual._tokenstart, actual._dataEnd);
+      nextKeyIdx = getNextKey();
+      break;
     case KeyInfo::noMain:
       // fall through
     case KeyInfo::isStandard: {
@@ -1930,7 +2045,7 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
         processRegion(actual._dataStart, actual._dataStart+1);
         nextKeyIdx = getNextKey();
       } else {
-        // Split on this key if not at start
+        // Split on this key if not at datastart of calling entry
         int start = interval.nextNotIgnored(previousStart);
         if (start < actual._tokenstart) {
           interval.output(os, actual._tokenstart);
@@ -1941,6 +2056,19 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
       }
       break;
     }
+    case KeyInfo::removeWithArg: {
+      nextKeyIdx = getNextKey();
+      // Search for end of arguments
+      int tmpIdx = find(nextKeyIdx, KeyInfo::endArguments);
+      if (tmpIdx > 0) {
+        for (int i = nextKeyIdx; i <= tmpIdx; i++) {
+          entries[i].disabled = true;
+        }
+        actual._dataEnd = entries[tmpIdx]._dataEnd;
+      }
+      interval.addIntervall(actual._tokenstart, actual._dataEnd+1);
+      break;
+    }
     case KeyInfo::doRemove: {
       // Remove the key with all parameters and following spaces
       size_t pos;
@@ -1959,13 +2087,30 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
         if (interval.par[actual._tokenstart-count-1] != ' ')
           break;
       }
+      nextKeyIdx = getNextKey();
+      int tmpIdx = find(nextKeyIdx, KeyInfo::endArguments);
+      if (tmpIdx > 0) {
+        // Special case: \item is not a list, but a command (like in Style Author_Biography in maa-monthly.layout)
+        // with arguments
+        // How else can we catch this one?
+        for (int i = nextKeyIdx; i <= tmpIdx; i++) {
+          entries[i].disabled = true;
+        }
+        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;
+        }
+      }
       if (actual.disabled) {
         interval.addIntervall(actual._tokenstart-count, actual._dataEnd+1);
       }
       else {
         interval.addIntervall(actual._tokenstart-count, actual._tokenstart);
       }
-      // Discard extra parentheses '[]'
       if (interval.par[actual._dataEnd+1] == '[') {
         int posdown = interval.findclosing(actual._dataEnd+2, interval.par.length(), '[', ']');
         if ((interval.par[actual._dataEnd+2] == '{') &&
@@ -1989,15 +2134,19 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
             interval.addIntervall(blk, blk+count);
         }
       }
-      nextKeyIdx = getNextKey();
       break;
     }
     case KeyInfo::isSectioning: {
       // Discard spaces before _tokenstart
       int count;
-      for (count = 0; count < actual._tokenstart; count++) {
-        if (interval.par[actual._tokenstart-count-1] != ' ')
+      int val = actual._tokenstart;
+      for (count = 0; count < actual._tokenstart;) {
+        val = interval.previousNotIgnored(val-1);
+        if (interval.par[val] != ' ')
           break;
+        else {
+          count = actual._tokenstart - val;
+        }
       }
       if (actual.disabled) {
         removeHead(actual, count);
@@ -2034,7 +2183,8 @@ int LatexInfo::dispatch(ostringstream &os, int previousStart, KeyInfo &actual)
           // Discard also the space before math-equation
           interval.addIntervall(actual._dataStart, actual._dataStart+1);
         }
-        interval.resetOpenedP(actual._dataStart-1);
+        nextKeyIdx = getNextKey();
+        // interval.resetOpenedP(actual._dataStart-1);
       }
       else {
         if (actual._tokenstart == 0) {
@@ -2074,7 +2224,7 @@ int LatexInfo::process(ostringstream &os, KeyInfo &actual )
     }
     KeyInfo &nextKey = getKeyInfo(nextKeyIdx);
 
-    if (nextKey.keytype == KeyInfo::isMain) {
+    if ((nextKey.keytype == KeyInfo::isMain) && !nextKey.disabled) {
       (void) dispatch(os, actual._dataStart, nextKey);
       end = nextKey._tokenstart;
       break;
@@ -2117,9 +2267,11 @@ int LatexInfo::process(ostringstream &os, KeyInfo &actual )
   return nextKeyIdx;
 }
 
-string splitOnKnownMacros(string par, bool isPatternString) {
+string splitOnKnownMacros(string par, bool isPatternString)
+{
   ostringstream os;
   LatexInfo li(par, isPatternString);
+  // LYXERR0("Berfore split: " << par);
   KeyInfo DummyKey = KeyInfo(KeyInfo::KeyType::isMain, 2, true);
   DummyKey.head = "";
   DummyKey._tokensize = 0;
@@ -2190,6 +2342,7 @@ string splitOnKnownMacros(string par, bool isPatternString) {
   }
   else
     s = par;                            /* no known macros found */
+  // LYXERR0("After split: " << s);
   return s;
 }
 
@@ -2209,12 +2362,16 @@ static string correctlanguagesetting(string par, bool isPatternString, bool with
        while ((parlen > 0) && (par[parlen-1] == '\n')) {
                parlen--;
        }
+       if (isPatternString && (parlen > 0) && (par[parlen-1] == '~')) {
+               // Happens to be there in case of description or labeling environment
+               parlen--;
+       }
        string result;
        if (withformat) {
                // Split the latex input into pieces which
                // can be digested by our search engine
                LYXERR(Debug::FIND, "input: \"" << par << "\"");
-               result = splitOnKnownMacros(par, isPatternString);
+               result = splitOnKnownMacros(par.substr(0,parlen), isPatternString);
                LYXERR(Debug::FIND, "After split: \"" << result << "\"");
        }
        else
@@ -2370,7 +2527,7 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const &
                                while (regex_replace(par_as_string, par_as_string, orig, dest));
                        }
                        regexp_str = "(" + lead_as_regexp + ")" + par_as_string;
-                       regexp2_str = "(" + lead_as_regexp + ").*" + par_as_string;
+                       regexp2_str = "(" + lead_as_regexp + ").*?" + par_as_string;
                }
                LYXERR(Debug::FIND, "Setting regexp to : '" << regexp_str << "'");
                regexp = lyx::regex(regexp_str);
@@ -2581,9 +2738,26 @@ string MatchStringAdv::normalize(docstring const & s, bool hack_braces) const
        while (!t.empty() && t[t.size() - 1] == '\n')
                t = t.substr(0, t.size() - 1);
        size_t pos;
-       // Replace all other \n with spaces
-       while ((pos = t.find("\n")) != string::npos)
-               t.replace(pos, 1, " ");
+       // Handle all other '\n'
+       while ((pos = t.find("\n")) != string::npos) {
+               if (pos > 1 && t[pos-1] == '\\' && t[pos-2] == '\\' ) {
+                       // Handle '\\\n'
+                       if (std::isalnum(t[pos+1])) {
+                               t.replace(pos-2, 3, " ");
+                       }
+                       else {
+                               t.replace(pos-2, 3, "");
+                       }
+               }
+               else if (!std::isalnum(t[pos+1]) || !std::isalnum(t[pos-1])) {
+                       // '\n' adjacent to non-alpha-numerics, discard
+                       t.replace(pos, 1, "");
+               }
+               else {
+                       // Replace all other \n with spaces
+                       t.replace(pos, 1, " ");
+               }
+       }
        // Remove stale empty \emph{}, \textbf{} and similar blocks from latexify
        // Kornel: Added textsl, textsf, textit, texttt and noun
        // + allow to seach for colored text too
@@ -2790,6 +2964,39 @@ int findAdvFinalize(DocIterator & cur, MatchStringAdv const & match)
              len = (int)((maxl + minl)/2);
            }
          }
+          old_cur = cur;
+          // Search for real start of matched characters
+          while (len > 1) {
+            int actual_match;
+            do {
+              cur.forwardPos();
+            } while (cur.depth() > old_cur.depth()); /* Skip inner insets */
+            if (cur.depth() < old_cur.depth()) {
+              // Outer inset?
+              LYXERR0("cur.depth() < old_cur.depth(), this should never happen");
+              break;
+            }
+            if (cur.pos() != old_cur.pos()) {
+              // OK, forwarded 1 pos in actual inset
+              actual_match = match(cur, len-1);
+              if (actual_match == max_match) {
+                // Ha, got it! The shorter selection has the same match length
+                len--;
+                old_cur = cur;
+              }
+              else {
+                // OK, the shorter selection matches less chars, revert to previous value
+                cur = old_cur;
+                break;
+              }
+            }
+            else {
+              LYXERR0("cur.pos() == old_cur.pos(), this should never happen");
+              actual_match = match(cur, len);
+              if (actual_match == max_match)
+                old_cur = cur;
+            }
+          }
        }
        return len;
 }