]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathMacroTemplate.cpp
* src/frontends/GuiDocument.{cpp,h}:
[lyx.git] / src / mathed / MathMacroTemplate.cpp
index 8f0ab385e3cf21dbab723f22be450014ec4b458e..b7ecb9bbc535511fec76a8662dddf88af316d60b 100644 (file)
@@ -13,6 +13,7 @@
 #include "MathMacroTemplate.h"
 
 #include "DocIterator.h"
+#include "LaTeXFeatures.h"
 #include "InsetMathBrace.h"
 #include "InsetMathChar.h"
 #include "InsetMathSqrt.h"
@@ -57,16 +58,16 @@ using support::bformat;
 class InsetLabelBox : public InsetMathNest {
 public:
        ///
-       InsetLabelBox(MathAtom const & atom, docstring label, 
-                                                               MathMacroTemplate const & parent, bool frame = false);
-       InsetLabelBox(docstring label, MathMacroTemplate const & parent, 
-                                                               bool frame = false);
+       InsetLabelBox(MathAtom const & atom, docstring label,
+                     MathMacroTemplate const & parent, bool frame = false);
+       InsetLabelBox(docstring label, MathMacroTemplate const & parent,
+                     bool frame = false);
        ///
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
        void draw(PainterInfo &, int x, int y) const;
-       
-private:
+
+protected:
        ///
        MathMacroTemplate const & parent_;
        ///
@@ -75,36 +76,34 @@ private:
        docstring const label_;
        ///
        bool frame_;
-       ///
-       mutable Dimension cellDim_;
 };
 
 
-InsetLabelBox::InsetLabelBox(MathAtom const & atom, docstring label, 
-                                                                                                                MathMacroTemplate const & parent, bool frame)
+InsetLabelBox::InsetLabelBox(MathAtom const & atom, docstring label,
+                            MathMacroTemplate const & parent, bool frame)
 :      InsetMathNest(1), parent_(parent), label_(label), frame_(frame)
 {
        cell(0).insert(0, atom);
 }
 
+
 InsetLabelBox::InsetLabelBox(docstring label,
-                                                                                                                MathMacroTemplate const & parent, bool frame)
+                            MathMacroTemplate const & parent, bool frame)
 :      InsetMathNest(1), parent_(parent), label_(label), frame_(frame)
 {
 }
-       
 
-Inset * InsetLabelBox::clone() const 
+
+Inset * InsetLabelBox::clone() const
 {
        return new InsetLabelBox(*this);
 }
 
 
-void InsetLabelBox::metrics(MetricsInfo & mi, Dimension & dim) const 
+void InsetLabelBox::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        // kernel
        cell(0).metrics(mi, dim);
-       cellDim_ = dim;
 
        // frame
        if (frame_) {
@@ -112,73 +111,132 @@ void InsetLabelBox::metrics(MetricsInfo & mi, Dimension & dim) const
                dim.asc += 5;
                dim.des += 5;
        }
-               
+
        // adjust to common height in main metrics phase
        if (!parent_.premetrics()) {
                dim.asc = max(dim.asc, parent_.commonLabelBoxAscent());
                dim.des = max(dim.des, parent_.commonLabelBoxDescent());
        }
-       
+
        // label
-       if (label_.length() > 0) {
+       if (parent_.editing(mi.base.bv) && label_.length() > 0) {
                // grey
                FontInfo font = sane_font;
                font.setSize(FONT_SIZE_TINY);
                font.setColor(Color_mathmacrolabel);
-               
+
                // make space for label and box
                int lwid = mathed_string_width(font, label_);
                int maxasc;
                int maxdes;
-               math_font_max_dim(font, maxasc, maxdes);                
-               
+               math_font_max_dim(font, maxasc, maxdes);
+
                dim.wid = max(dim.wid, lwid + 2);
 
                // space for the label
                if (!parent_.premetrics())
                        dim.des += maxasc + maxdes + 1;
        }
-
-       setDimCache(mi, dim);
 }
 
 
-void InsetLabelBox::draw(PainterInfo & pi, int x, int y) const 
+void InsetLabelBox::draw(PainterInfo & pi, int x, int y) const
 {
        Dimension const dim = dimension(*pi.base.bv);
-       
+       Dimension const cdim = cell(0).dimension(*pi.base.bv);
+
        // kernel
-       cell(0).draw(pi, x + (dim.wid - cellDim_.wid) / 2, y);
-       
+       cell(0).draw(pi, x + (dim.wid - cdim.wid) / 2, y);
+
        // label
-       if (label_.length() > 0) {
+       if (parent_.editing(pi.base.bv) && label_.length() > 0) {
                // grey
                FontInfo font = sane_font;
                font.setSize(FONT_SIZE_TINY);
                font.setColor(Color_mathmacrolabel);
-               
+
                // make space for label and box
                int lwid = mathed_string_width(font, label_);
                int maxasc;
                int maxdes;
                math_font_max_dim(font, maxasc, maxdes);
-               
+
                if (lwid < dim.wid)
                        pi.pain.text(x + (dim.wid - lwid) / 2, y + dim.des - maxdes, label_, font);
                else
                        pi.pain.text(x, y + dim.des - maxdes, label_, font);
        }
-       
+
        // draw frame
        int boxHeight = parent_.commonLabelBoxAscent() + parent_.commonLabelBoxDescent();
        if (frame_) {
-               pi.pain.rectangle(x + 1, y - dim.ascent() + 1, 
-                                                                                       dim.wid - 2, boxHeight - 2, 
-                                                                                       Color_mathline);
+               pi.pain.rectangle(x + 1, y - dim.ascent() + 1,
+                                 dim.wid - 2, boxHeight - 2,
+                                 Color_mathline);
        }
 }
 
-       
+
+//////////////////////////////////////////////////////////////////////
+
+class DisplayLabelBox : public InsetLabelBox {
+public:
+       ///
+       DisplayLabelBox(MathAtom const & atom, docstring label,
+                       MathMacroTemplate const & parent);
+
+       ///
+       void metrics(MetricsInfo & mi, Dimension & dim) const;
+       ///
+       void draw(PainterInfo &, int x, int y) const;
+
+protected:
+       ///
+       Inset * clone() const;
+};
+
+
+DisplayLabelBox::DisplayLabelBox(MathAtom const & atom,
+                                docstring label,
+                                MathMacroTemplate const & parent)
+       : InsetLabelBox(atom, label, parent, true)
+{
+}
+
+
+
+Inset * DisplayLabelBox::clone() const
+{
+       return new DisplayLabelBox(*this);
+}
+
+
+void DisplayLabelBox::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       InsetLabelBox::metrics(mi, dim);
+       if (!parent_.editing(mi.base.bv)
+           && parent_.cell(parent_.displayIdx()).empty()) {
+               dim.wid = 0;
+               dim.asc = 0;
+               dim.des = 0;
+       }
+}
+
+
+void DisplayLabelBox::draw(PainterInfo & pi, int x, int y) const
+{
+       if (parent_.editing(pi.base.bv)
+           || !parent_.cell(parent_.displayIdx()).empty()) {
+               InsetLabelBox::draw(pi, x, y);
+       } else {
+               bool enabled = pi.pain.isDrawingEnabled();
+               pi.pain.setDrawingEnabled(false);
+               InsetLabelBox::draw(pi, x, y);
+               pi.pain.setDrawingEnabled(enabled);
+       }
+}
+
+
 //////////////////////////////////////////////////////////////////////
 
 class InsetMathWrapper : public InsetMath {
@@ -189,7 +247,7 @@ public:
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
        void draw(PainterInfo &, int x, int y) const;
-       
+
 private:
        ///
        Inset * clone() const;
@@ -198,20 +256,20 @@ private:
 };
 
 
-Inset * InsetMathWrapper::clone() const 
+Inset * InsetMathWrapper::clone() const
 {
        return new InsetMathWrapper(*this);
 }
 
 
-void InsetMathWrapper::metrics(MetricsInfo & mi, Dimension & dim) const 
+void InsetMathWrapper::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        value_->metrics(mi, dim);
        //metricsMarkers2(dim);
 }
 
 
-void InsetMathWrapper::draw(PainterInfo & pi, int x, int y) const 
+void InsetMathWrapper::draw(PainterInfo & pi, int x, int y) const
 {
        value_->draw(pi, x, y);
        //drawMarkers(pi, x, y);
@@ -228,7 +286,7 @@ public:
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
        void draw(PainterInfo &, int x, int y) const;
-       
+
 private:
        ///
        MathMacroTemplate const & parent_;
@@ -237,72 +295,72 @@ private:
 };
 
 
-InsetNameWrapper::InsetNameWrapper(MathData const * value, 
-                                                                                                                                        MathMacroTemplate const & parent)
-       :       InsetMathWrapper(value), parent_(parent)
+InsetNameWrapper::InsetNameWrapper(MathData const * value,
+                                  MathMacroTemplate const & parent)
+       : InsetMathWrapper(value), parent_(parent)
 {
 }
 
 
-Inset * InsetNameWrapper::clone() const 
+Inset * InsetNameWrapper::clone() const
 {
        return new InsetNameWrapper(*this);
 }
 
 
-void InsetNameWrapper::metrics(MetricsInfo & mi, Dimension & dim) const 
+void InsetNameWrapper::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        InsetMathWrapper::metrics(mi, dim);
        dim.wid += mathed_string_width(mi.base.font, from_ascii("\\"));
 }
 
 
-void InsetNameWrapper::draw(PainterInfo & pi, int x, int y) const 
+void InsetNameWrapper::draw(PainterInfo & pi, int x, int y) const
 {
        // create fonts
        PainterInfo namepi = pi;
        if (parent_.validMacro())
                namepi.base.font.setColor(Color_latex);
        else
-               namepi.base.font.setColor(Color_error);         
-       
+               namepi.base.font.setColor(Color_error);
+
        // draw backslash
        pi.pain.text(x, y, from_ascii("\\"), namepi.base.font);
        x += mathed_string_width(namepi.base.font, from_ascii("\\"));
-       
+
        // draw name
        InsetMathWrapper::draw(namepi, x, y);
 }
 
-       
+
 ///////////////////////////////////////////////////////////////////////
-       
-       
+
+
 MathMacroTemplate::MathMacroTemplate()
-       : InsetMathNest(3), numargs_(0), optionals_(0), 
-         type_(MacroTypeNewcommand), editing_(false), lookOutdated_(true)
+       : InsetMathNest(3), numargs_(0), optionals_(0),
+         type_(MacroTypeNewcommand), lookOutdated_(true)
 {
        initMath();
 }
 
 
 MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
-       int optionals, MacroType type, 
-       vector<MathData> const & optionalValues, 
+       int optionals, MacroType type,
+       vector<MathData> const & optionalValues,
        MathData const & def, MathData const & display)
-       : InsetMathNest(optionals + 3), numargs_(numargs), 
+       : InsetMathNest(optionals + 3), numargs_(numargs),
          optionals_(optionals), optionalValues_(optionalValues),
-         type_(type), editing_(false), lookOutdated_(true)
+         type_(type), lookOutdated_(true)
 {
        initMath();
 
        if (numargs_ > 9)
                lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
                        << numargs_ << endl;
-       
+
        asArray(name, cell(0));
        optionalValues_.resize(9);
-       for (int i = 0; i < optionals_; ++i) 
+       for (int i = 0; i < optionals_; ++i)
                cell(optIdx(i)) = optionalValues_[i];
        cell(defIdx()) = def;
        cell(displayIdx()) = display;
@@ -313,7 +371,7 @@ MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
 
 MathMacroTemplate::MathMacroTemplate(docstring const & str)
        : InsetMathNest(3), numargs_(0), optionals_(0),
-       type_(MacroTypeNewcommand), editing_(false), lookOutdated_(true)
+       type_(MacroTypeNewcommand), lookOutdated_(true)
 {
        initMath();
 
@@ -335,7 +393,11 @@ MathMacroTemplate::MathMacroTemplate(docstring const & str)
 
 Inset * MathMacroTemplate::clone() const
 {
-       return new MathMacroTemplate(*this);
+       MathMacroTemplate * inset = new MathMacroTemplate(*this);
+       // the parent pointers of the proxy insets above will point to
+       // to the old template. Hence, the look must be updated.
+       inset->updateLook();
+       return inset;
 }
 
 
@@ -350,76 +412,63 @@ void MathMacroTemplate::updateToContext(MacroContext const & mc) const
        redefinition_ = mc.get(name()) != 0;
 }
 
-       
+
 void MathMacroTemplate::updateLook() const
 {
        lookOutdated_ = true;
 }
 
+
 void MathMacroTemplate::createLook() const
 {
        look_.clear();
 
        // \foo
-       look_.push_back(MathAtom(new InsetLabelBox(
-                editing_ ? _("name") : docstring(),
-                *this,
-                false)));
+       look_.push_back(MathAtom(new InsetLabelBox(_("Name"), *this, false)));
        MathData & nameData = look_[look_.size() - 1].nucleus()->cell(0);
        nameData.push_back(MathAtom(new InsetNameWrapper(&cell(0), *this)));
-       
+
        // [#1][#2]
        int i = 0;
        if (optionals_ > 0) {
-               look_.push_back(MathAtom(new InsetLabelBox(
-                       editing_ ? _("optional") : docstring(),
-                       *this,
-                       false)));
+               look_.push_back(MathAtom(new InsetLabelBox(_("optional"), *this, false)));
                MathData & optData = look_[look_.size() - 1].nucleus()->cell(0);
-       
+
                for (; i < optionals_; ++i) {
                        optData.push_back(MathAtom(new InsetMathChar('[')));
                        optData.push_back(MathAtom(new InsetMathWrapper(&cell(1 + i))));
                        optData.push_back(MathAtom(new InsetMathChar(']')));
                }
        }
-       
+
        // {#3}{#4}
        for (; i < numargs_; ++i) {
                MathData arg;
                arg.push_back(MathAtom(new MathMacroArgument(i + 1)));
                look_.push_back(MathAtom(new InsetMathBrace(arg)));
        }
-       
+
        // :=
        look_.push_back(MathAtom(new InsetMathChar(':')));
        look_.push_back(MathAtom(new InsetMathChar('=')));
 
        // definition
-       look_.push_back(
-               MathAtom(new InsetLabelBox(
-                               MathAtom(new InsetMathWrapper(&cell(defIdx()))),
-                               editing_ ? from_ascii("TeX") : docstring(),
-                               *this,
-                               true)));
+       look_.push_back(MathAtom(
+               new InsetLabelBox(MathAtom(
+                       new InsetMathWrapper(&cell(defIdx()))), _("TeX"), *this,        true)));
 
        // display
-       if (editing_ || !cell(displayIdx()).empty()) {
-               look_.push_back(
-                       MathAtom(new InsetLabelBox(
-                               MathAtom(new InsetMathWrapper(&cell(displayIdx()))),
-                                       editing_ ? from_ascii("LyX") : docstring(),
-                                       *this,
-                                       true)));
-       }
+       look_.push_back(MathAtom(
+               new DisplayLabelBox(MathAtom(
+                       new InsetMathWrapper(&cell(displayIdx()))), _("LyX"), *this)));
 }
-       
+
 
 void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        FontSetChanger dummy1(mi.base, from_ascii("mathnormal"));
        StyleChanger dummy2(mi.base, LM_ST_TEXT);
-       
+
        // valid macro?
        MacroData const * macro = 0;
        if (validName()) {
@@ -428,47 +477,34 @@ void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
                // updateToContext() - avoids another lookup
                redefinition_ = macro != 0;
        }
-       
-       // new edit mode?
-       bool realEditing = editing(mi.base.bv);
-       if (editing_ != realEditing) {
-               editing_ = realEditing;
-               lookOutdated_ = true;
-       }
-       
+
        // update look?
        if (lookOutdated_) {
                lookOutdated_ = false;
                createLook();
        }
-       
+
        /// metrics for inset contents
        if (macro)
-               macro->lock();          
-       
+               macro->lock();
+
        // first phase, premetric:
        premetrics_ = true;
        look_.metrics(mi, dim);
        labelBoxAscent_ = dim.asc;
        labelBoxDescent_ = dim.des;
-       
+
        // second phase, main metric:
        premetrics_ = false;
        look_.metrics(mi, dim);
-               
-       // metrics for invisible display box
-       if (!editing_ && cell(displayIdx()).empty()) {
-               Dimension ddim;
-               cell(displayIdx()).metrics(mi, ddim);
-       }
-       
+
        if (macro)
                macro->unlock();
-       
+
        dim.wid += 6;
        dim.des += 2;
        dim.asc += 2;
-       
+
        setDimCache(mi, dim);
 }
 
@@ -477,7 +513,7 @@ void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const
 {
        FontSetChanger dummy1(pi.base, from_ascii("mathnormal"));
        StyleChanger dummy2(pi.base, LM_ST_TEXT);
-       
+
        setPosCache(pi, x, y);
        Dimension const dim = dimension(*pi.base.bv);
 
@@ -485,62 +521,51 @@ void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const
        int const a = y - dim.asc + 1;
        int const w = dim.wid - 2;
        int const h = dim.height() - 2;
-       pi.pain.rectangle(x, a, w, h, Color_mathframe); 
-       
+       pi.pain.rectangle(x, a, w, h, Color_mathframe);
+
        // just to be sure: set some dummy values for coord cache
        for (idx_type i = 0; i < nargs(); ++i) {
                cell(i).setXY(*pi.base.bv, x, y);
        }
-       
+
        // draw contents
        look_.draw(pi, x + 3, y);
 }
 
-       
+
 void MathMacroTemplate::edit(Cursor & cur, bool left)
 {
        updateLook();
        cur.updateFlags(Update::Force);
        InsetMathNest::edit(cur, left);
 }
-       
-       
-Inset * MathMacroTemplate::editXY(Cursor & cur, int x, int y)
-{
-       Inset * ret = InsetMathNest::editXY(cur, x, y);
-/*     if (!editing_ && editing(cur.bv())) {
-               
-               cur.updateFlags(Update::Force);
-       }*/
-       return ret;
-}
-       
-       
+
+
 bool MathMacroTemplate::notifyCursorLeaves(Cursor & cur)
 {
        updateLook();
        cur.updateFlags(Update::Force);
        return InsetMathNest::notifyCursorLeaves(cur);
 }
-       
+
 
 void MathMacroTemplate::removeArguments(Cursor & cur, int from, int to) {
        for (DocIterator it = doc_iterator_begin(*this); it; it.forwardChar()) {
                if (!it.nextInset())
-                                               continue;
+                       continue;
                if (it.nextInset()->lyxCode() != MATHMACROARG_CODE)
-                                               continue;
+                       continue;
                MathMacroArgument * arg = static_cast<MathMacroArgument*>(it.nextInset());
                int n = arg->number() - 1;
                if (from <= n && n <= to) {
                        int cellSlice = cur.find(it.cell());
                        if (cellSlice != -1 && cur[cellSlice].pos() > it.pos())
-                                       --cur[cellSlice].pos();
+                               --cur[cellSlice].pos();
 
                        it.cell().erase(it.pos());
                }
        }
-       
+
        updateLook();
 }
 
@@ -548,9 +573,9 @@ void MathMacroTemplate::removeArguments(Cursor & cur, int from, int to) {
 void MathMacroTemplate::shiftArguments(size_t from, int by) {
        for (DocIterator it = doc_iterator_begin(*this); it; it.forwardChar()) {
                if (!it.nextInset())
-                                               continue;
+                       continue;
                if (it.nextInset()->lyxCode() != MATHMACROARG_CODE)
-                                               continue;
+                       continue;
                MathMacroArgument * arg = static_cast<MathMacroArgument*>(it.nextInset());
                if (arg->number() >= from + 1)
                        arg->setNumber(arg->number() + by);
@@ -577,18 +602,19 @@ void fixMacroInstancesAddRemove(Cursor const & from, docstring const & name, int
 
                // in front of macro instance?
                Inset * inset = dit.nextInset();
-               if (inset) {
-                       InsetMath * insetMath = inset->asInsetMath();
-                       if (insetMath) {
-                               MathMacro * macro = insetMath->asMacro();
-                               if (macro && macro->name() == name && macro->folded()) {
-                                       // found macro instance
-                                       if (insert)
-                                               macro->insertArgument(n);
-                                       else
-                                               macro->removeArgument(n);
-                               }
-                       }
+               if (!inset)
+                       continue;
+               InsetMath * insetMath = inset->asInsetMath();
+               if (!insetMath)
+                       continue;
+
+               MathMacro * macro = insetMath->asMacro();
+               if (macro && macro->name() == name && macro->folded()) {
+                       // found macro instance
+                       if (insert)
+                               macro->insertArgument(n);
+                       else
+                               macro->removeArgument(n);
                }
        }
 }
@@ -608,22 +634,22 @@ void fixMacroInstancesOptional(Cursor const & from, docstring const & name, int
 
                // in front of macro instance?
                Inset * inset = dit.nextInset();
-               if (inset) {
-                       InsetMath * insetMath = inset->asInsetMath();
-                       if (insetMath) {
-                               MathMacro * macro = insetMath->asMacro();
-                               if (macro && macro->name() == name && macro->folded()) {
-                                       // found macro instance
-                                       macro->setOptionals(optionals);
-                               }
-                       }
+               if (!inset)
+                       continue;
+               InsetMath * insetMath = inset->asInsetMath();
+               if (!insetMath)
+                       continue;
+               MathMacro * macro = insetMath->asMacro();
+               if (macro && macro->name() == name && macro->folded()) {
+                       // found macro instance
+                       macro->setOptionals(optionals);
                }
        }
 }
 
 
 template<class F>
-void fixMacroInstancesFunctional(Cursor const & from, 
+void fixMacroInstancesFunctional(Cursor const & from,
        docstring const & name, F & fix) {
        Cursor dit = from;
 
@@ -638,19 +664,19 @@ void fixMacroInstancesFunctional(Cursor const & from,
 
                // in front of macro instance?
                Inset * inset = dit.nextInset();
-               if (inset) {
-                       InsetMath * insetMath = inset->asInsetMath();
-                       if (insetMath) {
-                               MathMacro * macro = insetMath->asMacro();
-                               if (macro && macro->name() == name && macro->folded())
-                                       F(macro);
-                       }
-               }
+               if (!inset)
+                       continue;
+               InsetMath * insetMath = inset->asInsetMath();
+               if (!insetMath)
+                       continue;
+               MathMacro * macro = insetMath->asMacro();
+               if (macro && macro->name() == name && macro->folded())
+                       F(macro);
        }
 }
 
 
-void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy) 
+void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy)
 {
        if (pos <= numargs_ && pos >= optionals_ && numargs_ < 9) {
                ++numargs_;
@@ -666,7 +692,7 @@ void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy)
                        dit.leaveInset(*this);
                        // TODO: this was dit.forwardPosNoDescend before. Check that this is the same
                        dit.top().forwardPos();
-                       
+
                        // fix macro instances
                        fixMacroInstancesAddRemove(dit, name(), pos, true);
                }
@@ -741,7 +767,7 @@ void MathMacroTemplate::makeOptional(Cursor & cur) {
 void MathMacroTemplate::makeNonOptional(Cursor & cur) {
        if (numargs_ > 0 && optionals_ > 0) {
                --optionals_;
-               
+
                // store default value for later if the use changes his mind
                optionalValues_[optionals_] = cell(optIdx(optionals_));
                cells_.erase(cells_.begin() + optIdx(optionals_));
@@ -775,7 +801,7 @@ void MathMacroTemplate::doDispatch(Cursor & cur, FuncRequest & cmd)
        string const arg = to_utf8(cmd.argument());
        switch (cmd.action) {
 
-       case LFUN_MATH_MACRO_ADD_PARAM: 
+       case LFUN_MATH_MACRO_ADD_PARAM:
                if (numargs_ < 9) {
                        cur.recordUndoFullDocument();
                        size_t pos = numargs_;
@@ -786,7 +812,7 @@ void MathMacroTemplate::doDispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
 
-       case LFUN_MATH_MACRO_REMOVE_PARAM: 
+       case LFUN_MATH_MACRO_REMOVE_PARAM:
                if (numargs_ > 0) {
                        cur.recordUndoFullDocument();
                        size_t pos = numargs_ - 1;
@@ -859,7 +885,7 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd,
                        int num = numargs_ + 1;
                        if (arg.size() != 0)
                                num = convert<int>(arg);
-                       bool on = (num >= optionals_ 
+                       bool on = (num >= optionals_
                                   && numargs_ < 9 && num <= numargs_ + 1);
                        flag.enabled(on);
                        break;
@@ -878,13 +904,13 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd,
                }
 
                case LFUN_MATH_MACRO_MAKE_OPTIONAL:
-                       flag.enabled(numargs_ > 0 
-                                    && optionals_ < numargs_ 
+                       flag.enabled(numargs_ > 0
+                                    && optionals_ < numargs_
                                     && type_ != MacroTypeDef);
                        break;
 
                case LFUN_MATH_MACRO_MAKE_NONOPTIONAL:
-                       flag.enabled(optionals_ > 0 
+                       flag.enabled(optionals_ > 0
                                     && type_ != MacroTypeDef);
                        break;
 
@@ -897,7 +923,7 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd,
                        break;
 
                case LFUN_MATH_MACRO_ADD_GREEDY_OPTIONAL_PARAM:
-                       flag.enabled(numargs_ == 0 
+                       flag.enabled(numargs_ == 0
                                     && type_ != MacroTypeDef);
                        break;
 
@@ -923,7 +949,7 @@ void MathMacroTemplate::read(Buffer const &, Lexer & lex)
                return;
        }
        operator=( *(ar[0]->asMacroTemplate()) );
-       
+
        updateLook();
 }
 
@@ -946,40 +972,26 @@ void MathMacroTemplate::write(WriteStream & os) const
 
 void MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) const
 {
-       if (type_ == MacroTypeDef) {
-               os << "\\def\\" << name().c_str();
-               for (int i = 1; i <= numargs_; ++i)
-                       os << '#' << i;
-       } else {
-               // newcommand or renewcommand
+       // newcommand or renewcommand
+       if (os.latex() && optionals_ > 1)
+               os << "\\newlyxcommand";
+       else {
                if (redefinition_ && !overwriteRedefinition)
                        os << "\\renewcommand";
                else
                        os << "\\newcommand";
-               os << "{\\" << name().c_str() << '}';
-               if (numargs_ > 0)
-                       os << '[' << numargs_ << ']';
-               
-               // optional values
-               if (os.latex()) {
-                       // in latex only one optional possible, simulate the others
-                       if (optionals_ >= 1) {
-                               docstring optValue = asString(cell(optIdx(0)));
-                               if (optValue.find(']') != docstring::npos)
-                                       os << "[{" << cell(optIdx(0)) << "}]";
-                               else
-                                       os << "[" << cell(optIdx(0)) << "]";
-                       }
-               } else {
-                       // in lyx we handle all optionals as real optionals
-                       for (int i = 0; i < optionals_; ++i) {
-                               docstring optValue = asString(cell(optIdx(i)));
-                               if (optValue.find(']') != docstring::npos)
-                                       os << "[{" << cell(optIdx(i)) << "}]";
-                               else
-                                       os << "[" << cell(optIdx(i)) << "]";
-                       }
-               }
+       }
+       os << "{\\" << name().c_str() << '}';
+       if (numargs_ > 0)
+               os << '[' << numargs_ << ']';
+
+       // optional values
+       for (int i = 0; i < optionals_; ++i) {
+               docstring optValue = asString(cell(optIdx(i)));
+               if (optValue.find(']') != docstring::npos)
+                       os << "[{" << cell(optIdx(i)) << "}]";
+               else
+                       os << "[" << cell(optIdx(i)) << "]";
        }
 
        os << "{" << cell(defIdx()) << "}";
@@ -1022,7 +1034,7 @@ bool MathMacroTemplate::validName() const
        // valid characters?
        for (size_t i = 0; i < n.size(); ++i) {
                if (!(n[i] >= 'a' && n[i] <= 'z') &&
-                               !(n[i] >= 'A' && n[i] <= 'Z')) 
+                               !(n[i] >= 'A' && n[i] <= 'Z'))
                        return false;
        }
 
@@ -1052,7 +1064,7 @@ bool MathMacroTemplate::fixNameAndCheckIfValid()
                                continue;
                        }
                }
-               
+
                // throw cell away
                data.erase(i);
        }
@@ -1061,12 +1073,19 @@ bool MathMacroTemplate::fixNameAndCheckIfValid()
        return data.size() > 0;
 }
 
+       
+void MathMacroTemplate::validate(LaTeXFeatures & features) const
+{
+       if (optionals_ > 1) {
+               features.require("newlyxcommand");
+       }
+}
 
 void MathMacroTemplate::getDefaults(vector<docstring> & defaults) const
 {
        defaults.resize(numargs_);
        for (int i = 0; i < optionals_; ++i)
-               defaults[i] = asString(cell(optIdx(i)));        
+               defaults[i] = asString(cell(optIdx(i)));
 }
 
 
@@ -1093,7 +1112,7 @@ size_t MathMacroTemplate::numOptionals() const
        return optionals_;
 }
 
-       
+
 void MathMacroTemplate::infoize(odocstream & os) const
 {
        os << "Math Macro: \\" << name();