diff --git a/src/mathed/formulabase.C b/src/mathed/formulabase.C index 195273d58b..7154a6fd45 100644 --- a/src/mathed/formulabase.C +++ b/src/mathed/formulabase.C @@ -819,8 +819,12 @@ void mathDispatchCreation(BufferView * bv, string const & arg, bool display) // formula otherwise if (sel.find("\\newcommand") == string::npos) f = new InsetFormula(sel); - else + else { + string name; + if (!mathed_parse_macro(name, sel)) + return; f = new InsetFormulaMacro(sel); + } bv->getLyXText()->cutSelection(bv); openNewInset(bv, f); } diff --git a/src/mathed/formulamacro.C b/src/mathed/formulamacro.C index bd5d342a19..39b91c9cdc 100644 --- a/src/mathed/formulamacro.C +++ b/src/mathed/formulamacro.C @@ -47,16 +47,17 @@ InsetFormulaMacro::InsetFormulaMacro() } -InsetFormulaMacro::InsetFormulaMacro(string nm, int na) +InsetFormulaMacro::InsetFormulaMacro(string name, int nargs) { - setInsetName(nm); - MathMacroTable::create(nm, na, string()); + setInsetName(name); + MathMacroTable::create(name, nargs, string()); } InsetFormulaMacro::InsetFormulaMacro(string const & s) { - string name = mathed_parse_macro(s); + string name; + mathed_parse_macro(name, s); setInsetName(name); } @@ -106,7 +107,8 @@ int InsetFormulaMacro::docbook(Buffer const * buf, ostream & os) const void InsetFormulaMacro::read(Buffer const *, LyXLex & lex) { - string name = mathed_parse_macro(lex); + string name; + mathed_parse_macro(name, lex); setInsetName(name); //lyxerr << "metrics disabled"; metrics(); diff --git a/src/mathed/math_data.C b/src/mathed/math_data.C index faf37c415e..b9ecc2e79b 100644 --- a/src/mathed/math_data.C +++ b/src/mathed/math_data.C @@ -247,3 +247,24 @@ void MathArray::replace(ReplaceData & rep) for (const_iterator it = begin(); it != end(); ++it) it->nucleus()->replace(rep); } + + +bool MathArray::contains(MathArray const & ar) const +{ + for (size_type i = 0; i + ar.size() <= size(); ++i) { + const_iterator it = begin() + i; + const_iterator rt = ar.begin(); + const_iterator et = ar.end(); + for (const_iterator jt = it; rt != et; ++jt, ++rt) + if (!jt->nucleus()->match(rt->nucleus())) + break; + if (rt == et) + return true; + } + + for (const_iterator it = begin(); it != end(); ++it) + if (it->nucleus()->contains(ar)) + return true; + + return false; +} diff --git a/src/mathed/math_data.h b/src/mathed/math_data.h index 2e029e2aa1..a69342d531 100644 --- a/src/mathed/math_data.h +++ b/src/mathed/math_data.h @@ -115,7 +115,7 @@ public: /// looks for inclusion match starting at pos bool matchpart(MathArray const &, pos_type pos) const; /// looks for containment - const_iterator find(MathArray const &) const; + bool contains(MathArray const &) const; /// void replace(ReplaceData &); diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 6c79f76b9b..6f296da11e 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -60,6 +60,7 @@ class MathScriptInset; class MathStringInset; class MathSpaceInset; class MathSymbolInset; +class MathUnknownInset; class NormalStream; class OctaveStream; @@ -176,26 +177,27 @@ public: virtual int cellYOffset(idx_type) const { return 0; } /// identifies certain types of insets - virtual MathArrayInset * asArrayInset() { return 0; } - virtual MathBoxInset * asBoxInset() { return 0; } - virtual MathBoxInset const * asBoxInset() const { return 0; } - virtual MathCharInset const * asCharInset() const { return 0; } - virtual MathDelimInset * asDelimInset() { return 0; } - virtual MathDelimInset const * asDelimInset() const { return 0; } - virtual MathFuncInset * asFuncInset() { return 0; } - virtual MathFracInset * asFracInset() { return 0; } - virtual MathGridInset * asGridInset() { return 0; } - virtual MathHullInset * asHullInset() { return 0; } - virtual MathHullInset const * asHullInset() const { return 0; } - virtual MathMacroTemplate * asMacroTemplate() { return 0; } - virtual MathMatrixInset const * asMatrixInset() const { return 0; } - virtual MathNestInset * asNestInset() { return 0; } - virtual MathScriptInset * asScriptInset() { return 0; } - virtual MathScriptInset const * asScriptInset() const { return 0; } - virtual MathSpaceInset * asSpaceInset() { return 0; } - virtual MathStringInset * asStringInset() { return 0; } - virtual MathSymbolInset const * asSymbolInset() const { return 0; } - virtual UpdatableInset * asHyperActiveInset() const { return 0; } + virtual MathArrayInset * asArrayInset() { return 0; } + virtual MathBoxInset * asBoxInset() { return 0; } + virtual MathBoxInset const * asBoxInset() const { return 0; } + virtual MathCharInset const * asCharInset() const { return 0; } + virtual MathDelimInset * asDelimInset() { return 0; } + virtual MathDelimInset const * asDelimInset() const { return 0; } + virtual MathFuncInset * asFuncInset() { return 0; } + virtual MathFracInset * asFracInset() { return 0; } + virtual MathGridInset * asGridInset() { return 0; } + virtual MathHullInset * asHullInset() { return 0; } + virtual MathHullInset const * asHullInset() const { return 0; } + virtual MathMacroTemplate * asMacroTemplate() { return 0; } + virtual MathMatrixInset const * asMatrixInset() const { return 0; } + virtual MathNestInset * asNestInset() { return 0; } + virtual MathScriptInset * asScriptInset() { return 0; } + virtual MathScriptInset const * asScriptInset() const { return 0; } + virtual MathSpaceInset * asSpaceInset() { return 0; } + virtual MathStringInset * asStringInset() { return 0; } + virtual MathSymbolInset const * asSymbolInset() const { return 0; } + virtual MathUnknownInset const * asUnknownInset() const { return 0; } + virtual UpdatableInset * asHyperActiveInset() const { return 0; } /// identifies things that can get scripts virtual bool isScriptable() const { return false; } @@ -226,6 +228,8 @@ public: virtual bool match(MathInset *) const { return false; } /// replace things by other things virtual void replace(ReplaceData &) {} + /// do we contain a given subsequence? + virtual bool contains(MathArray const &) { return false; } /// write LaTeX and Lyx code virtual void write(WriteStream & os) const; diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index 6113621b43..59b974f523 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -169,3 +169,12 @@ void MathNestInset::replace(ReplaceData & rep) for (idx_type i = 0; i < nargs(); ++i) cell(i).replace(rep); } + + +bool MathNestInset::contains(MathArray const & ar) +{ + for (idx_type i = 0; i < nargs(); ++i) + if (cell(i).contains(ar)) + return true; + return false; +} diff --git a/src/mathed/math_nestinset.h b/src/mathed/math_nestinset.h index f194e1662f..8f7b93a266 100644 --- a/src/mathed/math_nestinset.h +++ b/src/mathed/math_nestinset.h @@ -70,6 +70,8 @@ public: bool match(MathInset *) const; /// replace in all cells void replace(ReplaceData &); + /// do we contain a given pattern? + bool contains(MathArray const &); /// debug helper void dump() const; diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index ca09a0d750..54711e8681 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -244,7 +244,7 @@ public: Parser(istream & is); /// - string parse_macro(); + bool parse_macro(string & name); /// bool parse_normal(MathAtom &); /// @@ -582,26 +582,26 @@ bool Parser::parse_lines(MathAtom & t, bool numbered, bool outmost) } -string Parser::parse_macro() +bool Parser::parse_macro(string & name) { - string name = "{error}"; + name = "{error}"; skipSpaces(); if (getToken().cs() != "newcommand") { lyxerr << "\\newcommand expected\n"; - return name; + return false; } if (getToken().cat() != catBegin) { lyxerr << "'{' in \\newcommand expected (1)\n"; - return name; + return false; } name = getToken().cs(); if (getToken().cat() != catEnd) { lyxerr << "'}' expected\n"; - return name; + return false; } string arg = getArg('[', ']'); @@ -609,13 +609,22 @@ string Parser::parse_macro() if (getToken().cat() != catBegin) { lyxerr << "'{' in \\newcommand expected (2)\n"; - return name; + return false; } MathArray ar; parse_into(ar, FLAG_BRACE_LAST); + + // we cannot handle recursive stuff at all + MathArray test; + test.push_back(createMathInset(name)); + if (ar.contains(test)) { + lyxerr << "we cannot handle recursive macros at all.\n"; + return false; + } + MathMacroTable::create(name, narg, ar); - return name; + return true; } @@ -1059,23 +1068,23 @@ void mathed_parse_cell(MathArray & ar, istream & is) -string mathed_parse_macro(string const & str) +bool mathed_parse_macro(string & name, string const & str) { istringstream is(str.c_str()); Parser parser(is); - return parser.parse_macro(); + return parser.parse_macro(name); } -string mathed_parse_macro(istream & is) +bool mathed_parse_macro(string & name, istream & is) { Parser parser(is); - return parser.parse_macro(); + return parser.parse_macro(name); } -string mathed_parse_macro(LyXLex & lex) +bool mathed_parse_macro(string & name, LyXLex & lex) { Parser parser(lex); - return parser.parse_macro(); + return parser.parse_macro(name); } diff --git a/src/mathed/math_parser.h b/src/mathed/math_parser.h index 05a936af89..45a7610b90 100644 --- a/src/mathed/math_parser.h +++ b/src/mathed/math_parser.h @@ -144,11 +144,11 @@ bool mathed_parse_normal(MathAtom &, std::istream &); bool mathed_parse_normal(MathAtom &, LyXLex &); /// parse a macro definition from a string, enter it into the macro table -string mathed_parse_macro(string const &); +bool mathed_parse_macro(string &, string const &); /// ... a stream -string mathed_parse_macro(std::istream &); +bool mathed_parse_macro(string &, std::istream &); /// ... the LyX lexxer -string mathed_parse_macro(LyXLex &); +bool mathed_parse_macro(string &, LyXLex &); /// parse a single cell from a string void mathed_parse_cell(MathArray & ar, string const &); diff --git a/src/mathed/math_unknowninset.C b/src/mathed/math_unknowninset.C index 275b30ec32..2739e45f19 100644 --- a/src/mathed/math_unknowninset.C +++ b/src/mathed/math_unknowninset.C @@ -38,6 +38,13 @@ void MathUnknownInset::setName(string const & n) } +bool MathUnknownInset::match(MathInset * p) const +{ + MathUnknownInset const * q = p->asUnknownInset(); + return q && name_ == q->name_; +} + + void MathUnknownInset::write(WriteStream & os) const { os << "\\" << name_ << ' '; @@ -46,7 +53,7 @@ void MathUnknownInset::write(WriteStream & os) const void MathUnknownInset::normalize(NormalStream & os) const { - os << "[func " << name_ << ']'; + os << "[unknown " << name_ << ']'; } diff --git a/src/mathed/math_unknowninset.h b/src/mathed/math_unknowninset.h index 05805ff89f..37bd4d6f98 100644 --- a/src/mathed/math_unknowninset.h +++ b/src/mathed/math_unknowninset.h @@ -28,6 +28,8 @@ public: MathUnknownInset const * asUnknownInset() const { return this; } /// void setName(string const &); + /// + bool match(MathInset * p) const; /// void normalize(NormalStream &) const;