mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
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
This commit is contained in:
parent
86c1053f51
commit
49395dd85e
@ -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<InsetBase> doClone() const;
|
||||
MathArray const * value_;
|
||||
docstring macroName_;
|
||||
};
|
||||
|
||||
|
||||
auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const
|
||||
{
|
||||
return auto_ptr<InsetBase>(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<MathArray> 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<char_type>(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<char_type>(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);
|
||||
}
|
||||
|
@ -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)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -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<EFBFBD>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 <boost/assert.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user