From: Abdelrazak Younes Date: Tue, 17 Apr 2007 16:52:43 +0000 (+0000) Subject: Real fix for bug 1395 by Stefan Schimanski, this commit replace the one done at revis... X-Git-Tag: 1.6.10~10228 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=49395dd85e26d96b5c046ed73ddba2b242b1974c;p=features.git Real fix for bug 1395 by Stefan Schimanski, this commit replace the one done at revision 17836 which was reverted! Locking counter added to MacroData: it is increased before drawing/ metric calculations and decreased afterwards in InsetMathMacro. If a macro is already locked at that point, "Self reference: \foo" is drawn instead of the macro definition to avoid endless loops. Moreover inside of the arguments of the macro the counter is temporarily decreased as those cases do not cause loops. (fixes bug #1395) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17841 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/mathed/InsetMathMacro.C b/src/mathed/InsetMathMacro.C index 43cbed7c31..087aa80807 100644 --- a/src/mathed/InsetMathMacro.C +++ b/src/mathed/InsetMathMacro.C @@ -33,6 +33,54 @@ using std::endl; using std::vector; +/// This class is the value of a macro argument, technically +/// a wrapper of the cells of MathMacro. +class MathMacroArgumentValue : public InsetMathDim { +public: + /// + MathMacroArgumentValue(MathArray const * value, docstring const & macroName) + : value_(value), macroName_(macroName) {} + /// + bool metrics(MetricsInfo & mi, Dimension & dim) const; + /// + void draw(PainterInfo &, int x, int y) const; + +private: + std::auto_ptr doClone() const; + MathArray const * value_; + docstring macroName_; +}; + + +auto_ptr MathMacroArgumentValue::doClone() const +{ + return auto_ptr(new MathMacroArgumentValue(*this)); +} + + +bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const +{ + // unlock outer macro in arguments, and lock it again later + MacroTable::globalMacros().get(macroName_).unlock(); + value_->metrics(mi, dim); + MacroTable::globalMacros().get(macroName_).lock(); + metricsMarkers2(dim); + if (dim_ == dim) + return false; + dim_ = dim; + return true; +} + + +void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const +{ + // unlock outer macro in arguments, and lock it again later + MacroTable::globalMacros().get(macroName_).unlock(); + value_->draw(pi, x, y); + MacroTable::globalMacros().get(macroName_).lock(); +} + + MathMacro::MathMacro(docstring const & name, int numargs) : InsetMathNest(numargs), name_(name) {} @@ -63,25 +111,39 @@ bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const { if (!MacroTable::globalMacros().has(name())) { mathed_string_dim(mi.base.font, "Unknown: " + name(), dim); - } else if (editing(mi.base.bv)) { - // FIXME UNICODE - asArray(MacroTable::globalMacros().get(name()).def(), tmpl_); - LyXFont font = mi.base.font; - augmentFont(font, from_ascii("lyxtex")); - tmpl_.metrics(mi, dim); - // FIXME UNICODE - dim.wid += mathed_string_width(font, name()) + 10; - // FIXME UNICODE - int ww = mathed_string_width(font, from_ascii("#1: ")); - for (idx_type i = 0; i < nargs(); ++i) { - MathArray const & c = cell(i); - c.metrics(mi); - dim.wid = max(dim.wid, c.width() + ww); - dim.des += c.height() + 10; - } } else { - MacroTable::globalMacros().get(name()).expand(cells_, expanded_); - expanded_.metrics(mi, dim); + MacroData const & macro = MacroTable::globalMacros().get(name()); + if (macro.locked()) { + mathed_string_dim(mi.base.font, "Self reference: " + name(), dim); + expanded_ = MathArray(); + } else if (editing(mi.base.bv)) { + // FIXME UNICODE + asArray(macro.def(), tmpl_); + LyXFont font = mi.base.font; + augmentFont(font, from_ascii("lyxtex")); + tmpl_.metrics(mi, dim); + // FIXME UNICODE + dim.wid += mathed_string_width(font, name()) + 10; + // FIXME UNICODE + int ww = mathed_string_width(font, from_ascii("#1: ")); + for (idx_type i = 0; i < nargs(); ++i) { + MathArray const & c = cell(i); + c.metrics(mi); + dim.wid = max(dim.wid, c.width() + ww); + dim.des += c.height() + 10; + } + } else { + // create MathMacroArgumentValue object pointing to the cells of the macro + MacroData const & macro = MacroTable::globalMacros().get(name()); + vector values(nargs()); + for (size_t i = 0; i != nargs(); ++i) + values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i], name()))); + macro.expand(values, expanded_); + + MacroTable::globalMacros().get(name()).lock(); + expanded_.metrics(mi, dim); + MacroTable::globalMacros().get(name()).unlock(); + } } metricsMarkers2(dim); if (dim_ == dim) @@ -96,28 +158,36 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const if (!MacroTable::globalMacros().has(name())) { // FIXME UNICODE drawStrRed(pi, x, y, "Unknown: " + name()); - } else if (editing(pi.base.bv)) { - LyXFont font = pi.base.font; - augmentFont(font, from_ascii("lyxtex")); - int h = y - dim_.ascent() + 2 + tmpl_.ascent(); - pi.pain.text(x + 3, h, name(), font); - int const w = mathed_string_width(font, name()); - tmpl_.draw(pi, x + w + 12, h); - h += tmpl_.descent(); - Dimension ldim; - docstring t = from_ascii("#1: "); - mathed_string_dim(font, t, ldim); - for (idx_type i = 0; i < nargs(); ++i) { - MathArray const & c = cell(i); - h += max(c.ascent(), ldim.asc) + 5; - c.draw(pi, x + ldim.wid, h); - char_type str[] = { '#', '1', ':', '\0' }; - str[1] += static_cast(i); - pi.pain.text(x + 3, h, str, font); - h += max(c.descent(), ldim.des) + 5; - } } else { - expanded_.draw(pi, x, y); + MacroData const & macro = MacroTable::globalMacros().get(name()); + if (macro.locked()) { + // FIXME UNICODE + drawStrRed(pi, x, y, "Self reference: " + name()); + } else if (editing(pi.base.bv)) { + LyXFont font = pi.base.font; + augmentFont(font, from_ascii("lyxtex")); + int h = y - dim_.ascent() + 2 + tmpl_.ascent(); + pi.pain.text(x + 3, h, name(), font); + int const w = mathed_string_width(font, name()); + tmpl_.draw(pi, x + w + 12, h); + h += tmpl_.descent(); + Dimension ldim; + string t = "#1: "; + mathed_string_dim(font, name(), ldim); + for (idx_type i = 0; i < nargs(); ++i) { + MathArray const & c = cell(i); + h += max(c.ascent(), ldim.asc) + 5; + c.draw(pi, x + ldim.wid, h); + char_type str[] = { '#', '1', ':', '\0' }; + str[1] += static_cast(i); + pi.pain.text(x + 3, h, str, font); + h += max(c.descent(), ldim.des) + 5; + } + } else { + MacroTable::globalMacros().get(name()).lock(); + expanded_.draw(pi, x, y); + MacroTable::globalMacros().get(name()).unlock(); + } } drawMarkers2(pi, x, y); } diff --git a/src/mathed/MathMacroTable.C b/src/mathed/MathMacroTable.C index 961235c2f2..2063419194 100644 --- a/src/mathed/MathMacroTable.C +++ b/src/mathed/MathMacroTable.C @@ -36,12 +36,12 @@ using std::size_t; MacroData::MacroData() - : numargs_(0) + : numargs_(0), lockCount_(0) {} MacroData::MacroData(docstring const & def, int numargs, docstring const & disp, string const & requires) - : def_(def), numargs_(numargs), disp_(disp), requires_(requires) + : def_(def), numargs_(numargs), disp_(disp), requires_(requires), lockCount_(0) {} diff --git a/src/mathed/MathMacroTable.h b/src/mathed/MathMacroTable.h index f6e2db77aa..eda5a21c2b 100644 --- a/src/mathed/MathMacroTable.h +++ b/src/mathed/MathMacroTable.h @@ -4,7 +4,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author André Pönitz + * \author Andr P�nitz * * Full author contact details are available in file CREDITS. */ @@ -12,11 +12,13 @@ #ifndef MATH_MACROTABLE_H #define MATH_MACROTABLE_H +#include "support/docstring.h" + +#include + #include #include -#include "support/docstring.h" - namespace lyx { class MathArray; @@ -40,6 +42,12 @@ public: std::string requires() const { return requires_; } /// std::string & requires() { return requires_; } + /// lock while being drawn + int lock() const { return ++lockCount_; } + /// is it being drawn? + bool locked() const { return lockCount_ != 0; } + /// + void unlock() const { --lockCount_; BOOST_ASSERT(lockCount_ >= 0); } private: /// @@ -50,6 +58,8 @@ private: docstring disp_; /// std::string requires_; + /// + mutable int lockCount_; }; diff --git a/src/mathed/MathMacroTemplate.C b/src/mathed/MathMacroTemplate.C index 2f6f8b4e79..24cb74a725 100644 --- a/src/mathed/MathMacroTemplate.C +++ b/src/mathed/MathMacroTemplate.C @@ -111,6 +111,10 @@ docstring MathMacroTemplate::prefix() const bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const { + bool lockMacro = MacroTable::globalMacros().has(name_); + if (lockMacro) + MacroTable::globalMacros().get(name_).lock(); + cell(0).metrics(mi); cell(1).metrics(mi); docstring dp = prefix(); @@ -118,6 +122,10 @@ bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const + theFontMetrics(mi.base.font).width(dp); dim.asc = std::max(cell(0).ascent(), cell(1).ascent()) + 7; dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7; + + if (lockMacro) + MacroTable::globalMacros().get(name_).unlock(); + if (dim_ == dim) return false; dim_ = dim; @@ -127,6 +135,10 @@ bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const { + bool lockMacro = MacroTable::globalMacros().has(name_); + if (lockMacro) + MacroTable::globalMacros().get(name_).lock(); + setPosCache(p, x, y); // label @@ -167,6 +179,9 @@ void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const cell(1).draw(pi, x + 8 + w0, y + 1); pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3, w1 + 4, dim_.height() - 6, LColor::mathline); + + if (lockMacro) + MacroTable::globalMacros().get(name_).unlock(); }