]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathParser.cpp
InsetMathFrac: reimplement \cfrac with its optional argument the way Enrico proposed...
[lyx.git] / src / mathed / MathParser.cpp
index 56fdf23c81db936e223f1483e967ddcd9b8ebe40..757458cc88329a83cafe70db7ba35576578675b9 100644 (file)
@@ -3,7 +3,7 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -54,6 +54,7 @@ following hack as starting point to write some macros:
 #include "InsetMathRef.h"
 #include "InsetMathRoot.h"
 #include "InsetMathScript.h"
+#include "InsetMathSpace.h"
 #include "InsetMathSplit.h"
 #include "InsetMathSqrt.h"
 #include "InsetMathTabular.h"
@@ -100,11 +101,16 @@ bool stared(docstring const & s)
 }
 
 
-docstring escapeSpecialChars(docstring const & str)
+docstring escapeSpecialChars(docstring const & str, bool textmode)
 {
+       docstring const backslash = textmode ? from_ascii("\\textbackslash ")
+                                            : from_ascii("\\backslash ");
+       docstring const caret = textmode ? from_ascii("\\textasciicircum ")
+                                        : from_ascii("\\mathcircumflex ");
+
        return subst(subst(subst(subst(subst(subst(subst(subst(subst(str,
-                       from_ascii("\\"), from_ascii("\\backslash ")),
-                       from_ascii("^"), from_ascii("\\mathcircumflex ")),
+                       from_ascii("\\"), backslash),
+                       from_ascii("^"), caret),
                        from_ascii("_"), from_ascii("\\_")),
                        from_ascii("$"), from_ascii("\\$")),
                        from_ascii("#"), from_ascii("\\#")),
@@ -540,8 +546,9 @@ void Parser::tokenize(istream & is)
 
 void Parser::tokenize(docstring const & buffer)
 {
-       idocstringstream is(mode_ & Parse::VERBATIM ?
-               escapeSpecialChars(buffer) : buffer, ios::in | ios::binary);
+       idocstringstream is(mode_ & Parse::VERBATIM
+                       ? escapeSpecialChars(buffer, mode_ & Parse::TEXTMODE)
+                       : buffer, ios::in | ios::binary);
 
        char_type c;
        while (is.get(c)) {
@@ -647,10 +654,10 @@ bool Parser::parse(MathAtom & at)
                //      at.nucleus()->cell(0) = ar;
                //else
                //      lyxerr << "unusual contents found: " << ar << endl;
-               return false;
-       }
-       at = ar[0];
-       return true;
+               success_ = false;
+       } else
+               at = ar[0];
+       return success_;
 }
 
 
@@ -665,7 +672,7 @@ docstring Parser::parse_verbatim_option()
                                putback();
                                res += '{' + parse_verbatim_item() + '}';
                        } else
-                               res += t.asString();
+                               res += t.asInput();
                }
        }
        return res;
@@ -684,7 +691,7 @@ docstring Parser::parse_verbatim_item()
                                res += '{' + parse_verbatim_item() + '}';
                        }
                        else
-                               res += t.asString();
+                               res += t.asInput();
                }
        }
        return res;
@@ -900,8 +907,24 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        return success_;
                }
 
-               else if (t.cat() == catOther)
-                       cell->push_back(MathAtom(new InsetMathChar(t.character())));
+               else if (t.cat() == catOther) {
+                       char_type c = t.character();
+                       if (isAsciiOrMathAlpha(c)
+                           || mode_ & Parse::VERBATIM
+                           || !(mode_ & Parse::USETEXT)
+                           || mode == InsetMath::TEXT_MODE) {
+                               cell->push_back(MathAtom(new InsetMathChar(c)));
+                       } else {
+                               MathAtom at = createInsetMath("text");
+                               at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
+                               while (nextToken().cat() == catOther
+                                      && !isAsciiOrMathAlpha(nextToken().character())) {
+                                       c = getToken().character();
+                                       at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
+                               }
+                               cell->push_back(at);
+                       }
+               }
 
                else if (t.cat() == catComment) {
                        docstring s;
@@ -1119,11 +1142,19 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                }
 
                else if (t.cs() == "(") {
+                       if (mode == InsetMath::MATH_MODE) {
+                               error("bad math environment");
+                               break;
+                       }
                        cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
                        parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
                }
 
                else if (t.cs() == "[") {
+                       if (mode != InsetMath::UNDECIDED_MODE) {
+                               error("bad math environment");
+                               break;
+                       }
                        cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
                        parse2(cell->back(), FLAG_EQUATION, InsetMath::MATH_MODE, false);
                }
@@ -1273,6 +1304,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
                        }
                }
+
                else if (t.cs() == "unitfrac") {
                        // Here allowed formats are \unitfrac[val]{num}{denom}
                        MathData ar;
@@ -1287,6 +1319,24 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
                }
 
+               else if (t.cs() == "cfrac") {
+                       // allowed formats are \cfrac[pos]{num}{denom}
+                       docstring const arg = getArg('[', ']');
+                       //lyxerr << "got so far: '" << arg << "'" << endl;                              
+                               if (arg == "l")
+                                       cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRACLEFT)));
+                               else if (arg == "r")
+                                       cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRACRIGHT)));
+                               else if (arg.empty() || arg == "c")
+                                       cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRAC)));
+                               else {
+                                       error("found invalid optional argument");
+                                       break;
+                               }
+                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                       parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
+               }
+
                else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
                        cell->push_back(createInsetMath(t.cs()));
                        parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
@@ -1359,32 +1409,56 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
 
                        else if (name == "math") {
+                               if (mode == InsetMath::MATH_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullSimple)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, true);
                        }
 
                        else if (name == "equation" || name == "equation*"
                                        || name == "displaymath") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullEquation)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, (name == "equation"));
                        }
 
                        else if (name == "eqnarray" || name == "eqnarray*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullEqnArray)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
                        }
 
                        else if (name == "align" || name == "align*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullAlign)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
                        }
 
                        else if (name == "flalign" || name == "flalign*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullFlAlign)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
                        }
 
                        else if (name == "alignat" || name == "alignat*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                // ignore this for a while
                                getArg('{', '}');
                                cell->push_back(MathAtom(new InsetMathHull(hullAlignAt)));
@@ -1392,6 +1466,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
 
                        else if (name == "xalignat" || name == "xalignat*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                // ignore this for a while
                                getArg('{', '}');
                                cell->push_back(MathAtom(new InsetMathHull(hullXAlignAt)));
@@ -1399,6 +1477,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
 
                        else if (name == "xxalignat") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                // ignore this for a while
                                getArg('{', '}');
                                cell->push_back(MathAtom(new InsetMathHull(hullXXAlignAt)));
@@ -1406,11 +1488,19 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
 
                        else if (name == "multline" || name == "multline*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullMultline)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
                        }
 
                        else if (name == "gather" || name == "gather*") {
+                               if (mode != InsetMath::UNDECIDED_MODE) {
+                                       error("bad math environment");
+                                       break;
+                               }
                                cell->push_back(MathAtom(new InsetMathHull(hullGather)));
                                parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
                        }
@@ -1540,6 +1630,22 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
                }
 
+               else if (t.cs() == "hspace" && nextToken().character() != '*') {
+                       docstring const name = t.cs();
+                       docstring const arg = parse_verbatim_item();
+                       Length length;
+                       if (isValidLength(to_utf8(arg), &length))
+                               cell->push_back(MathAtom(new InsetMathSpace(length)));
+                       else {
+                               // Since the Length class cannot use length variables
+                               // we must not create an InsetMathSpace.
+                               cell->push_back(MathAtom(new MathMacro(name)));
+                               MathData ar;
+                               mathed_parse_cell(ar, '{' + arg + '}');
+                               cell->append(ar);
+                       }
+               }
+
 #if 0
                else if (t.cs() == "infer") {
                        MathData ar;
@@ -1588,17 +1694,18 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                return success_;
                        }
                        docstring rem;
-                       cmd = Encodings::fromLaTeXCommand(cmd, rem);
-                       for (size_t i = 0; i < cmd.size(); ++i)
-                               cell->push_back(MathAtom(new InsetMathChar(cmd[i])));
-                       if (rem.size()) {
-                               MathAtom at = createInsetMath(t.cs());
-                               cell->push_back(at);
-                               MathData ar;
-                               if (!mathed_parse_cell(ar, '{' + rem + '}', mode_))
-                                       success_ = false;;
-                               cell->append(ar);
-                       }
+                       do {
+                               cmd = Encodings::fromLaTeXCommand(cmd, rem);
+                               for (size_t i = 0; i < cmd.size(); ++i)
+                                       cell->push_back(MathAtom(new InsetMathChar(cmd[i])));
+                               if (rem.size()) {
+                                       char_type c = rem[0];
+                                       cell->push_back(MathAtom(new InsetMathChar(c)));
+                                       cmd = rem.substr(1);
+                                       rem.clear();
+                               } else
+                                       cmd.clear();
+                       } while (cmd.size());
                }
 
                else if (t.cs().size()) {