virtual InsetMathAMSArray const * asAMSArrayInset() const { return 0; }
virtual InsetMathArray * asArrayInset() { return 0; }
virtual InsetMathArray const * asArrayInset() const { return 0; }
+ virtual InsetMathBrace * asBraceInset() { return 0; }
virtual InsetMathBrace const * asBraceInset() const { return 0; }
virtual InsetMathChar const * asCharInset() const { return 0; }
virtual InsetMathDelim * asDelimInset() { return 0; }
InsetMathBrace();
///
InsetMathBrace(MathArray const & ar);
- ///
- InsetMathBrace const * asBraceInset() const { return this; }
/// we write extra braces in any case...
bool extraBraces() const { return true; }
///
void mathmlize(MathStream &) const;
///
void infoize(odocstream & os) const;
+
+ /// identifies brace insets
+ InsetMathBrace * asBraceInset() { return this; }
+ /// identifies brace insets
+ InsetMathBrace const * asBraceInset() const { return this; }
private:
virtual std::auto_ptr<InsetBase> doClone() const;
};
using std::vector;
-MathMacro::MathMacro(docstring const & name, int numargs)
- : InsetMathNest(numargs), name_(name)
+/// 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) : value_(value) {}
+ ///
+ 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_;
+};
+
+
+auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const
+{
+ return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
+}
+
+
+bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+ value_->metrics(mi, dim);
+ metricsMarkers2(dim);
+ if (dim_ == dim)
+ return false;
+ dim_ = dim;
+ return true;
+}
+
+
+void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const
+{
+ value_->draw(pi, x, y);
+}
+
+
+
+MathMacro::MathMacro(docstring const & name)
+ : InsetMathNest(0), name_(name)
{}
dim.des += c.height() + 10;
}
} else {
- MacroTable::globalMacros().get(name()).expand(cells_, expanded_);
+ // 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])));
+ macro.expand(values, expanded_);
expanded_.metrics(mi, dim);
}
metricsMarkers2(dim);
InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
{
// We may have 0 arguments, but InsetMathNest requires at least one.
- if (nargs() > 0) {
- // Prevent crash due to cold coordcache
- // FIXME: This is only a workaround, the call of
- // InsetMathNest::editXY is correct. The correct fix would
- // ensure that the coordcache of the arguments is valid.
- if (!editing(&cur.bv())) {
- edit(cur, true);
- return this;
- }
+ if (nargs() > 0)
return InsetMathNest::editXY(cur, x, y);
- }
- return this;
+ else
+ return this;
+}
+
+
+void MathMacro::detachArguments(std::vector<MathArray> &args)
+{
+ args = cells_;
+ cells_ = std::vector<MathArray>();
+}
+
+
+void MathMacro::attachArguments(std::vector<MathArray> const &args)
+{
+ cells_ = args;
}
void MathMacro::maple(MapleStream & os) const
{
- updateExpansion();
lyx::maple(expanded_, os);
}
void MathMacro::mathmlize(MathStream & os) const
{
- updateExpansion();
lyx::mathmlize(expanded_, os);
}
void MathMacro::octave(OctaveStream & os) const
{
- updateExpansion();
lyx::octave(expanded_, os);
}
-void MathMacro::updateExpansion() const
-{
- //expanded_.substitute(*this);
-}
-
-
void MathMacro::infoize(odocstream & os) const
{
os << "Macro: " << name();
void MathMacro::infoize2(odocstream & os) const
{
os << "Macro: " << name();
-
}
class MathMacro : public InsetMathNest {
public:
/// A macro can be built from an existing template
- MathMacro(docstring const & name, int numargs);
+ MathMacro(docstring const & name);
+ ///
+ virtual MathMacro * asMacro() { return this; }
+ ///
+ virtual MathMacro const * asMacro() const { return this; }
///
void draw(PainterInfo & pi, int x, int y) const;
///
{ drawMarkers2(pi, x, y); }
///
bool metrics(MetricsInfo & mi, Dimension & dim) const;
+ ///
+ bool metricsExpanded(MetricsInfo & mi, Dimension & dim) const;
/// get cursor position
void cursorPos(BufferView const & bv, CursorSlice const & sl,
bool boundary, int & x, int & y) const;
///
docstring name() const;
///
- void setExpansion(MathArray const & exp, MathArray const & args) const;
-
+ void detachArguments(std::vector<MathArray> &args);
+ ///
+ void attachArguments(std::vector<MathArray> const &args);
+
///
void validate(LaTeXFeatures &) const;
private:
virtual std::auto_ptr<InsetBase> doClone() const;
- ///
- void updateExpansion() const;
- ///
- void expand() const;
-
+
/// name of macro
docstring name_;
- /// the unexpanded macro defintition
+ /// the macro template
mutable MathArray tmpl_;
/// the macro substituted with our args
mutable MathArray expanded_;
#include "InsetMathFont.h"
#include "InsetMathScript.h"
#include "InsetMathMacro.h"
+#include "InsetMathBrace.h"
#include "MathMacroTable.h"
#include "MathStream.h"
#include "MathSupport.h"
}
-
void MathArray::metrics(MetricsInfo & mi) const
{
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
if (empty())
return;
+ const_cast<MathArray*>(this)->updateMacros( mi );
+
dim_.asc = 0;
dim_.wid = 0;
- Dimension d;
- //BufferView & bv = *mi.base.bv;
- //Buffer const & buf = *bv.buffer();
- for (size_t i = 0, n = size(); i != n; ++i) {
+ Dimension d;
+ for (size_t i = 0; i != size(); ++i) {
MathAtom const & at = operator[](i);
-#if 0
- MathMacro const * mac = at->asMacro();
- if (mac && buf.hasMacro(mac->name())) {
- MacroData const & tmpl = buf.getMacro(mac->name());
- int numargs = tmpl.numargs();
- if (i + numargs > n)
- numargs = n - i - 1;
- lyxerr << "metrics:found macro: " << mac->name()
- << " numargs: " << numargs << endl;
- if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
- MathArray args(begin() + i + 1, begin() + i + numargs + 1);
- MathArray exp;
- tmpl.expand(args, exp);
- mac->setExpansion(exp, args);
- mac->metricsExpanded(mi, d);
- dim_.wid += mac->widthExpanded();
- i += numargs;
- continue;
- }
- }
-#endif
at->metrics(mi, d);
dim_ += d;
- if (i == n - 1)
+ if (i == size() - 1)
kerning_ = at->kerning();
}
}
for (size_t i = 0, n = size(); i != n; ++i) {
MathAtom const & at = operator[](i);
-#if 0
- Buffer const & buf = bv.buffer();
- // special macro handling
- MathMacro const * mac = at->asMacro();
- if (mac && buf.hasMacro(mac->name())) {
- MacroData const & tmpl = buf.getMacro(mac->name());
- int numargs = tmpl.numargs();
- if (i + numargs > n)
- numargs = n - i - 1;
- if (!isInside(bv.cursor(), *this, i + 1, i + numargs + 1)) {
- mac->drawExpanded(pi, x, y);
- x += mac->widthExpanded();
- i += numargs;
- continue;
- }
- }
-#endif
bv.coordCache().insets().add(at.nucleus(), x, y);
at->drawSelection(pi, x, y);
at->draw(pi, x, y);
}
+void MathArray::updateMacros(MetricsInfo & mi) {
+ Buffer *buf = mi.base.bv->buffer();
+
+ // go over the array and look for macros
+ for (size_t i = 0; i != size(); ++i) {
+ InsetMath * at = operator[](i).nucleus();
+ MathMacro * macroInset = at->asMacro();
+ if (macroInset) {
+ // get arity of macro or 0 if unknown
+ size_t numargs = 0;
+ if (buf->hasMacro(macroInset->name())) {
+ MacroData const & macro = buf->getMacro(macroInset->name());
+ numargs = macro.numargs();
+ }
+
+ // arity of macro changed?
+ if (macroInset->nargs() != numargs) {
+ // detach all arguments
+ std::vector<MathArray> detachedArgs;
+ macroInset->detachArguments( detachedArgs );
+
+ // too many arguments in the macro inset?
+ if (detachedArgs.size() > numargs) {
+ // insert overlap back as braces
+ std::vector<MathArray> overlap(detachedArgs.begin()+numargs, detachedArgs.end());
+ detachedArgs.erase(detachedArgs.begin()+numargs, detachedArgs.end());
+ for (size_t j = 0; j < overlap.size(); ++j) {
+ MathArray const & arg = overlap[j];
+ if (arg.size() == 1)
+ insert(i+j+1, MathAtom(new InsetMathBrace(arg)));
+ else
+ insert(i+j+1, arg[0]);
+ }
+ i += overlap.size();
+ } else {
+ // insert some cells from the array into the macro inset
+ size_t missingArgs = numargs-detachedArgs.size();
+ size_t j;
+ for (j = 0; j < missingArgs && i+1+j < size(); ++j) {
+ MathAtom & cell = operator[](i+1+j);
+ InsetMathBrace const * brace = cell->asBraceInset();
+ if (brace) {
+ // found brace, convert into argument
+ detachedArgs.push_back(brace->cell(0));
+ } else {
+ MathArray array;
+ array.insert(0, cell);
+ detachedArgs.push_back(array);
+ }
+ }
+
+ // remove them from the array
+ erase(begin()+i+1, begin()+i+1+j);
+
+ // enough for the macro inset now?
+ // Add some empty ones of necessary
+ for (; j < missingArgs; ++j)
+ detachedArgs.insert(detachedArgs.end(), MathArray());
+ }
+
+ // attach arguments back to macro inset
+ macroInset->attachArguments(detachedArgs);
+ }
+ }
+ }
+}
+
+
int MathArray::pos2x(size_type pos) const
{
return pos2x(pos, 0);
int kerning() const { return kerning_; }
///
void swap(MathArray & ar) { base_type::swap(ar); }
-
+
protected:
/// cached dimensions of cell
mutable Dimension dim_;
mutable int sshift_;
mutable int kerning_;
+ /// attach/detach brace inset to macros
+ void updateMacros(MetricsInfo & mi);
+
private:
/// is this an exact match at this position?
bool find1(MathArray const & ar, size_type pos) const;
if (s == "vphantom")
return MathAtom(new InsetMathPhantom(InsetMathPhantom::vphantom));
- if (MacroTable::globalMacros().has(s))
- return MathAtom(new MathMacro(s,
- MacroTable::globalMacros().get(s).numargs()));
- //if (MacroTable::localMacros().has(s))
- // return MathAtom(new MathMacro(s,
- // MacroTable::localMacros().get(s).numargs()));
-
- //lyxerr << "creating unknown inset '" << s << "'" << endl;
- return MathAtom(new InsetMathUnknown(s));
+ return MathAtom(new MathMacro(s));
}
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)
{}
* 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.
*/
std::string requires() const { return requires_; }
///
std::string & requires() { return requires_; }
-
+
+ ///
+ int lock() { return ++lockCount_; }
+ ///
+ bool locked() const { return lockCount_!=0; }
+ ///
+ void unlock() { --lockCount_; assert(lockCount_>=0); }
+
private:
///
docstring def_;
docstring disp_;
///
std::string requires_;
+ ///
+ int lockCount_;
};
docstring MathMacroTemplate::prefix() const
{
- return bformat(_(" Macro: %1$s: "), name_);
+ return bformat(_(" Macro \\%1$s: "), name_);
}