]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathMacro.cpp
mathed: bformat infoize messages
[lyx.git] / src / mathed / MathMacro.cpp
index 5564600d06487f06ed46261486e9ed608e80eaa3..f4150f30f84250533ff313105aa5ebfda07605cb 100644 (file)
 #include "FuncStatus.h"
 #include "FuncRequest.h"
 #include "LaTeXFeatures.h"
-#include "LyXFunc.h"
+#include "LyX.h"
 #include "LyXRC.h"
-#include "Undo.h"
 
 #include "frontends/Painter.h"
 
 #include "support/debug.h"
+#include "support/gettext.h"
 #include "support/lassert.h"
+#include "support/lstrings.h"
 #include "support/textutils.h"
 
 #include <ostream>
 #include <vector>
 
+using namespace lyx::support;
 using namespace std;
 
 namespace lyx {
@@ -75,6 +77,8 @@ public:
        ///
        void mathmlize(MathStream & ms) const { ms << mathMacro_.cell(idx_); }
        ///
+       void htmlize(HtmlStream & ms) const { ms << mathMacro_.cell(idx_); }
+       ///
        void draw(PainterInfo & pi, int x, int y) const {
                if (mathMacro_.editMetrics(pi.base.bv)) {
                        // The only way a ArgumentProxy can appear is in a cell of the 
@@ -124,7 +128,8 @@ private:
 MathMacro::MathMacro(Buffer * buf, docstring const & name)
        : InsetMathNest(buf, 0), name_(name), displayMode_(DISPLAY_INIT),
                expanded_(buf), attachedArgsNum_(0), optionals_(0), nextFoldMode_(true),
-               macroBackup_(buf), macro_(0), needsUpdate_(false), appetite_(9)
+               macroBackup_(buf), macro_(0), needsUpdate_(false),
+               isUpdating_(false), appetite_(9)
 {}
 
 
@@ -137,6 +142,15 @@ Inset * MathMacro::clone() const
 }
 
 
+void MathMacro::normalize(NormalStream & os) const
+{
+       os << "[macro " << name();
+       for (size_t i = 0; i < nargs(); ++i)
+               os << ' ' << cell(i);
+       os << ']';
+}
+
+
 docstring MathMacro::name() const
 {
        if (displayMode_ == DISPLAY_UNFOLDED)
@@ -163,9 +177,12 @@ bool MathMacro::editMode(BufferView const * bv) const {
                        // look if there is no other macro in edit mode above
                        ++i;
                        for (; i != cur.depth(); ++i) {
-                               MathMacro const * macro = dynamic_cast<MathMacro const *>(&cur[i].inset());
-                               if (macro && macro->displayMode() == DISPLAY_NORMAL)
-                                       return false;
+                               InsetMath * im = cur[i].asInsetMath();
+                               if (im) {
+                                       MathMacro const * macro = im->asMacro();
+                                       if (macro && macro->displayMode() == DISPLAY_NORMAL)
+                                               return false;
+                               }
                        }
 
                        // ok, none found, I am the highest one
@@ -202,7 +219,7 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
                   && editing_[mi.base.bv]) {
                // Macro will be edited in a old-style list mode here:
 
-               LASSERT(macro_ != 0, /**/);
+               LBUFERR(macro_);
                Dimension fontDim;
                FontInfo labelFont = sane_font;
                math_font_max_dim(labelFont, fontDim.asc, fontDim.des);
@@ -239,7 +256,7 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
                dim.wid += 2;
                metricsMarkers2(dim);
        } else {
-               LASSERT(macro_ != 0, /**/);
+               LBUFERR(macro_);
 
                // calculate metrics, hoping that all cells are seen
                macro_->lock();
@@ -248,7 +265,7 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
                // otherwise do a manual metrics call
                CoordCache & coords = mi.base.bv->coordCache();
                for (idx_type i = 0; i < nargs(); ++i) {
-                       if (!coords.getArrays().has(&cell(i))) {
+                       if (!coords.getArrays().hasDim(&cell(i))) {
                                Dimension tdim;
                                cell(i).metrics(mi, tdim);
                        }
@@ -287,7 +304,7 @@ int MathMacro::kerning(BufferView const * bv) const {
 void MathMacro::updateMacro(MacroContext const & mc) 
 {
        if (validName()) {
-               macro_ = mc.get(name());            
+               macro_ = mc.get(name());    
                if (macro_ && macroBackup_ != *macro_) {
                        macroBackup_ = *macro_;
                        needsUpdate_ = true;
@@ -298,8 +315,27 @@ void MathMacro::updateMacro(MacroContext const & mc)
 }
 
 
-void MathMacro::updateRepresentation()
+class MathMacro::UpdateLocker
+{
+public:
+       explicit UpdateLocker(MathMacro & mm) : mac(mm)
+       {
+               mac.isUpdating_ = true;
+       }
+       ~UpdateLocker() { mac.isUpdating_ = false; }
+private:
+       MathMacro & mac;
+};
+
+
+void MathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc,
+               UpdateType utype)
 {
+       if (isUpdating_)
+               return;
+
+       UpdateLocker locker(*this);
+
        // known macro?
        if (macro_ == 0)
                return;
@@ -307,14 +343,11 @@ void MathMacro::updateRepresentation()
        // update requires
        requires_ = macro_->requires();
        
-       // non-normal mode? We are done!
-       if (displayMode_ != DISPLAY_NORMAL)
+       if (!needsUpdate_
+               // non-normal mode? We are done!
+               || (displayMode_ != DISPLAY_NORMAL))
                return;
 
-       // macro changed?
-       if (!needsUpdate_)
-               return;
-       
        needsUpdate_ = false;
        
        // get default values of macro
@@ -332,6 +365,8 @@ void MathMacro::updateRepresentation()
        }
        // expanding macro with the values
        macro_->expand(values, expanded_.cell(0));
+       if (utype == OutputUpdate && !expanded_.cell(0).empty())
+               expanded_.cell(0).updateMacros(cur, mc, utype);
        // get definition for list edit mode
        docstring const & display = macro_->display();
        asArray(display.empty() ? macro_->definition() : display, definition_);
@@ -445,14 +480,14 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
 
        // edit mode changed?
        if (editing_[pi.base.bv] != editMode(pi.base.bv))
-               pi.base.bv->cursor().updateFlags(Update::SinglePar);
+               pi.base.bv->cursor().screenUpdateFlags(Update::SinglePar);
 }
 
 
 void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
 {
        // We may have 0 arguments, but InsetMathNest requires at least one.
-       if (cells_.size() > 0)
+       if (!cells_.empty())
                InsetMathNest::drawSelection(pi, x, y);
 }
 
@@ -494,8 +529,7 @@ bool MathMacro::validName() const
 {
        docstring n = name();
 
-       // empty name?
-       if (n.size() == 0)
+       if (n.empty())
                return false;
 
        // converting back and force doesn't swallow anything?
@@ -534,7 +568,7 @@ void MathMacro::validate(LaTeXFeatures & features) const
 
 void MathMacro::edit(Cursor & cur, bool front, EntryDirection entry_from)
 {
-       cur.updateFlags(Update::SinglePar);
+       cur.screenUpdateFlags(Update::SinglePar);
        InsetMathNest::edit(cur, front, entry_from);
 }
 
@@ -543,7 +577,7 @@ Inset * MathMacro::editXY(Cursor & cur, int x, int y)
 {
        // We may have 0 arguments, but InsetMathNest requires at least one.
        if (nargs() > 0) {
-               cur.updateFlags(Update::SinglePar);
+               cur.screenUpdateFlags(Update::SinglePar);
                return InsetMathNest::editXY(cur, x, y);                
        } else
                return this;
@@ -552,7 +586,7 @@ Inset * MathMacro::editXY(Cursor & cur, int x, int y)
 
 void MathMacro::removeArgument(Inset::pos_type pos) {
        if (displayMode_ == DISPLAY_NORMAL) {
-               LASSERT(size_t(pos) < cells_.size(), /**/);
+               LASSERT(size_t(pos) < cells_.size(), return);
                cells_.erase(cells_.begin() + pos);
                if (size_t(pos) < attachedArgsNum_)
                        --attachedArgsNum_;
@@ -567,7 +601,7 @@ void MathMacro::removeArgument(Inset::pos_type pos) {
 
 void MathMacro::insertArgument(Inset::pos_type pos) {
        if (displayMode_ == DISPLAY_NORMAL) {
-               LASSERT(size_t(pos) <= cells_.size(), /**/);
+               LASSERT(size_t(pos) <= cells_.size(), return);
                cells_.insert(cells_.begin() + pos, MathData());
                if (size_t(pos) < attachedArgsNum_)
                        ++attachedArgsNum_;
@@ -581,7 +615,7 @@ void MathMacro::insertArgument(Inset::pos_type pos) {
 
 void MathMacro::detachArguments(vector<MathData> & args, bool strip)
 {
-       LASSERT(displayMode_ == DISPLAY_NORMAL, /**/);  
+       LASSERT(displayMode_ == DISPLAY_NORMAL, return);
        args = cells_;
 
        // strip off empty cells, but not more than arity-attachedArgsNum_
@@ -602,7 +636,7 @@ void MathMacro::detachArguments(vector<MathData> & args, bool strip)
 
 void MathMacro::attachArguments(vector<MathData> const & args, size_t arity, int optionals)
 {
-       LASSERT(displayMode_ == DISPLAY_NORMAL, /**/);
+       LASSERT(displayMode_ == DISPLAY_NORMAL, return);
        cells_ = args;
        attachedArgsNum_ = args.size();
        cells_.resize(arity);
@@ -615,14 +649,14 @@ void MathMacro::attachArguments(vector<MathData> const & args, size_t arity, int
 
 bool MathMacro::idxFirst(Cursor & cur) const 
 {
-       cur.updateFlags(Update::SinglePar);
+       cur.screenUpdateFlags(Update::SinglePar);
        return InsetMathNest::idxFirst(cur);
 }
 
 
 bool MathMacro::idxLast(Cursor & cur) const 
 {
-       cur.updateFlags(Update::SinglePar);
+       cur.screenUpdateFlags(Update::SinglePar);
        return InsetMathNest::idxLast(cur);
 }
 
@@ -635,18 +669,21 @@ bool MathMacro::notifyCursorLeaves(Cursor const & old, Cursor & cur)
                        // The macro name was changed
                        Cursor inset_cursor = old;
                        int macroSlice = inset_cursor.find(this);
-                       LASSERT(macroSlice != -1, /**/);
+                       // returning true means the cursor is "now" invalid,
+                       // which it was.
+                       LASSERT(macroSlice != -1, return true);
                        inset_cursor.cutOff(macroSlice);
                        inset_cursor.recordUndoInset();
                        inset_cursor.pop();
                        inset_cursor.cell().erase(inset_cursor.pos());
                        inset_cursor.cell().insert(inset_cursor.pos(),
                                createInsetMath(unfolded_name, cur.buffer()));
-                       cur.updateFlags(cur.disp_.update() | Update::SinglePar);
+                       cur.resetAnchor();
+                       cur.screenUpdateFlags(cur.result().screenUpdate() | Update::SinglePar);
                        return true;
                }
        }
-       cur.updateFlags(Update::Force);
+       cur.screenUpdateFlags(Update::Force);
        return InsetMathNest::notifyCursorLeaves(old, cur);
 }
 
@@ -655,7 +692,7 @@ void MathMacro::fold(Cursor & cur)
 {
        if (!nextFoldMode_) {
                nextFoldMode_ = true;
-               cur.updateFlags(Update::SinglePar);
+               cur.screenUpdateFlags(Update::SinglePar);
        }
 }
 
@@ -664,7 +701,7 @@ void MathMacro::unfold(Cursor & cur)
 {
        if (nextFoldMode_) {
                nextFoldMode_ = false;
-               cur.updateFlags(Update::SinglePar);
+               cur.screenUpdateFlags(Update::SinglePar);
        }
 }
 
@@ -688,10 +725,11 @@ void MathMacro::write(WriteStream & os) const
        }
 
        // normal mode
-       LASSERT(macro_, /**/);
+       // we should be ok to continue even if this fails.
+       LATTEST(macro_);
 
-       // optional arguments make macros fragile
-       if (optionals_ > 0 && os.fragile())
+       // Always protect macros in a fragile environment
+       if (os.fragile())
                os << "\\protect";
        
        os << "\\" << name();
@@ -719,7 +757,7 @@ void MathMacro::write(WriteStream & os) const
        for (; i < cells_.size(); ++i) {
                if (cell(i).size() == 1 
                        && cell(i)[0].nucleus()->asCharInset()
-                       && cell(i)[0].nucleus()->asCharInset()->getChar() < 0x80) {
+                       && isASCII(cell(i)[0].nucleus()->asCharInset()->getChar())) {
                        if (first)
                                os << " ";
                        os << cell(i);
@@ -742,7 +780,23 @@ void MathMacro::maple(MapleStream & os) const
 
 void MathMacro::mathmlize(MathStream & os) const
 {
-       os << expanded_.cell(0);
+       MathData const & data = expanded_.cell(0);
+       if (data.empty()) {
+               // this means that we do not recognize the macro
+               throw MathExportException();
+       }
+       os << data;
+}
+
+
+void MathMacro::htmlize(HtmlStream & os) const
+{
+       MathData const & data = expanded_.cell(0);
+       if (data.empty()) {
+               // this means that we do not recognize the macro
+               throw MathExportException();
+       }
+       os << data;
 }
 
 
@@ -754,14 +808,13 @@ void MathMacro::octave(OctaveStream & os) const
 
 void MathMacro::infoize(odocstream & os) const
 {
-       os << "Macro: " << name();
+       os << bformat(_("Macro: %1$s"), name());
 }
 
 
 void MathMacro::infoize2(odocstream & os) const
 {
-       os << "Macro: " << name();
-
+       os << bformat(_("Macro: %1$s"), name());
 }
 
 
@@ -840,13 +893,13 @@ bool MathMacro::insertCompletion(Cursor & cur, docstring const & s,
        docstring newName = name() + s;
        asArray(newName, cell(0));
        cur.bv().cursor().pos() = name().size();
-       cur.updateFlags(Update::SinglePar);
+       cur.screenUpdateFlags(Update::SinglePar);
        
        // finish macro
        if (finished) {
                cur.bv().cursor().pop();
                ++cur.bv().cursor().pos();
-               cur.updateFlags(Update::SinglePar);
+               cur.screenUpdateFlags(Update::SinglePar);
        }
        
        return true;