+}
+
+
+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);
+ }
+ // get definition for list edit mode
+ docstring const & display = d->macro_->display();
+ asArray(display.empty() ? d->macro_->definition() : display,
+ d->definition_, Parse::QUIET);