- static bool keysBuilt = false;
- if (keysBuilt && !isPatternString) return;
-
- // Keys to ignore in any case
- makeKey("text|textcyrillic|lyxmathsym", KeyInfo(KeyInfo::headRemove, 1, true), true);
- // Known standard keys with 1 parameter.
- // Split is done, if not at start of region
- makeKey("textsf|textss|texttt", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getFamily()), isPatternString);
- makeKey("textbf", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getSeries()), isPatternString);
- makeKey("textit|textsc|textsl", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getShape()), isPatternString);
- makeKey("uuline|uline|uwave", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getUnderline()), isPatternString);
- makeKey("emph|noun", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getMarkUp()), isPatternString);
- makeKey("sout|xout", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getStrikeOut()), isPatternString);
-
- makeKey("section|subsection|subsubsection|paragraph|subparagraph|minisec",
- KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
- makeKey("section*|subsection*|subsubsection*|paragraph*",
- KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
- makeKey("part|part*|chapter|chapter*", KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
- makeKey("title|subtitle|author|subject|publishers|dedication|uppertitleback|lowertitleback|extratitle|lyxaddress|lyxrightaddress", KeyInfo(KeyInfo::isTitle, 1, ignoreFormats.getFrontMatter()), isPatternString);
- // Regex
- makeKey("regexp", KeyInfo(KeyInfo::isRegex, 1, false), isPatternString);
-
- // Split is done, if not at start of region
- makeKey("textcolor", KeyInfo(KeyInfo::isStandard, 2, ignoreFormats.getColor()), isPatternString);
- makeKey("latexenvironment", KeyInfo(KeyInfo::isStandard, 2, false), isPatternString);
-
- // Split is done always.
- makeKey("foreignlanguage", KeyInfo(KeyInfo::isMain, 2, ignoreFormats.getLanguage()), isPatternString);
-
- // Known charaters
- // No split
- makeKey("backslash|textbackslash|slash", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- makeKey("textasciicircum|textasciitilde", 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);
- makeKey("thickspace|medspace|thinspace", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- // Skip
- // makeKey("enskip|smallskip|medskip|bigskip|vfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- // Custom space/skip, remove the content (== length value)
- makeKey("vspace|vspace*|hspace|hspace*|mspace", KeyInfo(KeyInfo::noContent, 1, false), isPatternString);
- // Found in fr/UserGuide.lyx
- makeKey("og|fg", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- // quotes
- makeKey("textquotedbl|quotesinglbase|lyxarrow", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- makeKey("textquotedblleft|textquotedblright", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- // Known macros to remove (including their parameter)
- // No split
- makeKey("input|inputencoding|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);
-
- // Ignore deleted text
- makeKey("lyxdeleted", KeyInfo(KeyInfo::doRemove, 3, false), isPatternString);
- // but preserve added text
- makeKey("lyxadded", KeyInfo(KeyInfo::doRemove, 2, false), isPatternString);
-
- // Macros to remove, but let the parameter survive
- // No split
- makeKey("menuitem|textmd|textrm", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
-
- // Remove language spec from content of these insets
- makeKey("code", KeyInfo(KeyInfo::noMain, 1, false), isPatternString);
-
- // Same effect as previous, parameter will survive (because there is no one anyway)
- // No split
- makeKey("noindent|textcompwordmark|maketitle", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
- // Remove table decorations
- makeKey("hline|tabularnewline|toprule|bottomrule|midrule", KeyInfo(KeyInfo::doRemove, 0, true), isPatternString);
- // Discard shape-header.
- // For footnote or shortcut too, because of lang settings
- // and wrong handling if used 'KeyInfo::noMain'
- makeKey("circlepar|diamondpar|heartpar|nutpar", KeyInfo(KeyInfo::isStandard, 1, true), 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|vphantom|footnote|shortcut|include|includegraphics", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
- makeKey("parbox", KeyInfo(KeyInfo::doRemove, 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|LyX|latex|LaTeX|latexe|LaTeXe|tex|TeX", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- makeKey("tableofcontents", 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|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;
- }
- else {
- // no need to rebuild again
- keysBuilt = true;
- }
+class MathInfo {
+ class MathEntry {
+ public:
+ string wait;
+ size_t mathEnd;
+ size_t mathpostfixsize;
+ size_t mathStart;
+ size_t mathprefixsize;
+ size_t mathSize;
+ };
+ size_t actualIdx_;
+ vector<MathEntry> entries_;
+public:
+ MathInfo() {
+ actualIdx_ = 0;
+ }
+ void insert(string const & wait, size_t start, size_t prefixsize, size_t end, size_t postfixsize) {
+ MathEntry m = MathEntry();
+ m.wait = wait;
+ m.mathStart = start;
+ m.mathprefixsize = prefixsize;
+ m.mathEnd = end + postfixsize;
+ m.mathpostfixsize = postfixsize;
+ m.mathSize = m.mathEnd - m.mathStart;
+ entries_.push_back(m);
+ }
+ bool empty() const { return entries_.empty(); }
+ size_t getEndPos() const {
+ if (entries_.empty() || (actualIdx_ >= entries_.size())) {
+ return 0;
+ }
+ return entries_[actualIdx_].mathEnd;
+ }
+ size_t getStartPos() const {
+ if (entries_.empty() || (actualIdx_ >= entries_.size())) {
+ return 100000; /* definitely enough? */
+ }
+ return entries_[actualIdx_].mathStart;
+ }
+ size_t getPrefixSize() const {
+ if (entries_.empty() || (actualIdx_ >= entries_.size())) {
+ return 0;
+ }
+ return entries_[actualIdx_].mathprefixsize;
+ }
+ size_t getPostfixSize() const {
+ if (entries_.empty() || (actualIdx_ >= entries_.size())) {
+ return 0;
+ }
+ return entries_[actualIdx_].mathpostfixsize;
+ }
+ size_t getFirstPos() {
+ actualIdx_ = 0;
+ return getStartPos();
+ }
+ size_t getSize() const {
+ if (entries_.empty() || (actualIdx_ >= entries_.size())) {
+ return size_t(0);
+ }
+ return entries_[actualIdx_].mathSize;
+ }
+ void incrEntry() { actualIdx_++; }
+};
+
+void LatexInfo::buildEntries(bool isPatternString)
+{
+ static regex const rmath("(\\\\)*(\\$|\\\\\\[|\\\\\\]|\\\\(begin|end)\\{((eqnarray|equation|flalign|gather|multline|align|x?x?alignat)\\*?\\})(\\{[0-9]+\\})?)");
+ static regex const rkeys("(\\\\)*(\\$|\\\\\\[|\\\\\\]|\\\\((([a-zA-Z]+\\*?)(\\{([a-z]+\\*?)\\}|=[0-9]+[a-z]+)?)))");
+ static bool disableLanguageOverride = false;
+ smatch sub, submath;
+ bool evaluatingRegexp = false;
+ MathInfo mi;
+ 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;
+ size_t math_pos = 10000;
+ size_t math_prefix_size = 1;
+ string math_end;
+ static vector<string> usedText = vector<string>();
+ static bool removeMathHull = false;
+
+ interval_.removeAccents();
+
+ for (sregex_iterator itmath(interval_.par.begin(), interval_.par.end(), rmath), end; itmath != end; ++itmath) {
+ submath = *itmath;
+ if ((submath.position(2) - submath.position(0)) %2 == 1) {
+ // prefixed by odd count of '\\'
+ continue;
+ }
+ if (math_end_waiting) {
+ size_t pos = submath.position(size_t(2));
+ if ((math_end == "$") &&
+ (submath.str(2) == "$")) {
+ mi.insert("$", math_pos, 1, pos, 1);
+ math_end_waiting = false;
+ }
+ else if ((math_end == "\\]") &&
+ (submath.str(2) == "\\]")) {
+ mi.insert("\\]", math_pos, 2, pos, 2);
+ math_end_waiting = false;
+ }
+ else if ((submath.str(3).compare("end") == 0) &&
+ (submath.str(5).compare(math_end) == 0)) {
+ mi.insert(math_end, math_pos, math_prefix_size, pos, submath.str(2).length());
+ math_end_waiting = false;
+ }
+ else
+ continue;
+ }
+ else {
+ if (submath.str(3).compare("begin") == 0) {
+ math_end_waiting = true;
+ math_end = submath.str(5);
+ math_pos = submath.position(size_t(2));
+ math_prefix_size = submath.str(2).length();
+ }
+ else if (submath.str(2).compare("\\[") == 0) {
+ math_end_waiting = true;
+ math_end = "\\]";
+ math_pos = submath.position(size_t(2));
+ }
+ else if (submath.str(2) == "$") {
+ size_t pos = submath.position(size_t(2));
+ math_end_waiting = true;
+ math_end = "$";
+ math_pos = pos;
+ }
+ }
+ }
+ // Ignore language if there is math somewhere in pattern-string
+ if (isPatternString) {
+ for (auto s: usedText) {
+ // Remove entries created in previous search runs
+ keys.erase(s);
+ }
+ usedText = vector<string>();
+ if (! mi.empty()) {
+ // Disable language
+ keys["foreignlanguage"].disabled = true;
+ disableLanguageOverride = true;
+ removeMathHull = false;
+ }
+ else {
+ removeMathHull = true; // used later if not isPatternString
+ disableLanguageOverride = false;
+ }
+ }
+ else {
+ if (disableLanguageOverride) {
+ keys["foreignlanguage"].disabled = true;
+ }
+ }
+ math_pos = mi.getFirstPos();
+ for (sregex_iterator it(interval_.par.begin(), interval_.par.end(), rkeys), end; it != end; ++it) {
+ sub = *it;
+ if ((sub.position(2) - sub.position(0)) %2 == 1) {
+ // prefixed by odd count of '\\'
+ continue;
+ }
+ string key = sub.str(5);
+ if (key == "") {
+ if (sub.str(2)[0] == '\\')
+ key = sub.str(2)[1];
+ else {
+ key = sub.str(2);
+ }
+ }
+ 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));
+ found1._tokensize = found1.head.length();
+ found1._dataStart = found1._tokenstart + found1.head.length();
+ int endpos = interval_.findclosing(found1._dataStart, interval_.par.length(), '{', '}', 1);
+ found1._dataEnd = endpos;
+ removeHead(found1);
+ continue;
+ }
+ }
+ if (evaluatingRegexp) {
+ if (sub.str(3).compare("endregexp") == 0) {
+ evaluatingRegexp = false;
+ // found._tokenstart already set
+ found._dataEnd = sub.position(size_t(2)) + 13;
+ found._dataStart = found._dataEnd;
+ found._tokensize = found._dataEnd - found._tokenstart;
+ found.parenthesiscount = 0;
+ found.head = interval_.par.substr(found._tokenstart, found._tokensize);
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ if (evaluatingMath) {
+ if (size_t(sub.position(size_t(2))) < mi.getEndPos())
+ continue;
+ evaluatingMath = false;
+ mi.incrEntry();
+ math_pos = mi.getStartPos();
+ }
+ 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);
+ if (isPatternString) {
+ found.keytype = KeyInfo::isChar;
+ found.disabled = false;
+ found.used = true;
+ }
+ keys[key] = found;
+ usedText.push_back(key);
+ }
+ else
+ found = keys[key];
+ if (key.compare("regexp") == 0) {
+ evaluatingRegexp = true;
+ found._tokenstart = sub.position(size_t(2));
+ found._tokensize = 0;
+ continue;
+ }
+ }
+ // Handle the other params of key
+ if (found.keytype == KeyInfo::isIgnored)
+ continue;
+ else if (found.keytype == KeyInfo::isMath) {
+ if (size_t(sub.position(size_t(2))) == math_pos) {
+ found = keys[key];
+ found._tokenstart = sub.position(size_t(2));
+ found._tokensize = mi.getSize();
+ found._dataEnd = found._tokenstart + found._tokensize;
+ found._dataStart = found._dataEnd;
+ found.parenthesiscount = 0;
+ found.head = interval_.par.substr(found._tokenstart, found._tokensize);
+ if (removeMathHull) {
+ interval_.addIntervall(found._tokenstart, found._tokenstart + mi.getPrefixSize());
+ interval_.addIntervall(found._dataEnd - mi.getPostfixSize(), found._dataEnd);
+ }
+ else {
+ // Treate all math constructs as simple math
+ interval_.par[found._tokenstart] = '$';
+ interval_.par[found._dataEnd - mi.getPostfixSize()] = '$';
+ interval_.addIntervall(found._tokenstart + 1, found._tokenstart + mi.getPrefixSize());
+ interval_.addIntervall(found._dataEnd - mi.getPostfixSize() + 1, found._dataEnd);
+ }
+ evaluatingMath = true;
+ }
+ else {
+ // begin|end of unknown env, discard
+ // First handle tables
+ // longtable|tabular
+ bool discardComment;
+ found = keys[key];
+ found.keytype = KeyInfo::doRemove;
+ if ((sub.str(7).compare("longtable") == 0) ||
+ (sub.str(7).compare("tabular") == 0)) {
+ discardComment = true; /* '%' */
+ }
+ else {
+ discardComment = false;
+ static regex const removeArgs("^(multicols|multipar|sectionbox|subsectionbox|tcolorbox)$");
+ smatch sub2;
+ string token = sub.str(7);
+ if (regex_match(token, sub2, removeArgs)) {
+ found.keytype = KeyInfo::removeWithArg;
+ }
+ }
+ // discard spaces before pos(2)
+ int pos = sub.position(size_t(2));
+ int count;
+ for (count = 0; pos - count > 0; count++) {
+ char c = interval_.par[pos-count-1];
+ if (discardComment) {
+ if ((c != ' ') && (c != '%'))
+ break;
+ }
+ else if (c != ' ')
+ break;
+ }
+ found._tokenstart = pos - count;
+ if (sub.str(3).compare(0, 5, "begin") == 0) {
+ size_t pos1 = pos + sub.str(2).length();
+ if (sub.str(7).compare("cjk") == 0) {
+ 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.disabled = keys["foreignlanguage"].disabled;
+ found.used = keys["foreignlanguage"].used;
+ found._tokensize = pos1 - found._tokenstart;
+ 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;
+ }
+ // Swallow also the eventual parameter
+ if (interval_.par[pos1] == '{') {
+ found._dataEnd = interval_.findclosing(pos1+1, interval_.par.length()) + 1;
+ }
+ else {
+ found._dataEnd = pos1;
+ }
+ found._dataStart = found._dataEnd;
+ found._tokensize = count + found._dataEnd - pos;
+ found.parenthesiscount = 0;
+ found.head = interval_.par.substr(found._tokenstart, found._tokensize);
+ found.disabled = true;
+ }
+ }
+ else {
+ // Handle "\end{...}"
+ found._dataStart = pos + sub.str(2).length();
+ found._dataEnd = found._dataStart;
+ found._tokensize = count + found._dataEnd - pos;
+ found.parenthesiscount = 0;
+ found.head = interval_.par.substr(found._tokenstart, found._tokensize);
+ found.disabled = true;
+ }
+ }
+ }
+ else if (found.keytype != KeyInfo::isRegex) {
+ found._tokenstart = sub.position(size_t(2));
+ if (found.parenthesiscount == 0) {
+ // Probably to be discarded
+ size_t following_pos = sub.position(size_t(2)) + sub.str(5).length() + 1;
+ char following = interval_.par[following_pos];
+ if (following == ' ')
+ found.head = "\\" + sub.str(5) + " ";
+ else if (following == '=') {
+ // like \uldepth=1000pt
+ found.head = sub.str(2);
+ }
+ else
+ found.head = "\\" + key;
+ found._tokensize = found.head.length();
+ found._dataEnd = found._tokenstart + found._tokensize;
+ 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;
+ if (found.keytype == KeyInfo::isSectioning) {
+ // Remove optional values (but still keep in header)
+ interval_.addIntervall(params, optend);
+ }
+ }
+ string token = sub.str(7);
+ int closings;
+ if (interval_.par[optend] != '{') {
+ closings = 0;
+ found.parenthesiscount = 0;
+ found.head = "\\" + key;
+ }
+ else
+ closings = found.parenthesiscount;
+ if (found.parenthesiscount == 1) {
+ found.head = "\\" + key + "{";
+ }
+ else if (found.parenthesiscount > 1) {
+ if (token != "") {
+ found.head = sub.str(2) + "{";
+ closings = found.parenthesiscount - 1;
+ }
+ else {
+ found.head = "\\" + key + "{";
+ }
+ }
+ found._tokensize = found.head.length();
+ found._dataStart = found._tokenstart + found.head.length();
+ if (found.keytype == KeyInfo::doRemove) {
+ if (closings > 0) {
+ size_t endpar = 2 + interval_.findclosing(found._dataStart, interval_.par.length(), '{', '}', closings);
+ if (endpar >= interval_.par.length())
+ found._dataStart = interval_.par.length();
+ else
+ found._dataStart = endpar;
+ found._tokensize = found._dataStart - found._tokenstart;
+ }
+ else {
+ found._dataStart = found._tokenstart + found._tokensize;
+ }
+ closings = 0;
+ }
+ if (interval_.par.substr(found._dataStart, 15).compare("\\endarguments{}") == 0) {
+ found._dataStart += 15;
+ }
+ size_t endpos;
+ if (closings < 1)
+ endpos = found._dataStart - 1;
+ else
+ 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;
+ codeStart = found._dataStart;
+ }
+ else if (evaluatingCode) {
+ if (size_t(found._dataStart) > codeEnd)
+ evaluatingCode = false;
+ else if (found.keytype == KeyInfo::isMain) {
+ // Disable this key, treate it as standard
+ found.keytype = KeyInfo::isStandard;
+ found.disabled = true;
+ if ((codeEnd +1 >= 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 ((endpos == interval_.par.length()) &&
+ (found.keytype == KeyInfo::doRemove)) {
+ // Missing closing => error in latex-input?
+ // therefore do not delete remaining data
+ found._dataStart -= 1;
+ found._dataEnd = found._dataStart;
+ }
+ else
+ found._dataEnd = endpos;
+ }
+ if (isPatternString) {
+ keys[key].used = true;
+ }
+ }
+ entries_.push_back(found);
+ }
+}
+
+void LatexInfo::makeKey(const string &keysstring, KeyInfo keyI, bool isPatternString)
+{
+ stringstream s(keysstring);
+ string key;
+ const char delim = '|';
+ while (getline(s, key, delim)) {
+ KeyInfo keyII(keyI);
+ if (isPatternString) {
+ keyII.used = false;
+ }
+ else if ( !keys[key].used)
+ keyII.disabled = true;
+ keys[key] = keyII;
+ }
+}
+
+void LatexInfo::buildKeys(bool isPatternString)
+{
+
+ static bool keysBuilt = false;
+ if (keysBuilt && !isPatternString) return;
+
+ // Keys to ignore in any case
+ makeKey("text|textcyrillic|lyxmathsym|ensuremath", KeyInfo(KeyInfo::headRemove, 1, true), true);
+ // Known standard keys with 1 parameter.
+ // Split is done, if not at start of region
+ makeKey("textsf|textss|texttt", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getFamily()), isPatternString);
+ makeKey("textbf", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getSeries()), isPatternString);
+ makeKey("textit|textsc|textsl", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getShape()), isPatternString);
+ makeKey("uuline|uline|uwave", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getUnderline()), isPatternString);
+ makeKey("emph|noun", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getMarkUp()), isPatternString);
+ makeKey("sout|xout", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getStrikeOut()), isPatternString);
+
+ makeKey("section|subsection|subsubsection|paragraph|subparagraph|minisec",
+ KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
+ makeKey("section*|subsection*|subsubsection*|paragraph*",
+ KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
+ makeKey("part|part*|chapter|chapter*", KeyInfo(KeyInfo::isSectioning, 1, ignoreFormats.getSectioning()), isPatternString);
+ makeKey("title|subtitle|author|subject|publishers|dedication|uppertitleback|lowertitleback|extratitle|lyxaddress|lyxrightaddress", KeyInfo(KeyInfo::isTitle, 1, ignoreFormats.getFrontMatter()), isPatternString);
+ // Regex
+ makeKey("regexp", KeyInfo(KeyInfo::isRegex, 1, false), isPatternString);
+
+ // Split is done, if not at start of region
+ makeKey("textcolor", KeyInfo(KeyInfo::isStandard, 2, ignoreFormats.getColor()), isPatternString);
+ makeKey("latexenvironment", KeyInfo(KeyInfo::isStandard, 2, false), isPatternString);
+
+ // Split is done always.
+ makeKey("foreignlanguage", KeyInfo(KeyInfo::isMain, 2, ignoreFormats.getLanguage()), isPatternString);
+
+ // Known charaters
+ // No split
+ makeKey("backslash|textbackslash|slash", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textasciicircum|textasciitilde", 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);
+ makeKey("thickspace|medspace|thinspace", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Skip
+ // makeKey("enskip|smallskip|medskip|bigskip|vfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Custom space/skip, remove the content (== length value)
+ makeKey("vspace|vspace*|hspace|hspace*|mspace", KeyInfo(KeyInfo::noContent, 1, false), isPatternString);
+ // Found in fr/UserGuide.lyx
+ makeKey("og|fg", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // quotes
+ makeKey("textquotedbl|quotesinglbase|lyxarrow", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textquotedblleft|textquotedblright", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Known macros to remove (including their parameter)
+ // No split
+ makeKey("input|inputencoding|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);
+
+ // Ignore deleted text
+ makeKey("lyxdeleted", KeyInfo(KeyInfo::doRemove, 3, false), isPatternString);
+ // but preserve added text
+ makeKey("lyxadded", KeyInfo(KeyInfo::doRemove, 2, false), isPatternString);
+
+ // Macros to remove, but let the parameter survive
+ // No split
+ makeKey("menuitem|textmd|textrm", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
+
+ // Remove language spec from content of these insets
+ makeKey("code", KeyInfo(KeyInfo::noMain, 1, false), isPatternString);
+
+ // Same effect as previous, parameter will survive (because there is no one anyway)
+ // No split
+ makeKey("noindent|textcompwordmark|maketitle", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
+ // Remove table decorations
+ makeKey("hline|tabularnewline|toprule|bottomrule|midrule", KeyInfo(KeyInfo::doRemove, 0, true), isPatternString);
+ // Discard shape-header.
+ // For footnote or shortcut too, because of lang settings
+ // and wrong handling if used 'KeyInfo::noMain'
+ makeKey("circlepar|diamondpar|heartpar|nutpar", KeyInfo(KeyInfo::isStandard, 1, true), 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|vphantom|note|footnote|shortcut|include|includegraphics", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
+ makeKey("textgreek|textcyrillic", KeyInfo(KeyInfo::isStandard, 1, true), false);
+ makeKey("parbox", KeyInfo(KeyInfo::doRemove, 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|LyX|latex|LaTeX|latexe|LaTeXe|tex|TeX", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("tableofcontents", 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|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;
+ }
+ else {
+ // no need to rebuild again
+ keysBuilt = true;
+ }