2003-08-19 13:00:56 +00:00
|
|
|
|
/**
|
2007-04-25 16:11:45 +00:00
|
|
|
|
* \file MathMacro.cpp
|
2003-08-19 13:00:56 +00:00
|
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
|
* Licence details can be found in the file COPYING.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
*
|
2003-08-19 13:00:56 +00:00
|
|
|
|
* \author Alejandro Aguilar Sierra
|
|
|
|
|
* \author Andr<EFBFBD> P<EFBFBD>nitz
|
2007-11-01 11:13:07 +00:00
|
|
|
|
* \author Stefan Schimanski
|
1999-09-27 18:44:28 +00:00
|
|
|
|
*
|
2003-08-19 13:00:56 +00:00
|
|
|
|
* Full author contact details are available in file CREDITS.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2003-08-02 11:30:30 +00:00
|
|
|
|
#include <config.h>
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2007-04-25 16:11:45 +00:00
|
|
|
|
#include "MathMacro.h"
|
2006-09-17 09:14:18 +00:00
|
|
|
|
#include "MathSupport.h"
|
|
|
|
|
#include "MathExtern.h"
|
2006-10-22 10:15:23 +00:00
|
|
|
|
#include "MathStream.h"
|
2004-04-13 06:27:29 +00:00
|
|
|
|
|
2007-04-26 04:41:58 +00:00
|
|
|
|
#include "Buffer.h"
|
2007-11-01 11:13:07 +00:00
|
|
|
|
#include "BufferView.h"
|
2007-04-26 14:56:30 +00:00
|
|
|
|
#include "Cursor.h"
|
2001-11-16 08:26:41 +00:00
|
|
|
|
#include "debug.h"
|
2001-07-13 14:54:56 +00:00
|
|
|
|
#include "LaTeXFeatures.h"
|
2007-11-01 11:13:07 +00:00
|
|
|
|
#include "FuncStatus.h"
|
|
|
|
|
#include "FuncRequest.h"
|
|
|
|
|
#include "Undo.h"
|
|
|
|
|
|
2005-07-17 10:31:44 +00:00
|
|
|
|
#include "frontends/Painter.h"
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
#include <vector>
|
2006-10-21 00:16:43 +00:00
|
|
|
|
|
|
|
|
|
namespace lyx {
|
2006-08-13 22:54:59 +00:00
|
|
|
|
|
2003-10-06 15:43:21 +00:00
|
|
|
|
using std::string;
|
2002-02-16 15:59:55 +00:00
|
|
|
|
using std::max;
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
/// A proxy for the macro values
|
|
|
|
|
class ArgumentProxy : public InsetMath {
|
2007-04-17 16:52:43 +00:00
|
|
|
|
public:
|
|
|
|
|
///
|
2007-11-01 11:13:07 +00:00
|
|
|
|
ArgumentProxy(MathMacro & mathMacro, size_t idx)
|
2007-05-24 16:29:40 +00:00
|
|
|
|
: mathMacro_(mathMacro), idx_(idx) {}
|
2007-04-17 16:52:43 +00:00
|
|
|
|
///
|
2007-11-01 11:13:07 +00:00
|
|
|
|
ArgumentProxy(MathMacro & mathMacro, size_t idx, docstring const & def)
|
|
|
|
|
: mathMacro_(mathMacro), idx_(idx)
|
|
|
|
|
{
|
|
|
|
|
asArray(def, def_);
|
|
|
|
|
}
|
|
|
|
|
///
|
|
|
|
|
void metrics(MetricsInfo & mi, Dimension & dim) const {
|
|
|
|
|
mathMacro_.macro()->unlock();
|
|
|
|
|
mathMacro_.cell(idx_).metrics(mi, dim);
|
|
|
|
|
if (!mathMacro_.editing() && !def_.empty())
|
|
|
|
|
def_.metrics(mi, dim);
|
|
|
|
|
mathMacro_.macro()->lock();
|
|
|
|
|
}
|
|
|
|
|
///
|
|
|
|
|
void draw(PainterInfo & pi, int x, int y) const {
|
|
|
|
|
if (mathMacro_.editing()) {
|
2007-11-08 10:14:18 +00:00
|
|
|
|
// 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 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
|
|
|
|
|
// here (and the assert triggers in pain.leaveMonochromeMode())
|
|
|
|
|
// it's a bug.
|
2007-11-01 11:13:07 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-04-17 16:52:43 +00:00
|
|
|
|
///
|
2007-11-01 11:13:07 +00:00
|
|
|
|
size_t idx() const { return idx_; }
|
2007-06-15 18:26:35 +00:00
|
|
|
|
///
|
|
|
|
|
int kerning() const { return mathMacro_.cell(idx_).kerning(); }
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-04-17 16:52:43 +00:00
|
|
|
|
private:
|
2007-11-01 11:13:07 +00:00
|
|
|
|
///
|
|
|
|
|
Inset * clone() const
|
|
|
|
|
{
|
|
|
|
|
return new ArgumentProxy(*this);
|
|
|
|
|
}
|
|
|
|
|
///
|
|
|
|
|
MathMacro & mathMacro_;
|
|
|
|
|
///
|
2007-05-24 16:29:40 +00:00
|
|
|
|
size_t idx_;
|
2007-11-01 11:13:07 +00:00
|
|
|
|
///
|
|
|
|
|
MathData def_;
|
2007-04-17 16:52:43 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
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)
|
2001-07-12 11:55:57 +00:00
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
2007-08-30 18:03:17 +00:00
|
|
|
|
Inset * MathMacro::clone() const
|
1999-09-27 18:44:28 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
MathMacro * copy = new MathMacro(*this);
|
|
|
|
|
copy->needsUpdate_ = true;
|
|
|
|
|
copy->expanded_.cell(0).clear();
|
|
|
|
|
return copy;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-08-09 09:19:18 +00:00
|
|
|
|
|
2006-10-22 10:15:23 +00:00
|
|
|
|
docstring MathMacro::name() const
|
2001-08-08 17:26:30 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_UNFOLDED)
|
|
|
|
|
return asString(cell(0));
|
|
|
|
|
else
|
|
|
|
|
return name_;
|
2001-08-08 17:26:30 +00:00
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2001-08-09 09:19:18 +00:00
|
|
|
|
|
2006-10-17 16:23:27 +00:00
|
|
|
|
void MathMacro::cursorPos(BufferView const & bv,
|
|
|
|
|
CursorSlice const & sl, bool boundary, int & x, int & y) const
|
2005-10-05 21:19:32 +00:00
|
|
|
|
{
|
2006-09-16 18:11:38 +00:00
|
|
|
|
// We may have 0 arguments, but InsetMathNest requires at least one.
|
2005-10-05 21:19:32 +00:00
|
|
|
|
if (nargs() > 0)
|
2006-10-17 16:23:27 +00:00
|
|
|
|
InsetMathNest::cursorPos(bv, sl, boundary, x, y);
|
2005-10-05 21:19:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
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 {
|
|
|
|
|
// find this in cursor trace
|
|
|
|
|
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
|
|
|
|
|
++i;
|
|
|
|
|
for (; i != cur.depth(); ++i) {
|
|
|
|
|
MathMacro const * macro = dynamic_cast<MathMacro const *>(&cur[i].inset());
|
|
|
|
|
if (macro && macro->displayMode() == DISPLAY_NORMAL)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ok, none found, I am the highest one
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-09-21 20:39:47 +00:00
|
|
|
|
void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
|
2002-03-25 12:11:25 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
// calculate new metrics according to display mode
|
2007-11-01 14:40:15 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_NONGREEDY_INIT) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
mathed_string_dim(mi.base.font, from_ascii("\\") + name(), dim);
|
|
|
|
|
} else if (displayMode_ == DISPLAY_UNFOLDED) {
|
|
|
|
|
cell(0).metrics(mi, dim);
|
|
|
|
|
Dimension bsdim;
|
|
|
|
|
mathed_string_dim(mi.base.font, from_ascii("\\"), bsdim);
|
|
|
|
|
dim.wid += bsdim.width() + 1;
|
|
|
|
|
dim.asc = std::max(bsdim.ascent(), dim.ascent());
|
|
|
|
|
dim.des = std::max(bsdim.descent(), dim.descent());
|
|
|
|
|
metricsMarkers(dim);
|
2004-04-13 13:54:58 +00:00
|
|
|
|
} else {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
BOOST_ASSERT(macro_ != 0);
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
// calculate metric finally
|
|
|
|
|
macro_->lock();
|
|
|
|
|
expanded_.cell(0).metrics(mi, dim);
|
|
|
|
|
macro_->unlock();
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
// calculate dimension with label while editing
|
|
|
|
|
if (editing_) {
|
2007-10-28 18:51:54 +00:00
|
|
|
|
FontInfo font = mi.base.font;
|
2007-04-17 16:52:43 +00:00
|
|
|
|
augmentFont(font, from_ascii("lyxtex"));
|
2007-11-01 11:13:07 +00:00
|
|
|
|
Dimension namedim;
|
|
|
|
|
mathed_string_dim(font, name(), namedim);
|
|
|
|
|
#if 0
|
|
|
|
|
dim.wid += 2 + namedim.wid + 2 + 2;
|
|
|
|
|
dim.asc = std::max(dim.asc, namedim.asc) + 2;
|
|
|
|
|
dim.des = std::max(dim.des, namedim.des) + 2;
|
|
|
|
|
#endif
|
|
|
|
|
dim.wid = std::max(1 + namedim.wid + 1, 2 + dim.wid + 2);
|
|
|
|
|
dim.asc += 1 + namedim.height() + 1;
|
|
|
|
|
dim.des += 2;
|
2007-04-17 16:52:43 +00:00
|
|
|
|
}
|
2004-04-13 13:54:58 +00:00
|
|
|
|
}
|
2007-11-01 11:13:07 +00:00
|
|
|
|
|
2007-09-23 22:39:49 +00:00
|
|
|
|
// Cache the inset dimension.
|
|
|
|
|
setDimCache(mi, dim);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
int MathMacro::kerning() const {
|
|
|
|
|
if (displayMode_ == DISPLAY_NORMAL && !editing_)
|
|
|
|
|
return expanded_.kerning();
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MathMacro::updateMacro(MetricsInfo & mi)
|
2000-02-10 17:53:36 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (validName() && mi.macrocontext.has(name())) {
|
|
|
|
|
macro_ = &mi.macrocontext.get(name());
|
|
|
|
|
if (macroBackup_ != *macro_) {
|
|
|
|
|
macroBackup_ = *macro_;
|
|
|
|
|
needsUpdate_ = true;
|
|
|
|
|
}
|
2004-04-13 13:54:58 +00:00
|
|
|
|
} else {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
macro_ = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
|
|
|
|
|
void MathMacro::updateRepresentation(MetricsInfo & mi)
|
|
|
|
|
{
|
|
|
|
|
// index of child where the cursor is (or -1 if none is edited)
|
|
|
|
|
int curIdx = cursorIdx(mi.base.bv->cursor());
|
|
|
|
|
previousCurIdx_ = curIdx;
|
|
|
|
|
|
|
|
|
|
// known macro?
|
|
|
|
|
if (macro_) {
|
|
|
|
|
requires_ = macro_->requires();
|
|
|
|
|
|
|
|
|
|
if (displayMode_ == DISPLAY_NORMAL) {
|
|
|
|
|
// set edit mode to draw box around if needed
|
|
|
|
|
bool prevEditing = editing_;
|
|
|
|
|
editing_ = editMode(mi.base.bv->cursor());
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
// get default values of macro
|
|
|
|
|
std::vector<docstring> const & defaults = macro_->defaults();
|
|
|
|
|
|
|
|
|
|
// create MathMacroArgumentValue objects pointing to the cells of the macro
|
|
|
|
|
std::vector<MathData> values(nargs());
|
|
|
|
|
for (size_t i = 0; i < nargs(); ++i) {
|
|
|
|
|
if (!cell(i).empty() || i >= defaults.size() ||
|
|
|
|
|
defaults[i].empty() || curIdx == (int)i)
|
|
|
|
|
values[i].insert(0, MathAtom(new ArgumentProxy(*this, i)));
|
|
|
|
|
else
|
|
|
|
|
values[i].insert(0, MathAtom(new ArgumentProxy(*this, i, defaults[i])));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// expanding macro with the values
|
|
|
|
|
macro_->expand(values, expanded_.cell(0));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MathMacro::draw(PainterInfo & pi, int x, int y) const
|
|
|
|
|
{
|
|
|
|
|
Dimension const dim = dimension(*pi.base.bv);
|
|
|
|
|
|
|
|
|
|
setPosCache(pi, x, y);
|
|
|
|
|
int expx = x;
|
|
|
|
|
int expy = y;
|
|
|
|
|
|
2007-11-01 14:40:15 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_NONGREEDY_INIT) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
PainterInfo pi2(pi.base.bv, pi.pain);
|
|
|
|
|
pi2.base.font.setColor(macro_ ? Color_latex : Color_error);
|
|
|
|
|
//pi2.base.style = LM_ST_TEXT;
|
|
|
|
|
pi2.pain.text(x, y, from_ascii("\\") + name(), pi2.base.font);
|
|
|
|
|
} else if (displayMode_ == DISPLAY_UNFOLDED) {
|
|
|
|
|
PainterInfo pi2(pi.base.bv, pi.pain);
|
|
|
|
|
pi2.base.font.setColor(macro_ ? Color_latex : Color_error);
|
|
|
|
|
//pi2.base.style = LM_ST_TEXT;
|
|
|
|
|
pi2.pain.text(x, y, from_ascii("\\"), pi2.base.font);
|
|
|
|
|
x += mathed_string_width(pi2.base.font, from_ascii("\\")) + 1;
|
|
|
|
|
cell(0).draw(pi2, x, y);
|
|
|
|
|
drawMarkers(pi2, expx, expy);
|
|
|
|
|
} else {
|
|
|
|
|
// warm up cells
|
2007-05-24 16:29:40 +00:00
|
|
|
|
for (size_t i = 0; i < nargs(); ++i)
|
|
|
|
|
cell(i).setXY(*pi.base.bv, x, y);
|
2007-05-28 22:27:45 +00:00
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (editing_) {
|
|
|
|
|
// draw header and rectangle around
|
2007-10-28 18:51:54 +00:00
|
|
|
|
FontInfo font = pi.base.font;
|
2007-04-17 16:52:43 +00:00
|
|
|
|
augmentFont(font, from_ascii("lyxtex"));
|
2007-11-01 11:13:07 +00:00
|
|
|
|
font.setSize(FONT_SIZE_TINY);
|
|
|
|
|
font.setColor(Color_mathmacrolabel);
|
|
|
|
|
Dimension namedim;
|
|
|
|
|
mathed_string_dim(font, name(), namedim);
|
|
|
|
|
#if 0
|
|
|
|
|
pi.pain.fillRectangle(x, y - dim.asc, 2 + namedim.width() + 2, dim.height(), Color_mathmacrobg);
|
|
|
|
|
pi.pain.text(x + 2, y, name(), font);
|
|
|
|
|
expx += 2 + namew + 2;
|
|
|
|
|
#endif
|
|
|
|
|
pi.pain.fillRectangle(x, y - dim.asc, dim.wid, 1 + namedim.height() + 1, Color_mathmacrobg);
|
|
|
|
|
pi.pain.text(x + 1, y - dim.asc + namedim.asc + 2, name(), font);
|
|
|
|
|
expx += (dim.wid - expanded_.cell(0).dimension(*pi.base.bv).width()) / 2;
|
|
|
|
|
|
|
|
|
|
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
|
|
|
|
|
expanded_.cell(0).draw(pi, expx, expy);
|
|
|
|
|
pi.pain.leaveMonochromeMode();
|
|
|
|
|
} else
|
|
|
|
|
expanded_.cell(0).draw(pi, expx, expy);
|
|
|
|
|
|
|
|
|
|
// draw frame while editing
|
|
|
|
|
if (editing_)
|
|
|
|
|
pi.pain.rectangle(x, y - dim.asc, dim.wid, dim.height(), Color_mathmacroframe);
|
2004-04-13 13:54:58 +00:00
|
|
|
|
}
|
2007-11-01 11:13:07 +00:00
|
|
|
|
|
|
|
|
|
// another argument selected?
|
2007-11-01 15:36:27 +00:00
|
|
|
|
idx_type curIdx = cursorIdx(pi.base.bv->cursor());
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (previousCurIdx_ != curIdx || editing_ != editMode(pi.base.bv->cursor()))
|
|
|
|
|
pi.base.bv->cursor().updateFlags(Update::Force);
|
2001-04-24 16:13:38 +00:00
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2001-04-25 15:43:57 +00:00
|
|
|
|
|
2005-10-05 21:19:32 +00:00
|
|
|
|
void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
|
|
|
|
|
{
|
2006-09-16 18:11:38 +00:00
|
|
|
|
// We may have 0 arguments, but InsetMathNest requires at least one.
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (cells_.size() > 0)
|
2006-09-16 18:11:38 +00:00
|
|
|
|
InsetMathNest::drawSelection(pi, x, y);
|
2005-10-05 21:19:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::setDisplayMode(MathMacro::DisplayMode mode)
|
|
|
|
|
{
|
|
|
|
|
if (displayMode_ != mode) {
|
|
|
|
|
// transfer name if changing from or to DISPLAY_UNFOLDED
|
|
|
|
|
if (mode == DISPLAY_UNFOLDED) {
|
|
|
|
|
cells_.resize(1);
|
|
|
|
|
asArray(name_, cell(0));
|
|
|
|
|
} else if (displayMode_ == DISPLAY_UNFOLDED) {
|
|
|
|
|
name_ = asString(cell(0));
|
|
|
|
|
cells_.resize(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
displayMode_ = mode;
|
|
|
|
|
needsUpdate_ = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MathMacro::DisplayMode MathMacro::computeDisplayMode(MetricsInfo const & mi) const
|
|
|
|
|
{
|
|
|
|
|
if (nextFoldMode_ == true && macro_ && !macro_->locked())
|
|
|
|
|
return DISPLAY_NORMAL;
|
|
|
|
|
else
|
|
|
|
|
return DISPLAY_UNFOLDED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MathMacro::validName() const
|
|
|
|
|
{
|
|
|
|
|
docstring n = name();
|
|
|
|
|
|
|
|
|
|
// empty name?
|
|
|
|
|
if (n.size() == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// converting back and force doesn't swallow anything?
|
|
|
|
|
/*MathData ma;
|
|
|
|
|
asArray(n, ma);
|
|
|
|
|
if (asString(ma) != n)
|
|
|
|
|
return false;*/
|
|
|
|
|
|
|
|
|
|
// valid characters?
|
|
|
|
|
for (size_t i = 0; i<n.size(); ++i) {
|
|
|
|
|
if (!(n[i] >= 'a' && n[i] <= 'z') &&
|
|
|
|
|
!(n[i] >= 'A' && n[i] <= 'Z'))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-07-26 06:56:43 +00:00
|
|
|
|
void MathMacro::validate(LaTeXFeatures & features) const
|
2001-07-13 14:54:56 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (!requires_.empty())
|
|
|
|
|
features.require(requires_);
|
2007-05-04 15:30:27 +00:00
|
|
|
|
|
2002-04-03 10:45:32 +00:00
|
|
|
|
if (name() == "binom" || name() == "mathcircumflex")
|
2006-10-22 10:15:23 +00:00
|
|
|
|
features.require(to_utf8(name()));
|
2001-07-13 14:54:56 +00:00
|
|
|
|
}
|
2001-11-16 08:26:41 +00:00
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::edit(Cursor & cur, bool left)
|
|
|
|
|
{
|
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
InsetMathNest::edit(cur, left);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-29 13:39:47 +00:00
|
|
|
|
Inset * MathMacro::editXY(Cursor & cur, int x, int y)
|
2005-10-05 21:19:32 +00:00
|
|
|
|
{
|
2006-09-16 18:11:38 +00:00
|
|
|
|
// We may have 0 arguments, but InsetMathNest requires at least one.
|
2007-04-17 16:49:17 +00:00
|
|
|
|
if (nargs() > 0) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
return InsetMathNest::editXY(cur, x, y);
|
|
|
|
|
} else
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 15:36:27 +00:00
|
|
|
|
void MathMacro::removeArgument(Inset::pos_type pos) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_NORMAL) {
|
2007-11-01 15:36:27 +00:00
|
|
|
|
BOOST_ASSERT(size_t(pos) < cells_.size());
|
2007-11-01 11:13:07 +00:00
|
|
|
|
cells_.erase(cells_.begin() + pos);
|
2007-11-01 15:36:27 +00:00
|
|
|
|
if (size_t(pos) < attachedArgsNum_)
|
2007-11-01 11:13:07 +00:00
|
|
|
|
--attachedArgsNum_;
|
2007-11-01 15:36:27 +00:00
|
|
|
|
if (size_t(pos) < optionals_) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
--optionals_;
|
2007-04-17 16:49:17 +00:00
|
|
|
|
}
|
2007-11-01 11:13:07 +00:00
|
|
|
|
|
|
|
|
|
needsUpdate_ = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 15:36:27 +00:00
|
|
|
|
void MathMacro::insertArgument(Inset::pos_type pos) {
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_NORMAL) {
|
2007-11-01 15:36:27 +00:00
|
|
|
|
BOOST_ASSERT(size_t(pos) <= cells_.size());
|
2007-11-01 11:13:07 +00:00
|
|
|
|
cells_.insert(cells_.begin() + pos, MathData());
|
2007-11-01 15:36:27 +00:00
|
|
|
|
if (size_t(pos) < attachedArgsNum_)
|
2007-11-01 11:13:07 +00:00
|
|
|
|
++attachedArgsNum_;
|
2007-11-01 15:36:27 +00:00
|
|
|
|
if (size_t(pos) < optionals_)
|
2007-11-01 11:13:07 +00:00
|
|
|
|
++optionals_;
|
|
|
|
|
|
|
|
|
|
needsUpdate_ = true;
|
2007-04-17 16:49:17 +00:00
|
|
|
|
}
|
2005-10-05 21:19:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::detachArguments(std::vector<MathData> & args, bool strip)
|
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(displayMode_ == DISPLAY_NORMAL);
|
|
|
|
|
args = cells_;
|
|
|
|
|
|
|
|
|
|
// strip off empty cells, but not more than arity-attachedArgsNum_
|
|
|
|
|
if (strip) {
|
|
|
|
|
size_t i;
|
|
|
|
|
for (i = cells_.size(); i > attachedArgsNum_; --i)
|
|
|
|
|
if (!cell(i - 1).empty()) break;
|
|
|
|
|
args.resize(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attachedArgsNum_ = 0;
|
|
|
|
|
expanded_.cell(0) = MathData();
|
|
|
|
|
cells_.resize(0);
|
|
|
|
|
|
|
|
|
|
needsUpdate_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MathMacro::attachArguments(std::vector<MathData> const & args, size_t arity, int optionals)
|
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(displayMode_ == DISPLAY_NORMAL);
|
|
|
|
|
cells_ = args;
|
|
|
|
|
attachedArgsNum_ = args.size();
|
|
|
|
|
cells_.resize(arity);
|
|
|
|
|
expanded_.cell(0) = MathData();
|
|
|
|
|
optionals_ = optionals;
|
|
|
|
|
|
|
|
|
|
needsUpdate_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MathMacro::idxFirst(Cursor & cur) const
|
2007-04-16 14:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
return InsetMathNest::idxFirst(cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
bool MathMacro::idxLast(Cursor & cur) const
|
2007-04-16 14:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
return InsetMathNest::idxLast(cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
bool MathMacro::notifyCursorLeaves(Cursor & cur)
|
2007-06-14 20:57:56 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
return InsetMathNest::notifyCursorLeaves(cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MathMacro::fold(Cursor & cur)
|
|
|
|
|
{
|
|
|
|
|
if (!nextFoldMode_) {
|
|
|
|
|
nextFoldMode_ = true;
|
|
|
|
|
cur.updateFlags(Update::Force);
|
2007-06-14 20:57:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::unfold(Cursor & cur)
|
2007-04-16 14:42:53 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (nextFoldMode_) {
|
|
|
|
|
nextFoldMode_ = false;
|
|
|
|
|
cur.updateFlags(Update::Force);
|
|
|
|
|
}
|
2007-04-16 14:42:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
bool MathMacro::folded() const
|
2001-11-16 08:26:41 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
return nextFoldMode_;
|
2001-11-16 08:26:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::write(WriteStream & os) const
|
2001-11-16 08:29:11 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
if (displayMode_ == DISPLAY_NORMAL) {
|
|
|
|
|
BOOST_ASSERT(macro_);
|
|
|
|
|
|
|
|
|
|
os << "\\" << name();
|
|
|
|
|
bool first = true;
|
2007-11-01 15:36:27 +00:00
|
|
|
|
idx_type i = 0;
|
2007-11-01 11:13:07 +00:00
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
std::vector<docstring> const & defaults = macroBackup_.defaults();
|
|
|
|
|
|
|
|
|
|
// Optional argument
|
|
|
|
|
if (os.latex()) {
|
|
|
|
|
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) << "]";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (; i < cells_.size(); ++i) {
|
|
|
|
|
if (cell(i).empty() && i < optionals_) {
|
|
|
|
|
os << "{" << defaults[i] << "}";
|
|
|
|
|
} else if (cell(i).size() == 1 && cell(i)[0].nucleus()->asCharInset()) {
|
|
|
|
|
if (first)
|
|
|
|
|
os << " ";
|
|
|
|
|
os << cell(i);
|
|
|
|
|
} else
|
|
|
|
|
os << "{" << cell(i) << "}";
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
if (first)
|
|
|
|
|
os.pendingSpace(true);
|
|
|
|
|
} else {
|
|
|
|
|
os << "\\" << name() << " ";
|
|
|
|
|
os.pendingSpace(true);
|
|
|
|
|
}
|
2001-11-16 08:29:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::maple(MapleStream & os) const
|
|
|
|
|
{
|
|
|
|
|
lyx::maple(expanded_.cell(0), os);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MathMacro::mathmlize(MathStream & os) const
|
2001-11-16 08:29:11 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
lyx::mathmlize(expanded_.cell(0), os);
|
2001-11-16 08:26:41 +00:00
|
|
|
|
}
|
2001-12-11 11:33:43 +00:00
|
|
|
|
|
|
|
|
|
|
2007-11-01 11:13:07 +00:00
|
|
|
|
void MathMacro::octave(OctaveStream & os) const
|
2007-04-17 16:49:17 +00:00
|
|
|
|
{
|
2007-11-01 11:13:07 +00:00
|
|
|
|
lyx::octave(expanded_.cell(0), os);
|
2007-04-17 16:49:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-10-22 10:15:23 +00:00
|
|
|
|
void MathMacro::infoize(odocstream & os) const
|
2003-01-07 11:24:43 +00:00
|
|
|
|
{
|
|
|
|
|
os << "Macro: " << name();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-10-22 10:15:23 +00:00
|
|
|
|
void MathMacro::infoize2(odocstream & os) const
|
2003-01-07 11:24:43 +00:00
|
|
|
|
{
|
|
|
|
|
os << "Macro: " << name();
|
2007-04-17 16:49:17 +00:00
|
|
|
|
|
2003-01-07 11:24:43 +00:00
|
|
|
|
}
|
2006-10-21 00:16:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace lyx
|