+ d->macro_->unlock();
+
+ // calculate dimension with label while editing
+ if (lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX
+ && d->editing_[mi.base.bv]) {
+ FontInfo font = mi.base.font;
+ augmentFont(font, "lyxtex");
+ Dimension namedim;
+ mathed_string_dim(font, name(), namedim);
+#if 0
+ dim.wid += 2 + namedim.wid + 2 + 2;
+ dim.asc = max(dim.asc, namedim.asc) + 2;
+ dim.des = max(dim.des, namedim.des) + 2;
+#endif
+ dim.wid = max(1 + namedim.wid + 1, 2 + dim.wid + 2);
+ dim.asc += 1 + namedim.height() + 1;
+ dim.des += 2;
+ }
+ }
+}
+
+
+int MathMacro::kerning(BufferView const * bv) const {
+ if (d->displayMode_ == DISPLAY_NORMAL && !d->editing_[bv])
+ return d->expanded_.kerning(bv);
+ else
+ return 0;
+}
+
+
+void MathMacro::updateMacro(MacroContext const & mc)
+{
+ if (validName()) {
+ d->macro_ = mc.get(name());
+ if (d->macro_ && d->macroBackup_ != *d->macro_) {
+ d->macroBackup_ = *d->macro_;
+ d->needsUpdate_ = true;
+ }
+ } else {
+ d->macro_ = 0;
+ }
+}
+
+
+class MathMacro::UpdateLocker
+{
+public:
+ explicit UpdateLocker(MathMacro & mm) : mac(mm)
+ {
+ mac.d->isUpdating_ = true;
+ }
+ ~UpdateLocker() { mac.d->isUpdating_ = false; }
+private:
+ MathMacro & mac;
+};
+/** Avoid wrong usage of UpdateLocker.
+ To avoid wrong usage:
+ UpdateLocker(...); // wrong
+ UpdateLocker locker(...); // right
+*/
+#define UpdateLocker(x) unnamed_UpdateLocker;
+// Tip gotten from Bobby Schmidt's column in C/C++ Users Journal
+
+
+void MathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc,
+ UpdateType utype, int nesting)
+{
+ // block recursive calls (bug 8999)
+ if (d->isUpdating_)
+ return;
+
+ UpdateLocker locker(*this);
+
+ // known macro?
+ if (d->macro_ == 0)
+ return;
+
+ // remember nesting level of this macro
+ d->nesting_ = nesting;
+
+ // update requires
+ d->requires_ = d->macro_->requires();
+
+ if (!d->needsUpdate_
+ // non-normal mode? We are done!
+ || (d->displayMode_ != DISPLAY_NORMAL))
+ return;
+
+ d->needsUpdate_ = false;
+
+ // get default values of macro
+ vector<docstring> const & defaults = d->macro_->defaults();
+
+ // create MathMacroArgumentValue objects pointing to the cells of the macro
+ vector<MathData> values(nargs());
+ for (size_t i = 0; i < nargs(); ++i) {
+ ArgumentProxy * proxy;
+ if (i < defaults.size())
+ proxy = new ArgumentProxy(this, i, defaults[i]);
+ else
+ proxy = new ArgumentProxy(this, i);
+ values[i].insert(0, MathAtom(proxy));
+ }
+ // expanding macro with the values
+ // Only update the argument macros if anything was expanded, otherwise
+ // we would get an endless loop (bug 9140). UpdateLocker does not work
+ // in this case, since MacroData::expand() creates new MathMacro
+ // objects, so this would be a different recursion path than the one
+ // protected by UpdateLocker.
+ if (d->macro_->expand(values, d->expanded_)) {
+ if (utype == OutputUpdate && !d->expanded_.empty())
+ d->expanded_.updateMacros(cur, mc, utype, nesting);