#include "InsetMathArray.h"
#include "InsetMathBig.h"
#include "InsetMathBrace.h"
+#include "InsetMathCancelto.h"
#include "InsetMathChar.h"
#include "InsetMathColor.h"
#include "InsetMathComment.h"
#include "InsetMathEnv.h"
#include "InsetMathFrac.h"
#include "InsetMathKern.h"
-#include "MathMacro.h"
+#include "InsetMathMacro.h"
#include "InsetMathPar.h"
#include "InsetMathRef.h"
#include "InsetMathRoot.h"
#include "InsetMathScript.h"
+#include "InsetMathSideset.h"
#include "InsetMathSpace.h"
#include "InsetMathSplit.h"
#include "InsetMathSqrt.h"
+#include "InsetMathStackrel.h"
+#include "InsetMathString.h"
#include "InsetMathTabular.h"
-#include "MathMacroTemplate.h"
+#include "InsetMathMacroTemplate.h"
+#include "MathExtern.h"
#include "MathFactory.h"
-#include "MathMacroArgument.h"
+#include "InsetMathMacroArgument.h"
#include "MathSupport.h"
#include "Buffer.h"
+#include "BufferParams.h"
#include "Encoding.h"
#include "Lexer.h"
-#include "support/debug.h"
#include "support/convert.h"
+#include "support/debug.h"
#include "support/docstream.h"
+#include "support/unique_ptr.h"
#include <sstream>
/*!
- * Check wether the last row is empty and remove it if yes.
+ * Check whether the last row is empty and remove it if yes.
* Otherwise the following code
* \verbatim
\begin{array}{|c|c|}
* \endverbatim
* will result in a grid with 3 rows (+ the dummy row that is always present),
* because the last '\\' opens a new row.
+ * Do never delete a row that contains a multicolumn, even if all cells empty,
+ * since the multicolumn information would get lost otherwise.
+ * Note that this is only needed for inner-hull grid types, such as array
+ * or aligned, but not for outer-hull grid types, such as eqnarray or align.
*/
void delEmptyLastRow(InsetMathGrid & grid)
{
InsetMathGrid::row_type const row = grid.nrows() - 1;
for (InsetMathGrid::col_type col = 0; col < grid.ncols(); ++col) {
- if (!grid.cell(grid.index(row, col)).empty())
+ InsetMathGrid::idx_type const idx = grid.index(row, col);
+ if (!grid.cell(idx).empty() ||
+ grid.cellinfo(idx).multi_ != InsetMathGrid::CELL_NORMAL)
return;
}
// Copy the row information of the empty row (which would contain the
}
+/*!
+ * Tell whether the environment name corresponds to an inner-hull grid type.
+ */
+bool innerHull(docstring const & name)
+{
+ // For [bB]matrix, [vV]matrix, and pmatrix we can check the suffix only
+ return name == "array" || name == "cases" || name == "aligned"
+ || name == "alignedat" || name == "gathered" || name == "split"
+ || name == "subarray" || name == "tabular" || name == "matrix"
+ || name == "smallmatrix" || name.substr(1) == "matrix";
+}
+
+
// These are TeX's catcodes
enum CatCode {
catEscape, // 0 backslash
///
char_type character() const { return char_; }
///
- docstring asString() const { return cs_.size() ? cs_ : docstring(1, char_); }
+ docstring asString() const { return !cs_.empty() ? cs_ : docstring(1, char_); }
///
- docstring asInput() const { return cs_.size() ? '\\' + cs_ : docstring(1, char_); }
+ docstring asInput() const { return !cs_.empty() ? '\\' + cs_ : docstring(1, char_); }
private:
///
ostream & operator<<(ostream & os, Token const & t)
{
- if (t.cs().size()) {
+ if (!t.cs().empty()) {
docstring const & cs = t.cs();
// FIXME: For some strange reason, the stream operator instanciate
// a new Token before outputting the contents of t.cs().
bool parse1(InsetMathGrid & grid, unsigned flags, mode_type mode,
bool numbered);
///
- MathData parse(unsigned flags, mode_type mode);
- ///
int lineno() const { return lineno_; }
///
void putback();
+ /// store current position
+ void pushPosition();
+ /// restore previous position
+ void popPosition();
+ /// forget last saved position
+ void dropPosition();
private:
///
///
void push_back(Token const & t);
///
- void pop_back();
- ///
Token const & prevToken() const;
///
Token const & nextToken() const;
vector<Token> tokens_;
///
unsigned pos_;
+ ///
+ std::vector<unsigned> positions_;
/// Stack of active environments
vector<docstring> environments_;
///
: lineno_(lexer.lineNumber()), pos_(0), mode_(mode), success_(true),
buffer_(buf)
{
- if (buf)
- buf->updateMacros();
tokenize(lexer.getStream());
lexer.eatLine();
}
Parser::Parser(istream & is, parse_mode mode, Buffer * buf)
: lineno_(0), pos_(0), mode_(mode), success_(true), buffer_(buf)
{
- if (buf)
- buf->updateMacros();
tokenize(is);
}
Parser::Parser(docstring const & str, parse_mode mode, Buffer * buf)
: lineno_(0), pos_(0), mode_(mode), success_(true), buffer_(buf)
{
- if (buf)
- buf->updateMacros();
tokenize(str);
}
}
-void Parser::pop_back()
-{
- tokens_.pop_back();
-}
-
-
Token const & Parser::prevToken() const
{
static const Token dummy;
}
+void Parser::pushPosition()
+{
+ positions_.push_back(pos_);
+}
+
+
+void Parser::popPosition()
+{
+ pos_ = positions_.back();
+ positions_.pop_back();
+}
+
+
+void Parser::dropPosition()
+{
+ positions_.pop_back();
+}
+
+
bool Parser::good() const
{
return pos_ < tokens_.size();
{
if (!good()) {
error("The input stream is not well...");
- putback();
return 0;
}
return tokens_[pos_++].character();
docstring Parser::getArg(char_type left, char_type right)
{
+ docstring result;
skipSpaces();
- docstring result;
+ if (!good())
+ return result;
+
char_type c = getChar();
if (c != left)
if (!is) {
error("unexpected end of input");
} else {
+ if (c == '\n')
+ c = ' ';
docstring s(1, c);
if (catcode(c) == catLetter) {
// collect letters
bool Parser::parse(MathAtom & at)
{
skipSpaces();
- MathData ar;
+ MathData ar(buffer_);
parse(ar, false, InsetMath::UNDECIDED_MODE);
if (ar.size() != 1 || ar.front()->getType() == hullNone) {
if (!(mode_ & Parse::QUIET))
lyxerr << "unusual contents found: " << ar << endl;
- at = MathAtom(new InsetMathPar(ar));
+ at = MathAtom(new InsetMathPar(buffer_, ar));
//if (at->nargs() > 0)
// at.nucleus()->cell(0) = ar;
//else
docstring res;
if (nextToken().character() == '[') {
Token t = getToken();
- for (Token t = getToken(); t.character() != ']' && good(); t = getToken()) {
+ for (t = getToken(); t.character() != ']' && good(); t = getToken()) {
if (t.cat() == catBegin) {
putback();
res += '{' + parse_verbatim_item() + '}';
docstring res;
if (nextToken().cat() == catBegin) {
Token t = getToken();
- for (Token t = getToken(); t.cat() != catEnd && good(); t = getToken()) {
+ for (t = getToken(); t.cat() != catEnd && good(); t = getToken()) {
if (t.cat() == catBegin) {
putback();
res += '{' + parse_verbatim_item() + '}';
}
-MathData Parser::parse(unsigned flags, mode_type mode)
-{
- MathData ar;
- parse(ar, flags, mode);
- return ar;
-}
-
-
bool Parser::parse(MathData & array, unsigned flags, mode_type mode)
{
- InsetMathGrid grid(1, 1);
+ InsetMathGrid grid(buffer_, 1, 1);
parse1(grid, flags, mode, false);
array = grid.cell(0);
return success_;
InsetMathGrid::row_type cellrow = 0;
InsetMathGrid::col_type cellcol = 0;
MathData * cell = &grid.cell(grid.index(cellrow, cellcol));
+ Buffer * buf = buffer_;
if (grid.asHullInset())
grid.asHullInset()->numbered(cellrow, numbered);
Token const & n = getToken();
if (n.cat() == catMath) {
// TeX's $$...$$ syntax for displayed math
- cell->push_back(MathAtom(new InsetMathHull(hullEquation, buffer_)));
- parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
- getToken(); // skip the second '$' token
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation)));
+ parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
+ getToken(); // skip the second '$' token
+ } else {
+ // This is not an outer hull and display math is
+ // not allowed inside text mode environments.
+ error("bad math environment $$");
+ break;
+ }
} else {
// simple $...$ stuff
putback();
if (mode == InsetMath::UNDECIDED_MODE) {
- cell->push_back(MathAtom(new InsetMathHull(hullSimple, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple)));
parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false);
} else {
// Don't create nested math hulls (bug #5392)
- cell->push_back(MathAtom(new InsetMathEnsureMath));
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE, InsetMath::MATH_MODE);
}
}
}
else {
- error("something strange in the parser");
- break;
+ Token const & n = getToken();
+ if (n.cat() == catMath) {
+ error("something strange in the parser");
+ break;
+ } else {
+ // This is inline math ($...$), but the parser thinks we are
+ // already in math mode and latex would issue an error, unless we
+ // are inside a text mode user macro. We have no way to tell, so
+ // let's play safe by using \ensuremath, as it will work in any case.
+ putback();
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE, InsetMath::MATH_MODE);
+ }
}
}
}
else if (t.cat() == catParameter) {
- Token const & n = getToken();
- cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
+ Token const & n = nextToken();
+ char_type c = n.character();
+ if (c && '0' < c && c <= '9') {
+ cell->push_back(MathAtom(new InsetMathMacroArgument(c - '0')));
+ getToken();
+ } else
+ cell->push_back(MathAtom(new InsetMathHash()));
}
else if (t.cat() == catActive)
- cell->push_back(MathAtom(new InsetMathChar(t.character())));
+ cell->push_back(MathAtom(new InsetMathSpace(string(1, t.character()), "")));
else if (t.cat() == catBegin) {
MathData ar;
bool up = (t.cat() == catSuper);
// we need no new script inset if the last thing was a scriptinset,
// which has that script already not the same script already
- if (!cell->size())
- cell->push_back(MathAtom(new InsetMathScript(up)));
+ if (cell->empty())
+ cell->push_back(MathAtom(new InsetMathScript(buf, up)));
else if (cell->back()->asScriptInset() &&
!cell->back()->asScriptInset()->has(up))
cell->back().nucleus()->asScriptInset()->ensure(up);
else if (cell->back()->asScriptInset())
- cell->push_back(MathAtom(new InsetMathScript(up)));
+ cell->push_back(MathAtom(new InsetMathScript(buf, up)));
else
- cell->back() = MathAtom(new InsetMathScript(cell->back(), up));
+ cell->back() = MathAtom(new InsetMathScript(buf, cell->back(), up));
InsetMathScript * p = cell->back().nucleus()->asScriptInset();
// special handling of {}-bases
// Here we could remove the brace inset for things
// in an unreliable way. See this thread
// http://www.mail-archive.com/lyx-devel%40lists.lyx.org/msg104917.html
// for more details.
+ // However, we remove empty braces because they look
+ // ugly on screen and we are sure that they were added
+ // by the write() method (and will be re-added on save).
+ if (p->nuc().size() == 1 &&
+ p->nuc().back()->asBraceInset() &&
+ p->nuc().back()->asBraceInset()->cell(0).empty())
+ p->nuc().erase(0);
+
parse(p->cell(p->idxOfScript(up)), FLAG_ITEM, mode);
if (limits) {
p->limits(limits);
else if (t.cat() == catOther) {
char_type c = t.character();
- if (isAsciiOrMathAlpha(c)
+ if (!Encodings::isUnicodeTextOnly(c)
|| mode_ & Parse::VERBATIM
|| !(mode_ & Parse::USETEXT)
|| mode == InsetMath::TEXT_MODE) {
cell->push_back(MathAtom(new InsetMathChar(c)));
} else {
- MathAtom at = createInsetMath("text");
+ MathAtom at = createInsetMath("text", buf);
at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
while (nextToken().cat() == catOther
- && !isAsciiOrMathAlpha(nextToken().character())) {
+ && Encodings::isUnicodeTextOnly(nextToken().character())) {
c = getToken().character();
at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
}
else if (t.cat() == catComment) {
docstring s;
while (good()) {
- Token const & t = getToken();
- if (t.cat() == catNewline)
+ Token const & tt = getToken();
+ if (tt.cat() == catNewline)
break;
- s += t.asString();
+ s += tt.asInput();
}
- cell->push_back(MathAtom(new InsetMathComment(s)));
+ cell->push_back(MathAtom(new InsetMathComment(buf, s)));
skipSpaces();
}
//
else if (t.cs() == "lyxlock") {
- if (cell->size())
+ if (!cell->empty())
cell->back().nucleus()->lock(true);
}
t.cs() == "def") {
if (t.cs() == "global")
getToken();
-
+
// get name
docstring name = getToken().cs();
-
+
// read parameters
int nargs = 0;
docstring pars;
++nargs;
}
nargs /= 2;
-
+
// read definition
MathData def;
parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
+
// is a version for display attached?
skipSpaces();
MathData display;
if (nextToken().cat() == catBegin)
parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
-
- cell->push_back(MathAtom(new MathMacroTemplate(name,
- nargs, 0, MacroTypeDef, buffer_,
+
+ cell->push_back(MathAtom(new InsetMathMacroTemplate(buf,
+ name, nargs, 0, MacroTypeDef,
vector<MathData>(), def, display)));
+
+ if (buf && (mode_ & Parse::TRACKMACRO))
+ buf->usermacros.insert(name);
}
-
+
else if (t.cs() == "newcommand" ||
t.cs() == "renewcommand" ||
t.cs() == "newlyxcommand") {
error("'}' in \\newcommand expected");
return success_;
}
-
+
// get arity
docstring const arg = getArg('[', ']');
int nargs = 0;
if (!arg.empty())
nargs = convert<int>(arg);
-
+
// optional argument given?
skipSpaces();
int optionals = 0;
parse(optionalValues[optionals], FLAG_BRACK_LAST, mode);
++optionals;
}
-
+
MathData def;
parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
+
// is a version for display attached?
skipSpaces();
MathData display;
if (nextToken().cat() == catBegin)
parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
-
- cell->push_back(MathAtom(new MathMacroTemplate(name,
- nargs, optionals, MacroTypeNewcommand, buffer_,
+
+ cell->push_back(MathAtom(new InsetMathMacroTemplate(buf,
+ name, nargs, optionals, MacroTypeNewcommand,
optionalValues, def, display)));
+
+ if (buf && (mode_ & Parse::TRACKMACRO))
+ buf->usermacros.insert(name);
}
-
+
else if (t.cs() == "newcommandx" ||
t.cs() == "renewcommandx") {
// \newcommandx{\foo}[2][usedefault, addprefix=\global,1=default]{#1,#2}
}
} else
name = getToken().cs();
-
+
// get arity
docstring const arg = getArg('[', ']');
if (arg.empty()) {
return success_;
}
int nargs = convert<int>(arg);
-
+
// get options
int optionals = 0;
vector<MathData> optionalValues;
if (nextToken().character() == '[') {
// skip '['
getToken();
-
+
// handle 'opt=value' options, separated by ','.
skipSpaces();
while (nextToken().character() != ']' && good()) {
"for given optional parameter.");
return success_;
}
-
+
// skip '='
if (getToken().character() != '=') {
error("'=' and optional parameter value "
"expected for \\newcommandx");
return success_;
}
-
+
// get value
int optNum = max(size_t(n), optionalValues.size());
optionalValues.resize(optNum);
} else if (nextToken().cat() == catLetter) {
// we in fact ignore every non-optional
// parameter
-
+
// get option name
docstring opt;
while (nextToken().cat() == catLetter)
opt += getChar();
-
+
// value?
skipSpaces();
MathData value;
getToken();
while (nextToken().character() != ']'
&& nextToken().character() != ',')
- parse(value, FLAG_ITEM,
+ parse(value, FLAG_ITEM,
InsetMath::UNDECIDED_MODE);
}
} else {
error("option for \\newcommandx expected");
return success_;
}
-
+
// skip komma
skipSpaces();
if (nextToken().character() == ',') {
return success_;
}
}
-
+
// skip ']'
if (!good())
return success_;
if (nextToken().cat() == catBegin)
parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
- cell->push_back(MathAtom(new MathMacroTemplate(name,
- nargs, optionals, MacroTypeNewcommandx, buffer_,
+ cell->push_back(MathAtom(new InsetMathMacroTemplate(buf,
+ name, nargs, optionals, MacroTypeNewcommandx,
optionalValues, def, display)));
+
+ if (buf && (mode_ & Parse::TRACKMACRO))
+ buf->usermacros.insert(name);
}
else if (t.cs() == "(") {
- if (mode == InsetMath::MATH_MODE) {
- error("bad math environment");
- break;
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple)));
+ parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
+ } else {
+ // Don't create nested math hulls (bug #5392)
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE2, InsetMath::MATH_MODE);
}
- cell->push_back(MathAtom(new InsetMathHull(hullSimple, buffer_)));
- parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
}
else if (t.cs() == "[") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment [");
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullEquation, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation)));
parse2(cell->back(), FLAG_EQUATION, InsetMath::MATH_MODE, false);
}
// probably need to refine this test.
// Right now we only have to test for
// single line hull insets.
- if (grid.nrows() > 1)
+ if (grid.nrows() > 1 && innerHull(name))
delEmptyLastRow(grid);
return success_;
}
else if (t.cs() == "\\") {
if (flags & FLAG_ALIGN)
return success_;
- bool added = false;
+ bool starred = false;
+ docstring arg;
if (nextToken().asInput() == "*") {
getToken();
- added = addRow(grid, cellrow, docstring(), false);
- } else if (good())
- added = addRow(grid, cellrow, getArg('[', ']'));
- else
+ starred = true;
+ } else if (nextToken().asInput() == "[")
+ arg = getArg('[', ']');
+ else if (!good())
error("missing token after \\\\");
+ // skip "{}" added in front of "[" (the
+ // counterpart is in InsetMathGrid::eolString())
+ // skip spaces because formula could come from tex2lyx
+ bool skipBraces = false;
+ pushPosition();
+ if (nextToken().cat() == catBegin) {
+ getToken();
+ if (nextToken().cat() == catEnd) {
+ getToken();
+ pushPosition();
+ skipSpaces();
+ if (nextToken().asInput() == "[")
+ skipBraces = true;
+ popPosition();
+ }
+ }
+ if (skipBraces)
+ dropPosition();
+ else
+ popPosition();
+ bool const added = addRow(grid, cellrow, arg, !starred);
if (added) {
cellcol = 0;
if (grid.asHullInset())
}
}
-#if 0
- else if (t.cs() == "multicolumn") {
- // extract column count and insert dummy cells
+ else if (t.cs() == "multicolumn" && grid.handlesMulticolumn()) {
+ // if the columns are specified numerically,
+ // extract column count and insert dummy cells,
+ // otherwise parse it as an user macro
MathData count;
parse(count, FLAG_ITEM, mode);
- int cols = 1;
- if (!extractNumber(count, cols)) {
- success_ = false;
- lyxerr << " can't extract number of cells from " << count << endl;
- }
- // resize the table if necessary
- for (int i = 0; i < cols; ++i) {
- if (addCol(grid, cellcol)) {
- cell = &grid.cell(grid.index(
- cellrow, cellcol));
- // mark this as dummy
- grid.cellinfo(grid.index(
- cellrow, cellcol)).dummy_ = true;
+ int cols;
+ // limit arbitrarily to 100 columns
+ if (extractNumber(count, cols) && cols > 0 && cols < 100) {
+ // resize the table if necessary
+ size_t first = grid.index(cellrow, cellcol);
+ for (int i = 1; i < cols; ++i) {
+ if (addCol(grid, cellcol)) {
+ size_t const idx = grid.index(cellrow, cellcol);
+ grid.cellinfo(idx).multi_ =
+ InsetMathGrid::CELL_PART_OF_MULTICOLUMN;
+ }
}
- }
- // the last cell is the real thing, not a dummy
- grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = false;
-
- // read special alignment
- MathData align;
- parse(align, FLAG_ITEM, mode);
- //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align);
-
- // parse the remaining contents into the "real" cell
- parse(*cell, FLAG_ITEM, mode);
- }
-#endif
- else if (t.cs() == "limits")
- limits = 1;
+ // the first cell is the real thing, not a dummy
+ cell = &grid.cell(first);
+ grid.cellinfo(first).multi_ =
+ InsetMathGrid::CELL_BEGIN_OF_MULTICOLUMN;
- else if (t.cs() == "nolimits")
- limits = -1;
+ // read special alignment
+ MathData align;
+ parse(align, FLAG_ITEM, mode);
+ grid.cellinfo(first).align_ = asString(align);
- else if (t.cs() == "nonumber") {
- if (grid.asHullInset())
- grid.asHullInset()->numbered(cellrow, false);
+ // parse the remaining contents into the "real" cell
+ parse(*cell, FLAG_ITEM, mode);
+ } else {
+ MathAtom at = MathAtom(new InsetMathMacro(buf, t.cs()));
+ cell->push_back(at);
+ cell->push_back(MathAtom(new InsetMathBrace(count)));
+ }
}
- else if (t.cs() == "number") {
- if (grid.asHullInset())
- grid.asHullInset()->numbered(cellrow, true);
+ else if (t.cs() == "limits" || t.cs() == "nolimits") {
+ CatCode const cat = nextToken().cat();
+ if (cat == catSuper || cat == catSub)
+ limits = t.cs() == "limits" ? 1 : -1;
+ else {
+ MathAtom at = createInsetMath(t.cs(), buf);
+ cell->push_back(at);
+ }
}
+ // \notag is the same as \nonumber if amsmath is used
+ else if ((t.cs() == "nonumber" || t.cs() == "notag") &&
+ grid.asHullInset())
+ grid.asHullInset()->numbered(cellrow, false);
+
+ else if (t.cs() == "number" && grid.asHullInset())
+ grid.asHullInset()->numbered(cellrow, true);
+
else if (t.cs() == "hline") {
grid.rowinfo(cellrow).lines_ ++;
}
else if (t.cs() == "sqrt") {
MathData ar;
parse(ar, FLAG_OPTION, mode);
- if (ar.size()) {
- cell->push_back(MathAtom(new InsetMathRoot));
- cell->back().nucleus()->cell(0) = ar;
- parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
- } else {
- cell->push_back(MathAtom(new InsetMathSqrt));
+ if (!ar.empty()) {
+ cell->push_back(MathAtom(new InsetMathRoot(buf)));
+ cell->back().nucleus()->cell(1) = ar;
+ } else
+ cell->push_back(MathAtom(new InsetMathSqrt(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+
+ else if (t.cs() == "cancelto") {
+ MathData ar;
+ parse(ar, FLAG_ITEM, mode);
+ cell->push_back(MathAtom(new InsetMathCancelto(buf)));
+ cell->back().nucleus()->cell(1) = ar;
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
- }
}
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)));
+ if (!ar.empty()) {
+ cell->push_back(MathAtom(new InsetMathFrac(buf, 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)));
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNIT, 1)));
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
}
}
// 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)));
+ if (!ar.empty()) {
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNITFRAC, 3)));
cell->back().nucleus()->cell(2) = ar;
} else {
- cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::UNITFRAC)));
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNITFRAC)));
}
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
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;
+ //lyxerr << "got so far: '" << arg << "'" << endl;
if (arg == "l")
- cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRACLEFT)));
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRACLEFT)));
else if (arg == "r")
- cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRACRIGHT)));
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRACRIGHT)));
else if (arg.empty() || arg == "c")
- cell->push_back(MathAtom(new InsetMathFrac(InsetMathFrac::CFRAC)));
+ cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRAC)));
else {
error("found invalid optional argument");
break;
parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
}
+ else if (t.cs() == "sideset") {
+ // Here allowed formats are \sideset{_{bl}^{tl}}{_{br}^{tr}}{operator}
+ MathData ar[2];
+ InsetMathScript * script[2] = {0, 0};
+ for (int i = 0; i < 2; ++i) {
+ parse(ar[i], FLAG_ITEM, mode);
+ if (ar[i].size() == 1)
+ script[i] = ar[i][0].nucleus()->asScriptInset();
+ }
+ bool const hasscript[2] = {script[0] ? true : false, script[1] ? true : false};
+ cell->push_back(MathAtom(new InsetMathSideset(buf, hasscript[0], hasscript[1])));
+ if (hasscript[0]) {
+ if (script[0]->hasDown())
+ cell->back().nucleus()->cell(1) = script[0]->down();
+ if (script[0]->hasUp())
+ cell->back().nucleus()->cell(2) = script[0]->up();
+ } else
+ cell->back().nucleus()->cell(1) = ar[0];
+ if (hasscript[1]) {
+ if (script[1]->hasDown())
+ cell->back().nucleus()->cell(2 + hasscript[0]) = script[1]->down();
+ if (script[1]->hasUp())
+ cell->back().nucleus()->cell(3 + hasscript[0]) = script[1]->up();
+ } else
+ cell->back().nucleus()->cell(2 + hasscript[0]) = ar[1];
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+
+ else if (t.cs() == "stackrel") {
+ // Here allowed formats are \stackrel[subscript]{superscript}{operator}
+ MathData ar;
+ parse(ar, FLAG_OPTION, mode);
+ cell->push_back(MathAtom(new InsetMathStackrel(buf, !ar.empty())));
+ if (!ar.empty())
+ cell->back().nucleus()->cell(2) = ar;
+ parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+
else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
}
- else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == "prettyref"
- || t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") {
- cell->push_back(MathAtom(new InsetMathRef(t.cs())));
+ else if (t.cs() == "xhookrightarrow" || t.cs() == "xhookleftarrow" ||
+ t.cs() == "xRightarrow" || t.cs() == "xLeftarrow" ||
+ t.cs() == "xleftrightarrow" || t.cs() == "xLeftrightarrow" ||
+ t.cs() == "xrightharpoondown" || t.cs() == "xrightharpoonup" ||
+ t.cs() == "xleftharpoondown" || t.cs() == "xleftharpoonup" ||
+ t.cs() == "xleftrightharpoons" || t.cs() == "xrightleftharpoons" ||
+ t.cs() == "xmapsto") {
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
}
+ else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == "prettyref"
+ || t.cs() == "nameref" || t.cs() == "pageref"
+ || t.cs() == "vpageref" || t.cs() == "vref") {
+ cell->push_back(MathAtom(new InsetMathRef(buf, t.cs())));
+ docstring const opt = parse_verbatim_option();
+ docstring const ref = parse_verbatim_item();
+ if (!opt.empty()) {
+ cell->back().nucleus()->cell(1).push_back(
+ MathAtom(new InsetMathString(opt)));
+ }
+ cell->back().nucleus()->cell(0).push_back(
+ MathAtom(new InsetMathString(ref)));
+ }
+
else if (t.cs() == "left") {
skipSpaces();
Token const & tl = getToken();
skipSpaces();
Token const & tr = getToken();
docstring const r = tr.cs() == "|" ? from_ascii("Vert") : tr.asString();
- cell->push_back(MathAtom(new InsetMathDelim(l, r, ar)));
+ cell->push_back(MathAtom(new InsetMathDelim(buf, l, r, ar)));
}
else if (t.cs() == "right") {
else if (t.cs() == "begin") {
docstring const name = getArg('{', '}');
+
+ if (name.empty()) {
+ success_ = false;
+ error("found invalid environment");
+ return success_;
+ }
+
environments_.push_back(name);
if (name == "array" || name == "subarray") {
docstring const valign = parse_verbatim_option() + 'c';
docstring const halign = parse_verbatim_item();
- cell->push_back(MathAtom(new InsetMathArray(name,
+ cell->push_back(MathAtom(new InsetMathArray(buf, name,
InsetMathGrid::guessColumns(halign), 1, (char)valign[0], halign)));
- parse2(cell->back(), FLAG_END, mode, false);
+ parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, false);
}
else if (name == "tabular") {
docstring const valign = parse_verbatim_option() + 'c';
docstring const halign = parse_verbatim_item();
- cell->push_back(MathAtom(new InsetMathTabular(name,
+ cell->push_back(MathAtom(new InsetMathTabular(buf, name,
InsetMathGrid::guessColumns(halign), 1, (char)valign[0], halign)));
parse2(cell->back(), FLAG_END, InsetMath::TEXT_MODE, false);
}
else if (name == "split" || name == "cases") {
- cell->push_back(createInsetMath(name));
+ cell->push_back(createInsetMath(name, buf));
parse2(cell->back(), FLAG_END, mode, false);
}
docstring const valign = parse_verbatim_option() + 'c';
// ignore this for a while
getArg('{', '}');
- cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
+ cell->push_back(MathAtom(new InsetMathSplit(buf, name, (char)valign[0])));
parse2(cell->back(), FLAG_END, mode, false);
}
else if (name == "math") {
- if (mode == InsetMath::MATH_MODE) {
- error("bad math environment");
- break;
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple)));
+ parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, false);
+ } else {
+ // Don't create nested math hulls (bug #5392)
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_END, InsetMath::MATH_MODE);
}
- cell->push_back(MathAtom(new InsetMathHull(hullSimple, buffer_)));
- 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");
+ error("bad math environment " + name);
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullEquation, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, 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");
+ error("bad math environment " + name);
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullEqnArray, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, 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;
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullAlign)));
+ parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+ } else {
+ cell->push_back(MathAtom(new InsetMathSplit(buf, name,
+ 'c', !stared(name))));
+ parse2(cell->back(), FLAG_END, mode, !stared(name));
}
- cell->push_back(MathAtom(new InsetMathHull(hullAlign, buffer_)));
- 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");
+ error("bad math environment " + name);
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullFlAlign, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, 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");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
getArg('{', '}');
- cell->push_back(MathAtom(new InsetMathHull(hullAlignAt, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullAlignAt)));
parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
}
else if (name == "xalignat" || name == "xalignat*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
getArg('{', '}');
- cell->push_back(MathAtom(new InsetMathHull(hullXAlignAt, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullXAlignAt)));
parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
}
else if (name == "xxalignat") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
getArg('{', '}');
- cell->push_back(MathAtom(new InsetMathHull(hullXXAlignAt, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullXXAlignAt)));
parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
}
else if (name == "multline" || name == "multline*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullMultline, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, 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");
+ error("bad math environment " + name);
break;
}
- cell->push_back(MathAtom(new InsetMathHull(hullGather, buffer_)));
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullGather)));
parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
}
else if (latexkeys const * l = in_word_set(name)) {
if (l->inset == "matrix") {
- cell->push_back(createInsetMath(name));
+ cell->push_back(createInsetMath(name, buf));
parse2(cell->back(), FLAG_END, mode, false);
} else if (l->inset == "split") {
docstring const valign = parse_verbatim_option() + 'c';
- cell->push_back(MathAtom(new InsetMathSplit(name, (char)valign[0])));
+ cell->push_back(MathAtom(
+ new InsetMathSplit(buf, name, (char)valign[0])));
parse2(cell->back(), FLAG_END, mode, false);
} else {
success_ = false;
lyxerr << "found math environment `"
<< to_utf8(name)
<< "' in symbols file with unsupported inset `"
- << to_utf8(l->inset)
+ << l->inset
<< "'." << endl;
}
// create generic environment inset
- cell->push_back(MathAtom(new InsetMathEnv(name)));
+ cell->push_back(MathAtom(new InsetMathEnv(buf, name)));
parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
}
}
else {
success_ = false;
- if (!(mode_ & Parse::QUIET)) {
+ if (!(mode_ & Parse::QUIET) &&
+ !(mode_ & Parse::TRACKMACRO)) {
dump();
lyxerr << "found unknown math environment '"
<< to_utf8(name) << "'" << endl;
}
// create generic environment inset
- cell->push_back(MathAtom(new InsetMathEnv(name)));
+ cell->push_back(MathAtom(new InsetMathEnv(buf, name)));
parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
}
}
- else if (t.cs() == "kern") {
+ else if (t.cs() == "kern" || t.cs() == "mkern") {
// FIXME: A hack...
docstring s;
int num_tokens = 0;
while (true) {
- Token const & t = getToken();
+ Token const & tt = getToken();
++num_tokens;
if (!good()) {
s.clear();
putback();
break;
}
- s += t.character();
+ s += tt.character();
if (isValidLength(to_utf8(s)))
break;
}
if (s.empty())
- cell->push_back(MathAtom(new InsetMathKern));
+ cell->push_back(MathAtom(new InsetMathMacro(buf, t.cs())));
else
cell->push_back(MathAtom(new InsetMathKern(s)));
}
asArray(label, ar);
if (grid.asHullInset()) {
grid.asHullInset()->label(cellrow, label);
+ grid.asHullInset()->numbered(cellrow, true);
} else {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
cell->push_back(MathAtom(new InsetMathBrace(ar)));
}
}
else if (t.cs() == "choose" || t.cs() == "over"
|| t.cs() == "atop" || t.cs() == "brace"
|| t.cs() == "brack") {
- MathAtom at = createInsetMath(t.cs());
+ MathAtom at = createInsetMath(t.cs(), buf);
at.nucleus()->cell(0) = *cell;
cell->clear();
parse(at.nucleus()->cell(1), flags, mode);
else if (t.cs() == "color") {
docstring const color = parse_verbatim_item();
- cell->push_back(MathAtom(new InsetMathColor(true, color)));
+ cell->push_back(MathAtom(new InsetMathColor(buf, true, color)));
parse(cell->back().nucleus()->cell(0), flags, mode);
return success_;
}
else if (t.cs() == "textcolor") {
docstring const color = parse_verbatim_item();
- cell->push_back(MathAtom(new InsetMathColor(false, color)));
+ cell->push_back(MathAtom(new InsetMathColor(buf, false, color)));
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
}
else if (t.cs() == "normalcolor") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0), flags, mode);
return success_;
}
else if (t.cs() == "substack") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse2(cell->back(), FLAG_ITEM, mode, false);
+ // Delete empty last row if present
+ InsetMathGrid & subgrid =
+ *(cell->back().nucleus()->asGridInset());
+ if (subgrid.nrows() > 1)
+ delEmptyLastRow(subgrid);
}
else if (t.cs() == "xymatrix") {
odocstringstream os;
while (good() && nextToken().cat() != catBegin)
os << getToken().asInput();
- cell->push_back(createInsetMath(t.cs() + os.str()));
+ cell->push_back(createInsetMath(t.cs() + os.str(), buf));
+ parse2(cell->back(), FLAG_ITEM, mode, false);
+ // Delete empty last row if present
+ InsetMathGrid & subgrid =
+ *(cell->back().nucleus()->asGridInset());
+ if (subgrid.nrows() > 1)
+ delEmptyLastRow(subgrid);
+ }
+
+ else if (t.cs() == "Diagram") {
+ odocstringstream os;
+ while (good() && nextToken().cat() != catBegin)
+ os << getToken().asInput();
+ cell->push_back(createInsetMath(t.cs() + os.str(), buf));
parse2(cell->back(), FLAG_ITEM, mode, false);
}
else if (t.cs() == "framebox" || t.cs() == "makebox") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0), FLAG_OPTION, InsetMath::TEXT_MODE);
parse(cell->back().nucleus()->cell(1), FLAG_OPTION, InsetMath::TEXT_MODE);
parse(cell->back().nucleus()->cell(2), FLAG_ITEM, InsetMath::TEXT_MODE);
else if (t.cs() == "tag") {
if (nextToken().character() == '*') {
getToken();
- cell->push_back(createInsetMath(t.cs() + '*'));
+ cell->push_back(createInsetMath(t.cs() + '*', buf));
} else
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
}
- else if (t.cs() == "hspace" && nextToken().character() != '*') {
+ else if (t.cs() == "hspace") {
+ bool const prot = nextToken().character() == '*';
+ if (prot)
+ getToken();
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)));
+ if (prot && arg == "\\fill")
+ cell->push_back(MathAtom(new InsetMathSpace("hspace*{\\fill}", "")));
+ else if (isValidLength(to_utf8(arg), &length))
+ cell->push_back(MathAtom(new InsetMathSpace(length, prot)));
else {
// Since the Length class cannot use length variables
// we must not create an InsetMathSpace.
- cell->push_back(MathAtom(new MathMacro(name)));
+ cell->push_back(MathAtom(new InsetMathMacro(buf, name)));
MathData ar;
- mathed_parse_cell(ar, '{' + arg + '}',
- Parse::NORMAL, buffer_);
+ mathed_parse_cell(ar, '{' + arg + '}', mode_);
cell->append(ar);
}
}
+ else if (t.cs() == "smash") {
+ skipSpaces();
+ if (nextToken().asInput() == "[") {
+ // Since the phantom inset cannot handle optional arguments
+ // other than b and t, we must not create an InsetMathPhantom
+ // if opt is different from b and t (bug 8967).
+ docstring const opt = parse_verbatim_option();
+ if (opt == "t" || opt == "b") {
+ cell->push_back(createInsetMath(t.cs() + opt, buf));
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ } else {
+ docstring const arg = parse_verbatim_item();
+ cell->push_back(MathAtom(new InsetMathMacro(buf, t.cs())));
+ MathData ar;
+ mathed_parse_cell(ar, '[' + opt + ']', mode_);
+ cell->append(ar);
+ ar = MathData();
+ mathed_parse_cell(ar, '{' + arg + '}', mode_);
+ cell->append(ar);
+ }
+ }
+ else {
+ cell->push_back(createInsetMath(t.cs(), buf));
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+ }
+
#if 0
else if (t.cs() == "infer") {
MathData ar;
parse(ar, FLAG_OPTION, mode);
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse2(cell->back(), FLAG_ITEM, mode, false);
}
-
- // Disabled
- else if (1 && t.cs() == "ar") {
- auto_ptr<InsetMathXYArrow> p(new InsetMathXYArrow);
- // try to read target
- parse(p->cell(0), FLAG_OTPTION, mode);
- // try to read label
- if (nextToken().cat() == catSuper || nextToken().cat() == catSub) {
- p->up_ = nextToken().cat() == catSuper;
- getToken();
- parse(p->cell(1), FLAG_ITEM, mode);
- //lyxerr << "read label: " << p->cell(1) << endl;
- }
-
- cell->push_back(MathAtom(p.release()));
- //lyxerr << "read cell: " << cell << endl;
- }
#endif
else if (t.cs() == "lyxmathsym") {
error("'}' expected in \\" + t.cs());
return success_;
}
+ bool termination;
docstring rem;
do {
- cmd = Encodings::fromLaTeXCommand(cmd, rem);
+ cmd = Encodings::fromLaTeXCommand(cmd,
+ Encodings::MATH_CMD | Encodings::TEXT_CMD,
+ termination, rem);
for (size_t i = 0; i < cmd.size(); ++i)
cell->push_back(MathAtom(new InsetMathChar(cmd[i])));
- if (rem.size()) {
+ if (!rem.empty()) {
char_type c = rem[0];
cell->push_back(MathAtom(new InsetMathChar(c)));
cmd = rem.substr(1);
rem.clear();
} else
cmd.clear();
- } while (cmd.size());
+ } while (!cmd.empty());
}
- else if (t.cs().size()) {
- bool const is_user_macro =
- buffer_ && buffer_->getMacro(t.cs(), false);
+ else if (!t.cs().empty()) {
+ bool const no_mhchem =
+ (t.cs() == "ce" || t.cs() == "cf")
+ && buf && buf->params().use_package("mhchem") ==
+ BufferParams::package_off;
+
+ bool const is_user_macro = no_mhchem ||
+ (buf && (mode_ & Parse::TRACKMACRO
+ ? buf->usermacros.count(t.cs()) != 0
+ : buf->getMacro(t.cs(), false) != 0));
+
latexkeys const * l = in_word_set(t.cs());
if (l && !is_user_macro) {
if (l->inset == "big") {
cell->push_back(MathAtom(
new InsetMathBig(t.cs(), delim)));
else {
- cell->push_back(createInsetMath(t.cs()));
- putback();
+ cell->push_back(createInsetMath(t.cs(), buf));
+ // For some reason delim.empty()
+ // is always false here
+ if (delim.at(0))
+ putback();
}
}
else if (l->inset == "font") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0),
FLAG_ITEM, asMode(mode, l->extra));
}
else if (l->inset == "oldfont") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0),
flags | FLAG_ALIGN, asMode(mode, l->extra));
if (prevToken().cat() != catAlign &&
}
else if (l->inset == "style") {
- cell->push_back(createInsetMath(t.cs()));
+ cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(0),
flags | FLAG_ALIGN, mode);
if (prevToken().cat() != catAlign &&
putback();
}
+ else if (l->inset == "underset" || l->inset == "overset") {
+ cell->push_back(createInsetMath(t.cs(), buf));
+ parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+
else {
- MathAtom at = createInsetMath(t.cs());
+ MathAtom at = createInsetMath(t.cs(), buf);
for (InsetMath::idx_type i = 0; i < at->nargs(); ++i)
parse(at.nucleus()->cell(i),
FLAG_ITEM, asMode(mode, l->extra));
}
}
bool is_combining;
- char_type c =
- Encodings::fromLaTeXCommand(cmd, is_combining);
+ bool termination;
+ char_type c = Encodings::fromLaTeXCommand(cmd,
+ Encodings::MATH_CMD | Encodings::TEXT_CMD,
+ is_combining, termination);
if (is_combining) {
if (cat == catLetter)
cmd += '{';
++num_tokens;
if (cat == catLetter)
cmd += '}';
- c = Encodings::fromLaTeXCommand(cmd, is_combining);
+ c = Encodings::fromLaTeXCommand(cmd,
+ Encodings::MATH_CMD | Encodings::TEXT_CMD,
+ is_combining, termination);
}
- if (c) {
+ if (c && buf->params().encoding().encodable(c)) {
+ if (termination) {
+ if (nextToken().cat() == catBegin) {
+ getToken();
+ if (nextToken().cat() == catEnd) {
+ getToken();
+ num_tokens += 2;
+ } else
+ putback();
+ } else {
+ while (nextToken().cat() == catSpace) {
+ getToken();
+ ++num_tokens;
+ }
+ }
+ }
is_unicode_symbol = true;
cell->push_back(MathAtom(new InsetMathChar(c)));
} else {
}
if (!is_unicode_symbol) {
MathAtom at = is_user_macro ?
- MathAtom(new MathMacro(t.cs()))
- : createInsetMath(t.cs());
+ MathAtom(new InsetMathMacro(buf, t.cs()))
+ : createInsetMath(t.cs(), buf);
InsetMath::mode_type m = mode;
//if (m == InsetMath::UNDECIDED_MODE)
//lyxerr << "default creation: m1: " << m << endl;
// this fails on \bigg[...\bigg]
//MathData opt;
//parse(opt, FLAG_OPTION, InsetMath::VERBATIM_MODE);
- //if (opt.size()) {
+ //if (!opt.empty()) {
// start = 1;
// at.nucleus()->cell(0) = opt;
//}
for (InsetMath::idx_type i = start; i < at->nargs(); ++i) {
parse(at.nucleus()->cell(i), FLAG_ITEM, m);
- skipSpaces();
+ if (mode == InsetMath::MATH_MODE)
+ skipSpaces();
}
cell->push_back(at);
}
} // anonymous namespace
-bool mathed_parse_cell(MathData & ar, docstring const & str,
- Parse::flags f, Buffer * buf)
+// FIXME This will likely need some work.
+char const * latexkeys::MathMLtype() const
+{
+ if (extra == "mathord")
+ return "mi";
+ return "mo";
+}
+
+
+bool mathed_parse_cell(MathData & ar, docstring const & str, Parse::flags f)
{
- return Parser(str, f, buf).parse(ar, 0, f & Parse::TEXTMODE ?
+ return Parser(str, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ?
InsetMath::TEXT_MODE : InsetMath::MATH_MODE);
}
-bool mathed_parse_cell(MathData & ar, istream & is,
- Parse::flags f, Buffer * buf)
+bool mathed_parse_cell(MathData & ar, istream & is, Parse::flags f)
{
- return Parser(is, f, buf).parse(ar, 0, f & Parse::TEXTMODE ?
+ return Parser(is, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ?
InsetMath::TEXT_MODE : InsetMath::MATH_MODE);
}
-bool mathed_parse_normal(MathAtom & t, docstring const & str,
- Parse::flags f, Buffer * buf)
+bool mathed_parse_normal(Buffer * buf, MathAtom & t, docstring const & str,
+ Parse::flags f)
{
return Parser(str, f, buf).parse(t);
}
-bool mathed_parse_normal(MathAtom & t, Lexer & lex,
- Parse::flags f, Buffer * buf)
+bool mathed_parse_normal(Buffer * buf, MathAtom & t, Lexer & lex,
+ Parse::flags f)
{
return Parser(lex, f, buf).parse(t);
}
bool mathed_parse_normal(InsetMathGrid & grid, docstring const & str,
- Parse::flags f, Buffer * buf)
+ Parse::flags f)
{
- return Parser(str, f, buf).parse1(grid, 0, f & Parse::TEXTMODE ?
+ return Parser(str, f, &grid.buffer()).parse1(grid, 0, f & Parse::TEXTMODE ?
InsetMath::TEXT_MODE : InsetMath::MATH_MODE, false);
}