]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathParser.cpp
Change the interface to a paragraph's layout. We still store a LayoutPtr, but now...
[lyx.git] / src / mathed / MathParser.cpp
index 7044009806e03e86fc46400d5ab36e14c3297459..e14c925d6ef9e26867ddf932b4e6b6b182dcfbce 100644 (file)
@@ -47,6 +47,7 @@ following hack as starting point to write some macros:
 #include "InsetMathComment.h"
 #include "InsetMathDelim.h"
 #include "InsetMathEnv.h"
+#include "InsetMathFrac.h"
 #include "InsetMathKern.h"
 #include "MathMacro.h"
 #include "InsetMathPar.h"
@@ -62,27 +63,18 @@ following hack as starting point to write some macros:
 #include "MathSupport.h"
 
 #include "Lexer.h"
-#include "debug.h"
 
+#include "support/debug.h"
 #include "support/convert.h"
+#include "support/docstream.h"
 
 #include <sstream>
 
-
-namespace lyx {
-
-using std::endl;
-using std::fill;
-
-using std::string;
-using std::ios;
-using std::istream;
-using std::ostream;
-using std::vector;
-
-
 //#define FILEDEBUG
 
+using namespace std;
+
+namespace lyx {
 
 namespace {
 
@@ -110,7 +102,7 @@ bool stared(docstring const & s)
  * environments like "equation" that have a fixed number of rows.
  */
 bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow,
-           docstring const & vskip, bool allow_pagebreak = true)
+           docstring const & vskip, bool allow_newpage_ = true)
 {
        ++cellrow;
        if (cellrow == grid.nrows()) {
@@ -127,14 +119,14 @@ bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow,
                        lyxerr << "ignoring extra row";
                        if (!vskip.empty())
                                lyxerr << " with extra space " << to_utf8(vskip);
-                       if (!allow_pagebreak)
+                       if (!allow_newpage_)
                                lyxerr << " with no page break allowed";
                        lyxerr << '.' << endl;
                        return false;
                }
        }
        grid.vcrskip(Length(to_utf8(vskip)), cellrow - 1);
-       grid.rowinfo(cellrow - 1).allow_pagebreak_ = allow_pagebreak;
+       grid.rowinfo(cellrow - 1).allow_newpage_ = allow_newpage_;
        return true;
 }
 
@@ -149,7 +141,7 @@ bool addCol(InsetMathGrid & grid, InsetMathGrid::col_type & cellcol)
        ++cellcol;
        if (cellcol == grid.ncols()) {
                //lyxerr << "adding column " << cellcol << endl;
-               grid.addCol(cellcol - 1);
+               grid.addCol(cellcol);
                if (cellcol == grid.ncols()) {
                        // We can't add a column to this grid, so let's
                        // append the content of this cell to the previous
@@ -241,7 +233,7 @@ enum {
        FLAG_END        = 1 << 3,  //  next \\end ends the parsing process
        FLAG_BRACK_LAST = 1 << 4,  //  next closing bracket ends the parsing
        FLAG_TEXTMODE   = 1 << 5,  //  we are in a box
-       FLAG_ITEM       = 1 << 6,  //  read a (possibly braced token)
+       FLAG_ITEM       = 1 << 6,  //  read a (possibly braced) token
        FLAG_LEAVE      = 1 << 7,  //  leave the loop at the end
        FLAG_SIMPLE     = 1 << 8,  //  next $ leaves the loop
        FLAG_EQUATION   = 1 << 9,  //  next \] leaves the loop
@@ -315,7 +307,7 @@ public:
        ///
        Parser(Lexer & lex);
        /// Only use this for reading from .lyx file format, for the reason
-       /// see Parser::tokenize(std::istream &).
+       /// see Parser::tokenize(istream &).
        Parser(istream & is);
        ///
        Parser(docstring const & str);
@@ -462,8 +454,11 @@ bool Parser::good() const
 
 char_type Parser::getChar()
 {
-       if (!good())
+       if (!good()) {
                error("The input stream is not well...");
+               putback();
+               return 0;
+       }
        return tokens_[pos_++].character();
 }
 
@@ -899,12 +894,17 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
 
                else if (t.cs() == "def" ||
                        t.cs() == "newcommand" ||
-                       t.cs() == "renewcommand")
+                       t.cs() == "renewcommand" ||
+                       t.cs() == "newlyxcommand")
                {
-                       docstring const type = t.cs();
+                       MacroType type = MacroTypeNewcommand;
+                       if (t.cs() == "def")
+                               type = MacroTypeDef;
                        docstring name;
                        int nargs = 0;
-                       if (t.cs() == "def") {
+                       int optionals = 0;
+                       vector<MathData> optionalValues;
+                       if (type == MacroTypeDef) {
                                // get name
                                name = getToken().cs();
 
@@ -917,8 +917,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                nargs /= 2;
                                //lyxerr << "read \\def parameter list '" << pars << "'" << endl;
 
-                       } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
-
+                       } else {
                                if (getToken().cat() != catBegin) {
                                        error("'{' in \\newcommand expected (1) ");
                                        return;
@@ -935,27 +934,27 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                if (!arg.empty())
                                        nargs = convert<int>(arg);
 
+                               // optional argument given?
+                               skipSpaces();
+                               while (nextToken().character() == '[') {
+                                       getToken();
+                                       optionalValues.push_back(MathData());
+                                       parse(optionalValues[optionals], FLAG_BRACK_LAST, mode);
+                                       ++optionals;
+                               }
                        }
 
-                       MathData ar1;
-                       parse(ar1, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
-                       // we cannot handle recursive stuff at all
-                       //MathData test;
-                       //test.push_back(createInsetMath(name));
-                       //if (ar1.contains(test)) {
-                       //      error("we cannot handle recursive macros at all.");
-                       //      return;
-                       //}
+                       MathData def;
+                       parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
 
                        // is a version for display attached?
                        skipSpaces();
-                       MathData ar2;
+                       MathData display;
                        if (nextToken().cat() == catBegin)
-                               parse(ar2, FLAG_ITEM, InsetMath::MATH_MODE);
+                               parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
 
-                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type,
-                               ar1, ar2)));
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, optionals, type, 
+                                                                                                                                                                                                                optionalValues, def, display)));
                }
 
                else if (t.cs() == "(") {
@@ -1016,12 +1015,14 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                else if (t.cs() == "\\") {
                        if (flags & FLAG_ALIGN)
                                return;
-                       bool added;
+                       bool added = false;
                        if (nextToken().asInput() == "*") {
                                getToken();
                                added = addRow(grid, cellrow, docstring(), false);
-                       } else
+                       } else if (good())
                                added = addRow(grid, cellrow, getArg('[', ']'));
+                       else
+                               error("missing token after \\\\");
                        if (added) {
                                cellcol = 0;
                                if (grid.asHullInset())
@@ -1097,6 +1098,33 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
                }
 
+               else if (t.cs() == "unit") {
+                       // Allowed formats \unit[val]{unit}
+                       MathData ar;
+                       parse(ar, FLAG_OPTION, mode);
+                       if (ar.size()) {
+                               cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::UNIT)));
+                               cell->back().nucleus()->cell(0) = ar;
+                               parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
+                       } else {
+                               cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::UNIT, 1)));
+                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                       }
+               }
+               else if (t.cs() == "unitfrac") {
+                       // Here allowed formats are \unitfrac[val]{num}{denom}
+                       MathData ar;
+                       parse(ar, FLAG_OPTION, mode);
+                       if (ar.size()) {
+                               cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::UNITFRAC, 3)));
+                               cell->back().nucleus()->cell(2) = ar;
+                       } else {
+                               cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::UNITFRAC)));
+                       }
+                       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);
@@ -1238,7 +1266,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                               << to_utf8(l->inset) << "'." << endl;
                                        // create generic environment inset
                                        cell->push_back(MathAtom(new InsetMathEnv(name)));
-                                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                                       parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                                }
                        }
 
@@ -1248,7 +1276,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                        << "'" << endl;
                                // create generic environment inset
                                cell->push_back(MathAtom(new InsetMathEnv(name)));
-                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                               parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                        }
                }