#include "Buffer.h"
#include "BufferView.h"
+#include "CoordCache.h"
#include "Cursor.h"
#include "support/debug.h"
#include "LaTeXFeatures.h"
///
void metrics(MetricsInfo & mi, Dimension & dim) const {
mathMacro_.macro()->unlock();
- mathMacro_.cell(idx_).metrics(mi, dim);
- if (!mathMacro_.editing() && !def_.empty())
+ if (!mathMacro_.editMetrics(mi.base.bv)
+ && mathMacro_.cell(idx_).empty())
def_.metrics(mi, dim);
+ else {
+ CoordCache & coords = mi.base.bv->coordCache();
+ dim = coords.arrays().dim(&mathMacro_.cell(idx_));
+ }
mathMacro_.macro()->lock();
}
///
void draw(PainterInfo & pi, int x, int y) const {
- if (mathMacro_.editing()) {
+ if (mathMacro_.editMetrics(pi.base.bv)) {
// The only way a ArgumentProxy can appear is in a cell of the
// MathMacro. Moreover the cells are only drawn in the DISPLAY_FOLDED
- // mode and then, in the case of "editing_ == true" the monochrome
+ // mode and then, if the macro is edited the monochrome
// mode is entered by the MathMacro before calling the cells' draw
// method. Then eventually this code is reached and the proxy leaves
// monochrome mode temporarely. Hence, if it is not in monochrome
pi.pain.leaveMonochromeMode();
mathMacro_.cell(idx_).draw(pi, x, y);
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
- } else {
- if (def_.empty())
- mathMacro_.cell(idx_).draw(pi, x, y);
- else {
- mathMacro_.cell(idx_).setXY(*pi.base.bv, x, y);
- def_.draw(pi, x, y);
- }
- }
+ } else if (mathMacro_.cell(idx_).empty()) {
+ mathMacro_.cell(idx_).setXY(*pi.base.bv, x, y);
+ def_.draw(pi, x, y);
+ } else
+ mathMacro_.cell(idx_).draw(pi, x, y);
}
///
size_t idx() const { return idx_; }
///
- int kerning() const { return mathMacro_.cell(idx_).kerning(); }
+ int kerning(BufferView const * bv) const
+ {
+ if (mathMacro_.editMetrics(bv)
+ || !mathMacro_.cell(idx_).empty())
+ return mathMacro_.cell(idx_).kerning(bv);
+ else
+ return def_.kerning(bv);
+ }
private:
///
MathMacro::MathMacro(docstring const & name)
: InsetMathNest(0), name_(name), displayMode_(DISPLAY_INIT),
- attachedArgsNum_(0), previousCurIdx_(-1),
- optionals_(0), nextFoldMode_(true),
- macro_(0), editing_(false), needsUpdate_(false)
+ attachedArgsNum_(0), optionals_(0), nextFoldMode_(true),
+ macro_(0), needsUpdate_(false)
{}
}
-int MathMacro::cursorIdx(Cursor const & cur) const {
- for (size_t i = 0; i != cur.depth(); ++i)
- if (&cur[i].inset() == this)
- return cur[i].idx();
- return -1;
-}
-
-
-bool MathMacro::editMode(Cursor const & cur) const {
+bool MathMacro::editMode(BufferView const * bv) const {
// find this in cursor trace
+ Cursor const & cur = bv->cursor();
for (size_t i = 0; i != cur.depth(); ++i)
if (&cur[i].inset() == this) {
// look if there is no other macro in edit mode above
}
+bool MathMacro::editMetrics(BufferView const * bv) const
+{
+ return editing_[bv];
+}
+
+
void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
{
+ // set edit mode for which we will have calculated metrics. But only
+ editing_[mi.base.bv] = editMode(mi.base.bv);
+
// calculate new metrics according to display mode
if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_INTERACTIVE_INIT) {
mathed_string_dim(mi.base.font, from_ascii("\\") + name(), dim);
} else {
BOOST_ASSERT(macro_ != 0);
- // calculate metric finally
+ // metrics are computed here for the cells,
+ // in the proxy we will then use the dim from the cache
+ InsetMathNest::metrics(mi);
+
+ // calculate metrics finally
macro_->lock();
expanded_.cell(0).metrics(mi, dim);
macro_->unlock();
// calculate dimension with label while editing
- if (editing_) {
+ if (editing_[mi.base.bv]) {
FontInfo font = mi.base.font;
augmentFont(font, from_ascii("lyxtex"));
Dimension namedim;
dim.des += 2;
}
}
-
- // Cache the inset dimension.
- setDimCache(mi, dim);
}
-int MathMacro::kerning() const {
- if (displayMode_ == DISPLAY_NORMAL && !editing_)
- return expanded_.kerning();
+int MathMacro::kerning(BufferView const * bv) const {
+ if (displayMode_ == DISPLAY_NORMAL && !editing_[bv])
+ return expanded_.kerning(bv);
else
return 0;
}
void MathMacro::updateRepresentation(Cursor const * bvCur)
{
- // index of child where the cursor is (or -1 if none is edited)
- int curIdx = -1;
- if (bvCur)
- curIdx = cursorIdx(*bvCur);
- previousCurIdx_ = curIdx;
-
// known macro?
if (macro_ == 0)
return;
if (displayMode_ != DISPLAY_NORMAL)
return;
- // set edit mode to draw box around if needed
- bool prevEditing = editing_;
- editing_ = false;
- if (bvCur)
- editing_ = editMode(*bvCur);
-
- // editMode changed and we have to switch default value and hole of optional?
- if (optionals_ > 0 && nargs() > 0 &&
- prevEditing != editing_)
- needsUpdate_ = true;
-
// macro changed?
if (needsUpdate_) {
needsUpdate_ = false;
vector<MathData> values(nargs());
for (size_t i = 0; i < nargs(); ++i) {
ArgumentProxy * proxy;
- if (!cell(i).empty()
- || i >= defaults.size()
- || defaults[i].empty()
- || curIdx == (int)i)
- proxy = new ArgumentProxy(*this, i);
- else
+ 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
macro_->expand(values, expanded_.cell(0));
- }
+ }
}
for (size_t i = 0; i < nargs(); ++i)
cell(i).setXY(*pi.base.bv, x, y);
- if (editing_) {
+ if (editing_[pi.base.bv]) {
// draw header and rectangle around
FontInfo font = pi.base.font;
augmentFont(font, from_ascii("lyxtex"));
expanded_.cell(0).draw(pi, expx, expy);
// draw frame while editing
- if (editing_)
+ if (editing_[pi.base.bv])
pi.pain.rectangle(x, y - dim.asc, dim.wid, dim.height(), Color_mathmacroframe);
}
- // another argument selected?
- idx_type curIdx = cursorIdx(pi.base.bv->cursor());
- if (previousCurIdx_ != curIdx || editing_ != editMode(pi.base.bv->cursor()))
+ // edit mode changed?
+ if (editing_[pi.base.bv] != editMode(pi.base.bv))
pi.base.bv->cursor().updateFlags(Update::Force);
}
// normal mode
BOOST_ASSERT(macro_);
+ // optional arguments make macros fragile
+ if (optionals_ > 0 && os.fragile())
+ os << "\\protect";
+
os << "\\" << name();
bool first = true;
- idx_type i = 0;
- // Use macroBackup_ instead of macro_ here, because
- // this is outside the metrics/draw calls, hence the macro_
- // variable can point to a MacroData which was freed already.
- vector<docstring> const & defaults = macroBackup_.defaults();
+ // Optional arguments:
+ // First find last non-empty optional argument
+ idx_type emptyOptFrom = 0;
+ idx_type i = 0;
+ for (; i < cells_.size() && i < optionals_; ++i) {
+ if (!cell(i).empty())
+ emptyOptFrom = i + 1;
+ }
- // Optional argument
- if (os.latex()) {
- // Print first optional in LaTeX semantics
- if (i < optionals_) {
- // the first real optional, the others are non-optional in latex
- if (!cell(i).empty()) {
- first = false;
- os << "[" << cell(0) << "]";
- }
-
- ++i;
- }
- } else {
- // In lyx mode print all in any case
- for (; i < cells_.size() && i < optionals_; ++i) {
- first = false;
- os << "[" << cell(i) << "]";
- }
+ // print out optionals
+ for (i=0; i < cells_.size() && i < emptyOptFrom; ++i) {
+ first = false;
+ os << "[" << cell(i) << "]";
}
-
+
+ // skip the tailing empty optionals
+ i = optionals_;
+
// Print remaining macros
- // (also the further optional parameters in LaTeX mode!)
for (; i < cells_.size(); ++i) {
- if (cell(i).empty() && i < optionals_)
- os << "{" << defaults[i] << "}";
- else if (cell(i).size() == 1
+ if (cell(i).size() == 1
&& cell(i)[0].nucleus()->asCharInset()) {
if (first)
os << " ";