#include "debug.h"
#include "array.h"
#include "mathed/support.h"
+#include "support/LAssert.h"
using std::ostream;
using std::endl;
void MathArray::substitute(MathMacro const & m)
{
for (iterator it = begin(); it != end(); ++it)
- it->substitute(m);
+ it->nucleus()->substitute(m);
}
-MathAtom * MathArray::at(size_type pos)
+MathScriptInset const * MathArray::asScript(const_iterator it) const
{
- return pos < size() ? &bf_[pos] : 0;
+ if (it->nucleus()->asScriptInset())
+ return 0;
+ const_iterator jt = it + 1;
+ if (jt == end())
+ return 0;
+ return jt->nucleus()->asScriptInset();
}
-MathAtom const * MathArray::at(size_type pos) const
+MathAtom & MathArray::at(size_type pos)
{
- return pos < size() ? &bf_[pos] : 0;
+ lyx::Assert(pos < size());
+ return bf_[pos];
}
-void MathArray::insert(size_type pos, MathInset * p)
+MathAtom const & MathArray::at(size_type pos) const
{
- //cerr << "\n 1: "; p->write(cerr, true); cerr << p << "\n";
- // inserting here invalidates the pointer!
- bf_.insert(begin() + pos, MathAtom(p));
- //cerr << "\n 2: "; p->write(cerr, true); cerr << p << "\n";
+ lyx::Assert(pos < size());
+ return bf_[pos];
+}
+
+
+void MathArray::insert(size_type pos, MathAtom const & t)
+{
+ bf_.insert(begin() + pos, t);
}
}
-void MathArray::push_back(MathInset * p)
-{
- bf_.push_back(MathAtom(p));
-}
-
-
void MathArray::push_back(MathArray const & array)
{
insert(size(), array);
void MathArray::dump2(ostream & os) const
{
for (const_iterator it = begin(); it != end(); ++it)
- os << *it << ' ';
+ os << it->nucleus() << ' ';
}
void MathArray::dump(ostream & os) const
{
for (const_iterator it = begin(); it != end(); ++it)
- os << "<" << *it << ">";
+ os << "<" << it->nucleus() << ">";
}
if (!it->nucleus())
break;
p = it->nucleus()->asCharInset();
- if (!p || it->up() || it->down() || p->code() != c)
+ if (!p || p->code() != c)
break;
s += p->getChar();
}
void MathArray::write(ostream & os, bool fragile) const
{
- for (const_iterator it = begin(); it != end(); ++it) {
- if (it->nucleus() && it->nucleus()->asCharInset()
- && !it->up() && !it->down())
- {
- MathCharInset const * p = it->nucleus()->asCharInset();
+ for (const_iterator it = begin(); it != end(); ++it) {
+ MathInset * p = it->nucleus();
+ if (!p)
+ continue;
+
+/*
+ if (p->asCharInset()) {
+ MathCharInset const * c = p->asCharInset();
// special handling for character sequences with the same code
string s = charSequence(it, end());
- p->writeHeader(os);
+ c->writeHeader(os);
os << s;
- p->writeTrailer(os);
+ c->writeTrailer(os);
it += s.size() - 1;
+ } else
+*/
+ if (MathScriptInset const * q = asScript(it)) {
+ q->write(p, os, fragile);
+ ++it;
} else {
- it->write(os, fragile);
+ p->write(os, fragile);
}
}
}
void MathArray::validate(LaTeXFeatures & features) const
{
for (const_iterator it = begin(); it != end(); ++it)
- it->validate(features);
+ it->nucleus()->validate(features);
}
#include <iosfwd>
#include "math_atom.h"
-class MathInset;
+class MathScriptInset;
class MathMacro;
class LaTeXFeatures;
void swap(MathArray &);
///
- void insert(size_type pos, MathInset * inset);
+ void insert(size_type pos, MathAtom const &);
///
void insert(size_type pos, MathArray const &);
void erase();
///
- void push_back(MathInset * inset);
+ void push_back(MathAtom const &);
///
void push_back(MathArray const &);
///
- void push_back(MathAtom const &);
- ///
void pop_back();
///
MathAtom & back();
void substitute(MathMacro const &);
///
- MathAtom * at(size_type pos);
+ MathAtom & at(size_type pos);
///
- MathAtom const * at(size_type pos) const;
+ MathAtom const & at(size_type pos) const;
///
void write(std::ostream &, bool) const;
///
iterator begin();
///
iterator end();
+ ///
+ MathScriptInset const * asScript(const_iterator it) const;
private:
/// Buffer
buffer_type bf_;
#include "debug.h"
#include "lyx_gui_misc.h"
#include "support/LOstream.h"
+#include "support/LAssert.h"
#include "support/lyxlib.h"
#include "support/syscall.h"
#include "support/lstrings.h"
InsetFormula::InsetFormula()
- : par_(new MathMatrixInset)
-{}
-
-
-InsetFormula::InsetFormula(const InsetFormula & f)
- : InsetFormulaBase(f), par_(static_cast<MathMatrixInset *>(f.par_->clone()))
+ : par_(MathAtom(new MathMatrixInset))
{}
InsetFormula::InsetFormula(MathInsetTypes t)
- : par_(new MathMatrixInset(t))
+ : par_(MathAtom(new MathMatrixInset(t)))
{}
InsetFormula::InsetFormula(string const & s)
- : par_(mathed_parse_normal(s))
{
- if (!par_)
- par_ = mathed_parse_normal("$" + s + "$");
+ if (s.size()) {
+ bool res = mathed_parse_normal(par_, s);
- if (!par_) {
- lyxerr << "cannot interpret '" << s << "' as math\n";
- par_ = new MathMatrixInset(LM_OT_SIMPLE);
+ if (!res)
+ res = mathed_parse_normal(par_, "$" + s + "$");
+
+ if (!res) {
+ lyxerr << "cannot interpret '" << s << "' as math\n";
+ par_ = MathAtom(new MathMatrixInset(LM_OT_SIMPLE));
+ }
}
metrics();
}
-InsetFormula::~InsetFormula()
-{
- delete par_;
-}
-
-
Inset * InsetFormula::clone(Buffer const &, bool) const
{
return new InsetFormula(*this);
void InsetFormula::read(Buffer const *, LyXLex & lex)
{
- par(mathed_parse_normal(lex));
+ mathed_parse_normal(par_, lex);
metrics();
}
vector<string> const InsetFormula::getLabelList() const
{
- return par_->getLabelList();
+ return mat()->getLabelList();
}
//lyxerr << "toggling all numbers\n";
if (display()) {
bv->lockedInsetStoreUndo(Undo::INSERT);
- bool old = par_->numberedType();
+ bool old = mat()->numberedType();
for (MathInset::row_type row = 0; row < par_->nrows(); ++row)
- par_->numbered(row, !old);
+ mat()->numbered(row, !old);
bv->owner()->message(old ? _("No number") : _("Number"));
updateLocal(bv, true);
}
if (display()) {
bv->lockedInsetStoreUndo(Undo::INSERT);
MathCursor::row_type row = mathcursor->row();
- bool old = par_->numbered(row);
+ bool old = mat()->numbered(row);
bv->owner()->message(old ? _("No number") : _("Number"));
- par_->numbered(row, !old);
+ mat()->numbered(row, !old);
updateLocal(bv, true);
}
break;
bv->lockedInsetStoreUndo(Undo::INSERT);
MathCursor::row_type row = mathcursor->row();
- string old_label = par_->label(row);
+ string old_label = mat()->label(row);
string new_label = arg;
if (new_label.empty()) {
if (!new_label.empty()) {
lyxerr << "setting label to '" << new_label << "'\n";
- par_->numbered(row, true);
+ mat()->numbered(row, true);
}
if (!new_label.empty() && bv->ChangeRefsIfUnique(old_label, new_label))
bv->redraw();
- par_->label(row, new_label);
+ mat()->label(row, new_label);
updateLocal(bv, true);
break;
int x;
int y;
mathcursor->getPos(x, y);
- par_->mutate(arg);
+ mat()->mutate(arg);
mathcursor->setPos(x, y);
mathcursor->normalize();
updateLocal(bv, true);
int x;
int y;
mathcursor->getPos(x, y);
- if (par_->getType() == LM_OT_SIMPLE)
- par_->mutate(LM_OT_EQUATION);
+ if (mat()->getType() == LM_OT_SIMPLE)
+ mat()->mutate(LM_OT_EQUATION);
else
- par_->mutate(LM_OT_SIMPLE);
+ mat()->mutate(LM_OT_SIMPLE);
mathcursor->setPos(x, y);
mathcursor->normalize();
updateLocal(bv, true);
{
string const clip = bv->getClipboard();
if (!clip.empty())
- par(mathed_parse_normal(clip));
+ mathed_parse_normal(par_, clip);
break;
}
case LFUN_MATH_COLUMN_INSERT:
{
- if (par_->getType() == LM_OT_ALIGN)
- par_->mutate(LM_OT_ALIGNAT);
- par_->addCol(par_->ncols());
+ if (mat()->getType() == LM_OT_ALIGN)
+ mat()->mutate(LM_OT_ALIGNAT);
+ mat()->addCol(mat()->ncols());
mathcursor->normalize();
updateLocal(bv, true);
}
//string outfile = lyx::tempName("maple.out");
string outfile = "/tmp/lyx2" + arg + ".out";
ostringstream os;
- par_->writeNormal(os);
+ mat()->writeNormal(os);
string code = os.str().c_str();
string script = "lyx2" + arg + " '" + code + "' " + outfile;
lyxerr << "calling: " << script << endl;
Systemcalls cmd(Systemcalls::System, script, 0);
ifstream is(outfile.c_str());
- par(mathed_parse_normal(is));
+ mathed_parse_normal(par_, is);
metrics();
}
+
bool InsetFormula::display() const
{
- return par_->getType() != LM_OT_SIMPLE;
+ return mat()->getType() != LM_OT_SIMPLE;
}
-MathInset const * InsetFormula::par() const
+MathMatrixInset const * InsetFormula::mat() const
{
- return par_;
+ lyx::Assert(par_->asMatrixInset());
+ return par_->asMatrixInset();
}
-void InsetFormula::par(MathMatrixInset * p)
-{
- delete par_;
- par_ = p ? static_cast<MathMatrixInset *>(p) : new MathMatrixInset;
+MathMatrixInset * InsetFormula::mat()
+{
+ lyx::Assert(par_->asMatrixInset());
+ return par_->asMatrixInset();
}
MathInsetTypes InsetFormula::getType() const
{
- return par_->getType();
+ return mat()->getType();
}
#include "mathed/formulabase.h"
#include "math_defs.h"
+#include "math_atom.h"
class MathMatrixInset;
///
InsetFormula();
///
- InsetFormula(InsetFormula const &);
- ///
explicit InsetFormula(MathInsetTypes);
///
explicit InsetFormula(string const &);
///
- ~InsetFormula();
- ///
- void operator=(InsetFormula const &);
- ///
int ascent(BufferView *, LyXFont const &) const;
///
int descent(BufferView *, LyXFont const &) const;
///
void handleExtern(string const & arg, BufferView * bv);
///
- MathInset const * par() const;
- ///
bool display() const;
///
bool ams() const;
///
MathInsetTypes getType() const;
-private:
- /// Safe setting of contents
- void par(MathMatrixInset *);
///
- MathMatrixInset * par_;
+ MathAtom const & par() const { return par_; }
+ ///
+ MathAtom & par() { return par_; }
+public:
+ ///
+ MathAtom par_;
+
+ /// Access
+ MathMatrixInset * mat();
+ /// Access
+ MathMatrixInset const * mat() const;
};
#endif
void InsetFormulaBase::edit(BufferView * bv, int x, int /*y*/, unsigned int)
{
- mathcursor = new MathCursor(this);
-
if (!bv->lockInset(this))
lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl;
+ mathcursor = new MathCursor(this, x == 0);
metrics();
// if that is removed, we won't get the magenta box when entering an
// inset for the first time
bv->updateInset(this, false);
- if (x == 0)
- mathcursor->first();
- else
- mathcursor->last();
sel_x = 0;
sel_y = 0;
sel_flag = false;
case LFUN_VECTOR: handleAccent(bv, "vec"); break;
// Math fonts
- case LFUN_GREEK: handleFont(bv, LM_TC_GREEK1); break;
case LFUN_GREEK_TOGGLE: handleFont(bv, LM_TC_GREEK); break;
case LFUN_BOLD: handleFont(bv, LM_TC_BF); break;
case LFUN_SANS: handleFont(bv, LM_TC_SF); break;
case LFUN_NOUN: handleFont(bv, LM_TC_BB); break;
case LFUN_DEFAULT: handleFont(bv, LM_TC_VAR); break;
+ case LFUN_GREEK:
+ handleFont(bv, LM_TC_GREEK1);
+ if (arg.size())
+ mathcursor->interpret(arg[0]);
+ break;
+
case LFUN_MATH_MODE:
handleFont(bv, LM_TC_TEXTRM);
//bv->owner()->message(_("math text mode toggled"));
// p->incSpace();
//else
// mathcursor->insert(new MathSpaceInset(1));
- mathcursor->insert(new MathSpaceInset(1));
+ mathcursor->insert(MathAtom(new MathSpaceInset(1)));
updateLocal(bv, true);
break;
}
case LFUN_PROTECTEDSPACE:
//lyxerr << " called LFUN_PROTECTEDSPACE\n";
bv->lockedInsetStoreUndo(Undo::INSERT);
- mathcursor->insert(new MathSpaceInset(1));
+ mathcursor->insert(MathAtom(new MathSpaceInset(1)));
updateLocal(bv, true);
break;
if (bv->available()) {
InsetFormula * f = new InsetFormula;
if (openNewInset(bv, f)) {
- bv->theLockingInset()->localDispatch(bv, LFUN_GREEK, string());
- bv->theLockingInset()->localDispatch(bv, LFUN_SELFINSERT, arg);
+ bv->theLockingInset()->localDispatch(bv, LFUN_GREEK, arg);
bv->unlockInset(f);
}
}
class Buffer;
class BufferView;
-class MathInset;
+class MathAtom;
///
class InsetFormulaBase : public UpdatableInset {
///
virtual std::vector<string> const getLabelList() const;
///
- virtual MathInset const * par() const = 0;
+ virtual MathAtom const & par() const = 0;
+ ///
+ virtual MathAtom & par() = 0;
///
virtual void metrics() const = 0;
-protected:
///
virtual void updateLocal(BufferView * bv, bool mark_dirty);
private:
InsetFormulaMacro::InsetFormulaMacro(string nm, int na)
{
setInsetName(nm);
- MathMacroTable::createTemplate(nm, na, string());
+ MathMacroTable::create(nm, na, string());
}
InsetFormulaMacro::InsetFormulaMacro(string const & s)
{
- MathMacroTemplate * t = mathed_parse_macro(s);
- MathMacroTable::insertTemplate(*t);
- setInsetName(t->name());
- delete t;
+ string name = mathed_parse_macro(s);
+ setInsetName(name);
metrics();
}
void InsetFormulaMacro::write(Buffer const *, ostream & os) const
{
os << "FormulaMacro ";
- tmacro().write(os, false);
+ par()->write(os, false);
}
int InsetFormulaMacro::latex(Buffer const *, ostream & os, bool fragile,
bool /*free_spacing*/) const
{
- tmacro().write(os, fragile);
+ par()->write(os, fragile);
return 2;
}
int InsetFormulaMacro::ascii(Buffer const *, ostream & os, int) const
{
- tmacro().write(os, false);
+ par()->write(os, false);
return 0;
}
void InsetFormulaMacro::read(Buffer const *, LyXLex & lex)
{
- MathMacroTemplate * t = mathed_parse_macro(lex);
- if (!t)
- t = new MathMacroTemplate("{parse error}", 0);
- MathMacroTable::insertTemplate(*t);
- setInsetName(t->name());
- delete t;
+ string name = mathed_parse_macro(lex);
+ setInsetName(name);
metrics();
}
string InsetFormulaMacro::prefix() const
{
- return string(" ") + _("Macro: ") + tmacro().name() + ": ";
+ return string(" ") + _("Macro: ") + getInsetName() + ": ";
}
int InsetFormulaMacro::ascent(BufferView *, LyXFont const &) const
{
- return tmacro().ascent() + 5;
+ return par()->ascent() + 5;
}
int InsetFormulaMacro::descent(BufferView *, LyXFont const &) const
{
- return tmacro().descent() + 5;
+ return par()->descent() + 5;
}
int InsetFormulaMacro::width(BufferView *, LyXFont const & f) const
{
metrics();
- return 10 + lyxfont::width(prefix(), f) + tmacro().width();
+ return 10 + lyxfont::width(prefix(), f) + par()->width();
}
case LFUN_MATH_MACROARG: {
int const i = lyx::atoi(arg);
lyxerr << "inserting macro arg " << i << "\n";
- if (i > 0 && i <= tmacro().numargs()) {
- mathcursor->insert(new MathMacroArgument(i));
+ //if (i > 0 && i <= par()->numargs()) {
+ mathcursor->insert(MathAtom(new MathMacroArgument(i)));
updateLocal(bv, true);
- } else {
- lyxerr << "not in range 0.." << tmacro().numargs() << "\n";
- }
+ //} else {
+ // lyxerr << "not in range 0.." << par()->numargs() << "\n";
+ //}
break;
}
}
-MathMacroTemplate const & InsetFormulaMacro::tmacro() const
+MathAtom const & InsetFormulaMacro::par() const
{
- return MathMacroTable::provideTemplate(getInsetName());
+ return MathMacroTable::provide(getInsetName());
}
-Inset::Code InsetFormulaMacro::lyxCode() const
+MathAtom & InsetFormulaMacro::par()
{
- return Inset::MATHMACRO_CODE;
+ return MathMacroTable::provide(getInsetName());
}
-MathInsetTypes InsetFormulaMacro::getType() const
+Inset::Code InsetFormulaMacro::lyxCode() const
{
- return LM_OT_MACRO;
+ return Inset::MATHMACRO_CODE;
}
-MathInset const * InsetFormulaMacro::par() const
+MathInsetTypes InsetFormulaMacro::getType() const
{
- return &tmacro();
+ return LM_OT_MACRO;
}
void InsetFormulaMacro::metrics() const
{
- tmacro().metrics(LM_ST_TEXT);
+ par()->metrics(LM_ST_TEXT);
}
x += width(bv, font);
// formula
- float t = tmacro().width() + 5;
+ float t = par()->width() + 5;
x -= t;
- tmacro().draw(pain, int(x), baseline);
+ par()->draw(pain, int(x), baseline);
x += t;
}
///
MathInsetTypes getType() const;
///
- MathInset const * par() const;
- ///
void metrics() const;
-private:
///
- MathMacroTemplate const & tmacro() const;
+ MathAtom const & par() const;
+ ///
+ MathAtom & par();
+private:
/// prefix in inset
string prefix() const;
};
{}
+MathArrayInset::MathArrayInset(int m, int n, char valign, string const & halign)
+ : MathGridInset(m, n, valign, halign)
+{}
+
+
MathInset * MathArrayInset::clone() const
{
return new MathArrayInset(*this);
///
MathArrayInset(int m, int n);
///
+ MathArrayInset(int m, int n, char valign, string const & halign);
+ ///
MathInset * clone() const;
///
void write(std::ostream &, bool fragile) const;
///
void metrics(MathStyles st) const;
///
- bool isArray() const { return true; }
+ MathArrayInset * asArrayInset() { return this; }
};
#endif
#endif
#include "math_atom.h"
-#include "math_scriptinset.h"
-#include "debug.h"
-#include "support.h"
+#include "math_inset.h"
#include "support/LAssert.h"
MathAtom::MathAtom()
- : nucleus_(0), limits_(0), xo_(0), yo_(0)
-{
- script_[0] = 0;
- script_[1] = 0;
-}
+ : nucleus_(0)
+{}
MathAtom::MathAtom(MathInset * p)
- : nucleus_(p), limits_(0), xo_(0), yo_(0)
-{
- script_[0] = 0;
- script_[1] = 0;
-}
-
-
-MathAtom::MathAtom(MathInset * p, MathScriptInset * up, MathScriptInset * down)
- : nucleus_(p), limits_(0), xo_(0), yo_(0)
-{
- script_[0] = down;
- script_[1] = up;
-}
+ : nucleus_(p)
+{}
MathAtom::MathAtom(MathAtom const & p)
void MathAtom::done()
{
delete nucleus_;
- delete script_[0];
- delete script_[1];
}
void MathAtom::copy(MathAtom const & p)
{
//cerr << "calling MathAtom::copy\n";
- xo_ = p.xo_;
- yo_ = p.yo_;
- limits_ = p.limits_;
nucleus_ = p.nucleus_;
- script_[0] = p.script_[0];
- script_[1] = p.script_[1];
if (nucleus_)
nucleus_ = nucleus_->clone();
- if (script_[0])
- script_[0] = new MathScriptInset(*script_[0]);
- if (script_[1])
- script_[1] = new MathScriptInset(*script_[1]);
}
-int MathAtom::height() const
+MathInset * MathAtom::nucleus() const
{
- return ascent() + descent();
+ lyx::Assert(nucleus_);
+ return nucleus_;
}
-std::ostream & operator<<(std::ostream & os, MathAtom const & atom)
+MathInset * MathAtom::operator->() const
{
- atom.write(os, false);
- return os;
+ return nucleus();
}
-
-int MathAtom::xo() const
-{
- return xo_;
-}
-
-
-int MathAtom::yo() const
-{
- return yo_;
-}
-
-
-void MathAtom::xo(int x) const
-{
- xo_ = x;
-}
-
-
-void MathAtom::yo(int y) const
-{
- yo_ = y;
-}
-
-
-void MathAtom::getXY(int & x, int & y) const
-{
- x = xo();
- y = yo();
-}
-
-
/*
void MathAtom::userSetSize(MathStyles sz)
{
}
}
*/
-
-void MathAtom::writeNormal(std::ostream & os) const
-{
- os << "[unknown] ";
-}
-
-
-void MathAtom::dump() const
-{
- lyxerr << "---------------------------------------------\n";
- write(lyxerr, false);
- lyxerr << "\n---------------------------------------------\n";
-}
-
-
-bool MathAtom::covers(int x, int y) const
-{
- return
- x >= xo_ &&
- x <= xo_ + width() &&
- y >= yo_ - ascent() &&
- y <= yo_ + descent();
-}
-
-
-MathScriptInset * MathAtom::ensure(bool up)
-{
- if (!script_[up])
- script_[up] = new MathScriptInset(up);
- return script_[up];
-}
-
-
-void MathAtom::validate(LaTeXFeatures &) const
-{}
-
-
-void MathAtom::metrics(MathStyles st) const
-{
- MathStyles tt = smallerStyleScript(st);
- if (nucleus())
- nucleus()->metrics(st);
- if (up())
- up()->metrics(tt);
- if (down())
- down()->metrics(tt);
-}
-
-
-MathScriptInset * MathAtom::up() const
-{
- return script_[1];
-}
-
-
-MathScriptInset * MathAtom::down() const
-{
- return script_[0];
-}
-
-
-MathScriptInset * & MathAtom::up()
-{
- return script_[1];
-}
-
-
-MathScriptInset * & MathAtom::down()
-{
- return script_[0];
-}
-
-
-int MathAtom::dy0() const
-{
- if (!down())
- return ndes();
- int des = down()->ascent();
- if (hasLimits())
- des += ndes() + 2;
- else
- des = std::max(des, ndes());
- return des;
-}
-
-
-int MathAtom::dy1() const
-{
- if (!up())
- return nasc();
- int asc = up()->descent();
- if (hasLimits())
- asc += nasc() + 2;
- else
- asc = std::max(asc, nasc());
- asc = std::max(asc, mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I'));
- return asc;
-}
-
-
-int MathAtom::dx0() const
-{
- lyx::Assert(down());
- return hasLimits() ? (width() - down()->width()) / 2 : nwid();
-}
-
-
-int MathAtom::dx1() const
-{
- lyx::Assert(up());
- return hasLimits() ? (width() - up()->width()) / 2 : nwid();
-}
-
-
-int MathAtom::dxx() const
-{
- //lyx::Assert(nucleus());
- return hasLimits() ? (width() - nwid()) / 2 : 0;
-}
-
-
-int MathAtom::ascent() const
-{
- return dy1() + (up() ? up()->ascent() : 0);
-}
-
-
-int MathAtom::descent() const
-{
- return dy0() + (down() ? down()->descent() : 0);
-}
-
-
-int MathAtom::width() const
-{
- int wid = 0;
- if (hasLimits()) {
- wid = nwid();
- if (up())
- wid = std::max(wid, up()->width());
- if (down())
- wid = std::max(wid, down()->width());
- } else {
- if (up())
- wid = std::max(wid, up()->width());
- if (down())
- wid = std::max(wid, down()->width());
- wid += nwid();
- }
- return wid;
-}
-
-
-int MathAtom::nwid() const
-{
- return nucleus() ?
- nucleus()->width() :
- mathed_char_width(LM_TC_TEX, LM_ST_TEXT, '.');
-}
-
-
-int MathAtom::nasc() const
-{
- return nucleus() ? nucleus()->ascent()
- : mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I');
-}
-
-
-int MathAtom::ndes() const
-{
- return nucleus() ? nucleus()->descent()
- : mathed_char_descent(LM_TC_VAR, LM_ST_TEXT, 'I');
-}
-
-
-void MathAtom::draw(Painter & pain, int x, int y) const
-{
- xo(x);
- yo(y);
- if (nucleus())
- nucleus()->draw(pain, x + dxx(), y);
- else
- drawStr(pain, LM_TC_TEX, LM_ST_TEXT, x + dxx(), y, ".");
- if (up())
- up()->draw(pain, x + dx1(), y - dy1());
- if (down())
- down()->draw(pain, x + dx0(), y + dy0());
-}
-
-
-void MathAtom::write(std::ostream & os, bool fragile) const
-{
- if (nucleus()) {
- nucleus()->write(os, fragile);
- if (nucleus()->takesLimits()) {
- if (limits_ == -1)
- os << "\\nolimits ";
- if (limits_ == 1)
- os << "\\limits ";
- }
- } else
- os << "{}";
-
- if (down()) {
- os << "_{";
- down()->write(os, fragile);
- os << "}";
- }
-
- if (up()) {
- os << "^{";
- up()->write(os, fragile);
- os << "}";
- }
-}
-
-
-bool MathAtom::hasLimits() const
-{
- return
- limits_ == 1 || (limits_ == 0 && nucleus() && nucleus()->isScriptable());
-}
-
-
-bool MathAtom::hasInner() const
-{
- return nucleus_ && (script_[0] || script_[1]);
-}
-
-
-void MathAtom::substitute(MathMacro const & m)
-{
- if (nucleus())
- nucleus()->substitute(m);
- if (up())
- up()->substitute(m);
- if (down())
- down()->substitute(m);
-}
-
-
-void MathAtom::removeEmptyScripts()
-{
- for (int i = 0; i <= 1; ++i)
- if (script_[i] && !script_[i]->cell(0).size()) {
- delete script_[i];
- script_[i] = 0;
- }
-}
-
-
-void MathAtom::removeNucleus()
-{
- delete nucleus_;
- nucleus_ = 0;
-}
-
-
-void MathAtom::removeUp()
-{
- delete script_[1];
- script_[1] = 0;
-}
-
-
-void MathAtom::removeDown()
-{
- delete script_[0];
- script_[0] = 0;
-}
#ifndef MATH_ATOM_H
#define MATH_ATOM_H
-#include <config.h>
-#include <iosfwd>
-
#ifdef __GNUG__
#pragma interface
#endif
-#include "math_defs.h"
-
/**
The 'atom' is the major blob in math typesetting. And 'atom' consists
of a nucleus, an optional superscript, and an optional subscript.
Jules
*/
-class LaTeXFeatures;
-class MathCharInset;
-class MathScriptInset;
class MathInset;
-class MathMacro;
-class MathArray;
-class Painter;
class MathAtom {
public:
MathAtom(MathAtom const &);
///
explicit MathAtom(MathInset * p);
- ///
- MathAtom(MathInset * p, MathScriptInset * up, MathScriptInset * down);
///
virtual ~MathAtom();
///
void operator=(MathAtom const &);
///
- void swap(MathAtom &);
-
- /// draw the object, sets xo_ and yo_ cached values
- virtual void draw(Painter &, int x, int y) const;
- /// reproduce itself
- void metrics(MathStyles st) const;
- ///
- int ascent() const;
- ///
- int descent() const;
- ///
- int width() const;
- ///
- int height() const;
-
- ///
- int xo() const;
- ///
- int yo() const;
- ///
- void xo(int tx) const;
- ///
- void yo(int ty) const;
- ///
-
- ///
- void getXY(int & x, int & y) const;
- ///
- bool covers(int x, int y) const;
-
- ///
- void dump() const;
- ///
- void validate(LaTeXFeatures & features) const;
+ MathInset * nucleus() const;
///
- void handleFont(MathTextCodes) {}
+ MathInset * operator->() const;
- /// make sure superscript is available
- MathScriptInset * ensure(bool up);
- /// delete subscript array if empty
- void removeEmptyScripts();
- /// delete nucleus
- void removeNucleus();
- /// delete superscript
- void removeUp();
- /// delete subscript
- void removeDown();
- /// can we add a super- or subscript?
- virtual bool allows(bool up) const { return script_[up] == 0; }
- /// can we add a super- or subscript?
- virtual bool allowsLimits() const { return true; }
- /// set limits
- void limits(int lim) { limits_ = lim; }
- ///
- int limits() const { return limits_; }
- ///
- bool hasLimits() const;
- /// true if we have an "inner" position
- bool hasInner() const;
- /// returns superscript
- MathScriptInset * up() const;
- /// returns subscript
- MathScriptInset * down() const;
- /// returns superscript
- MathScriptInset * & up();
- /// returns subscript
- MathScriptInset * & down();
- ///
- MathInset * nucleus() const { return nucleus_; }
- ///
- MathInset * & nucleus() { return nucleus_; }
- ///
- void substitute(const MathMacro &);
- ///
- void write(std::ostream &, bool) const;
- ///
- void writeNormal(std::ostream &) const;
- /// returns width of nucleus if any
- int nwid() const;
-
-protected:
- /// possible subscript (index 0) and superscript (index 1)
- MathScriptInset * script_[2];
+private:
///
MathInset * nucleus_;
- ///
- int limits_;
-
-private:
- /// the following are used for positioning the cursor with the mouse
- /// cached cursor start position in pixels from the document left
- mutable int xo_;
- /// cached cursor start position in pixels from the document top
- mutable int yo_;
/// raw copy
void copy(MathAtom const & p);
/// raw destruction
void done();
-
- /// returns y offset for superscript
- int dy0() const;
- /// returns y offset for subscript
- int dy1() const;
- /// returns x offset for main part
- int dxx() const;
- /// returns x offset for superscript
- int dx0() const;
- /// returns x offset for subscript
- int dx1() const;
- /// returns ascent of nucleus if any
- int nasc() const;
- /// returns descent of nucleus if any
- int ndes() const;
};
-std::ostream & operator<<(std::ostream &, MathAtom const &);
-
#endif
#include <cctype>
#include "support/lstrings.h"
+#include "support/LAssert.h"
#include "debug.h"
#include "LColor.h"
#include "Painter.h"
MathCursorPos i1;
MathCursorPos i2;
cursor.getSelection(i1, i2);
- if (i1.idx_ == i2.idx_) {
- MathArray ar;
- if (i1.inner_) {
- ar.push_back(*i1.at());
- ar.back().removeNucleus();
- ++i1.pos_;
- }
- ar.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
- if (i2.inner_) {
- ar.push_back(*i2.at());
- ar.back().removeUp();
- ar.back().removeDown();
- }
- data_.push_back(ar);
- }
+ if (i1.idx_ == i2.idx_)
+ data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
else {
std::vector<MathInset::idx_type> indices =
- i1.par_->idxBetween(i1.idx_, i2.idx_);
+ (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
for (MathInset::idx_type i = 0; i < indices.size(); ++i)
data_.push_back(i1.cell(indices[i]));
}
MathCursorPos i2;
cursor.getSelection(i1, i2);
if (i1.idx_ == i2.idx_) {
- if (i1.inner_) {
- i1.inner_ = false;
- i1.at()->removeUp();
- i1.at()->removeDown();
- ++i1.pos_;
- }
- if (i2.inner_) {
- i2.inner_ = false;
- i2.at()->removeNucleus();
- }
i1.cell().erase(i1.pos_, i2.pos_);
} else {
std::vector<MathInset::idx_type> indices =
- i1.par_->idxBetween(i1.idx_, i2.idx_);
+ (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i)
i1.cell(indices[i]).erase();
}
void paste(MathCursor & cursor) const
{
- cursor.insert(glue());
+ MathArray ar = glue();
+ cursor.paste(ar);
}
// glues selection to one cell
#if FILEDEBUG
std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
{
- os << "(par: " << p.par_ << " idx: " << p.idx_
- << " pos: " << p.pos_ << " inner: " << p.inner_ << ")";
+ os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")";
return os;
}
#endif
}
-MathCursor::MathCursor(InsetFormulaBase * formula)
+MathCursor::MathCursor(InsetFormulaBase * formula, bool left)
: formula_(formula), lastcode_(LM_TC_VAR), selection_(false)
{
- first();
+ left ? first() : last();
}
-void MathCursor::pushLeft(MathInset * par)
+void MathCursor::push(MathAtom & t)
{
+ //cerr << "Entering atom "; t->write(cerr, false); cerr << " left\n";
MathCursorPos p;
- p.par_ = par;
- p.inner_ = false;
- par->idxFirst(p.idx_, p.pos_);
+ p.par_ = &t;
Cursor_.push_back(p);
}
-void MathCursor::pushRight(MathInset * par)
+void MathCursor::pushLeft(MathAtom & t)
+{
+ //cerr << "Entering atom "; t->write(cerr, false); cerr << " left\n";
+ push(t);
+ t->idxFirst(idx(), pos());
+}
+
+
+void MathCursor::pushRight(MathAtom & t)
{
+ //cerr << "Entering atom "; t->write(cerr, false); cerr << " right\n";
posLeft();
- MathCursorPos p;
- p.par_ = par;
- p.inner_ = false;
- par->idxLast(p.idx_, p.pos_);
- Cursor_.push_back(p);
+ push(t);
+ t->idxLast(idx(), pos());
}
bool MathCursor::popLeft()
{
+ //cerr << "Leaving atom "; par()->write(cerr, false); cerr << " left\n";
if (Cursor_.size() <= 1)
return false;
- if (nextAtom())
- nextAtom()->removeEmptyScripts();
+ //if (nextInset())
+ // nextInset()->removeEmptyScripts();
Cursor_.pop_back();
- if (nextAtom())
- nextAtom()->removeEmptyScripts();
+ //if (nextAtom())
+ // nextAtom()->removeEmptyScripts();
return true;
}
bool MathCursor::popRight()
{
+ //cerr << "Leaving atom "; par()->write(cerr, false); cerr << " right\n";
if (Cursor_.size() <= 1)
return false;
- if (nextAtom())
- nextAtom()->removeEmptyScripts();
+ //if (nextInset())
+ // nextInset()->removeEmptyScripts();
Cursor_.pop_back();
- if (nextAtom())
- nextAtom()->removeEmptyScripts();
+ //if (nextInset())
+ // nextInset()->removeEmptyScripts();
posRight();
return true;
}
#if FILEDEBUG
-void MathCursor::dump(char const *) const
+void MathCursor::dump(char const * what) const
{
lyxerr << "MC: " << what << "\n";
for (unsigned i = 0; i < Cursor_.size(); ++i)
lyxerr << " i: " << i
- << " pos: " << Cursor_[i].pos_
+ << " Cursor: pos: " << Cursor_[i].pos_
<< " idx: " << Cursor_[i].idx_
<< " par: " << Cursor_[i].par_ << "\n";
- //lyxerr << " sel: " << selection_ << " data: " << array() << "\n";
+
+ for (unsigned i = 0; i < Anchor_.size(); ++i)
+ lyxerr << " i: " << i
+ << " Anchor: pos: " << Anchor_[i].pos_
+ << " idx: " << Anchor_[i].idx_
+ << " par: " << Anchor_[i].par_ << "\n";
+
+ lyxerr << " sel: " << selection_ << "\n";
}
+
void MathCursor::seldump(char const * str) const
{
//lyxerr << "SEL: " << str << ": '" << theSelection << "'\n";
bool MathCursor::isInside(MathInset const * p) const
{
for (unsigned i = 0; i < Cursor_.size(); ++i)
- if (Cursor_[i].par_ == p)
+ if (Cursor_[i].par_->nucleus() == p)
return true;
return false;
}
-bool MathCursor::openable(MathInset * p, bool sel) const
+bool MathCursor::openable(MathAtom const & t, bool sel) const
{
- if (!p)
+ if (!t->isActive())
return false;
- if (!p->isActive())
+ if (t->asScriptInset())
return false;
if (sel) {
// we can't move into anything new during selection
if (Cursor_.size() == Anchor_.size())
return false;
- if (p != Anchor_[Cursor_.size()].par_)
+ if (&t != Anchor_[Cursor_.size()].par_)
return false;
}
return true;
}
-MathInset * MathCursor::positionable(MathAtom * t, int x, int y) const
+bool MathCursor::positionable(MathAtom const & t, int x, int y) const
{
- if (!t)
- return 0;
-
if (selection_) {
// we can't move into anything new during selection
if (Cursor_.size() == Anchor_.size())
// return 0;
}
- MathInset * p;
-
- p = t->nucleus();
- if (p && p->nargs() && p->covers(x, y))
- return p;
-
- p = t->up();
- if (p && p->nargs() && p->covers(x, y))
- return p;
-
- p = t->down();
- if (p && p->nargs() && p->covers(x, y))
- return p;
-
- return 0;
+ return t->nargs() && t->covers(x, y);
}
bool MathCursor::posLeft()
{
- if (inner()) {
- inner() = false;
- return true;
- }
-
if (pos() == 0)
return false;
--pos();
- if (nextAtom()->hasInner())
- inner() = true;
-
return true;
}
bool MathCursor::posRight()
{
- if (inner()) {
- ++pos();
- inner() = false;
- return true;
- }
-
if (pos() == size())
return false;
- if (nextAtom()->hasInner())
- inner() = true;
- else
- ++pos();
+ ++pos();
return true;
}
selHandle(sel);
lastcode_ = LM_TC_VAR;
- MathInset * p = prevInset();
- if (openable(p, sel)) {
- pushRight(p);
+ if (hasPrevAtom() && openable(prevAtom(), sel)) {
+ pushRight(prevAtom());
return true;
}
selHandle(sel);
lastcode_ = LM_TC_VAR;
- MathInset * p = nextInset();
- if (openable(p, sel)) {
- pushLeft(p);
+ if (hasNextAtom() && openable(nextAtom(), sel)) {
+ pushLeft(nextAtom());
return true;
}
void MathCursor::first()
{
Cursor_.clear();
- pushLeft(outerPar());
+ pushLeft(formula_->par());
}
lastcode_ = LM_TC_VAR;
first();
- cursor().par_ = outerPar();
+ cursor().par_ = &formula_->par();
while (1) {
idx() = 0;
int x1 = x - ar.xo();
int y1 = y - ar.yo();
MathXArray::size_type c = ar.x2pos(x1);
- int xx = abs(x1 - ar.pos2x(c, false));
+ int xx = abs(x1 - ar.pos2x(c));
int yy = abs(y1);
//lyxerr << "idx: " << i << " xx: " << xx << " yy: " << yy
// << " c: " << c << " xo: " << ar.xo() << "\n";
}
//lyxerr << "found idx: " << idx() << " cursor: "
// << pos() << "\n";
- if (MathInset * p = positionable(nextAtom(), x, y))
- pushLeft(p);
- else if (MathInset * p = positionable(prevAtom(), x, y))
- pushRight(p);
+ if (hasNextAtom() && positionable(nextAtom(), x, y))
+ pushLeft(nextAtom());
+ else if (hasPrevAtom() && positionable(prevAtom(), x, y))
+ pushRight(prevAtom());
else
break;
}
}
-void MathCursor::plainInsert(MathInset * p)
+void MathCursor::plainInsert(MathAtom const & t)
{
- if (inner()) {
- array().insert(pos(), p);
- ++pos();
- if (prevAtom() && nextAtom()) // should be unnecessary
- swap(prevAtom()->nucleus(), nextAtom()->nucleus());
- return;
- }
-
- MathAtom * n = nextAtom();
-
- if (n && !n->nucleus()) {
- n->nucleus() = p;
- inner() = true;
- return;
- }
-
- array().insert(pos(), p); // this invalidates the pointer!
+ array().insert(pos(), t);
++pos();
}
void MathCursor::insert(char c, MathTextCodes t)
{
//lyxerr << "inserting '" << c << "'\n";
- plainInsert(new MathCharInset(c, t));
+ plainInsert(MathAtom(new MathCharInset(c, t)));
}
-void MathCursor::insert(MathInset * p)
+void MathCursor::insert(MathAtom const & t)
{
macroModeClose();
- if (p && selection_) {
- if (p->nargs())
+ if (selection_) {
+ if (t->nargs())
selCut();
else
selDel();
}
- plainInsert(p);
+ plainInsert(t);
}
-void MathCursor::niceInsert(MathInset * p)
+void MathCursor::niceInsert(MathAtom const & t)
{
- if (!p) {
- lyxerr << "MathCursor::niceInsert: should not happen\n";
- return;
- }
selCut();
- //cerr << "\n2: "; p->write(cerr, true); cerr << "\n";
- insert(p); // inserting invalidates the pointer!
- p = prevAtom()->nucleus();
- //cerr << "\n3: "; p->write(cerr, true); cerr << "\n";
+ insert(t); // inserting invalidates the pointer!
+ MathAtom const & p = prevAtom();
if (p->nargs()) {
posLeft();
right(); // do not push for e.g. MathSymbolInset
}
-void MathCursor::glueAdjacentAtoms()
+void MathCursor::paste(MathArray const & ar)
{
- MathAtom * p = prevAtom();
- if (!p)
- return;
-
- MathAtom * n = nextAtom();
- if (!n)
- return;
-
- if (p->up() && n->up())
- return;
-
- if (p->down() && n->down())
- return;
-
- // move everything to the previous atom
- if (n->up())
- swap(p->up(), n->up());
-
- if (n->down())
- swap(p->down(), n->down());
-
- plainErase();
- --pos();
- inner() = nextAtom()->hasInner();
+ Anchor_ = Cursor_;
+ selection_ = true;
+ array().insert(pos(), ar);
+ pos() += ar.size();
}
void MathCursor::backspace()
{
- if (inner()) {
- nextAtom()->removeNucleus();
- inner() = false;
- glueAdjacentAtoms();
- return;
- }
-
if (pos() == 0) {
pullArg(false);
return;
}
- if (prevAtom()->hasInner()) {
- --pos();
- inner() = true;
+ if (selection_) {
+ selDel();
return;
}
+ MathScriptInset * p = prevAtom()->asScriptInset();
+ if (p) {
+ p->removeScript(p->hasUp());
+ // Don't delete if there is anything left
+ if (p->hasUp() || p->hasDown())
+ return;
+ }
+
--pos();
plainErase();
}
return;
}
- MathAtom * n = nextAtom();
-
- if (!n)
+ if (pos() == size())
return;
- if (inner()) {
- if (n->up())
- n->removeUp();
- else if (n->down())
- n->removeDown();
- if (!n->up() && !n->down()) {
- ++pos();
- inner() = false;
- }
- return;
- }
-
- if (n->hasInner()) {
- n->removeNucleus();
- inner() = true;
- glueAdjacentAtoms();
- return;
+ MathScriptInset * p = nextAtom()->asScriptInset();
+ if (p) {
+ p->removeScript(p->hasUp());
+ // Don't delete if there is anything left
+ if (p->hasUp() || p->hasDown())
+ return;
}
plainErase();
macroModeClose();
selHandle(sel);
- if (selection_)
- return goUp();
-
- // check whether we could move into a superscript on the right or on the left
- if (prevAtom() && prevAtom()->up()) {
- pushRight(prevAtom()->up());
- return true;
- }
+ if (!selection_) {
+ // check whether we could move into a superscript
+ if (hasPrevAtom()) {
+ MathAtom & p = prevAtom();
+ if (p->asScriptInset() && p->asScriptInset()->hasUp()) {
+ pushRight(p);
+ pos() = size();
+ return true;
+ }
+ }
- if (nextAtom() && nextAtom()->up()) {
- pushLeft(nextAtom()->up());
- return true;
+ if (hasNextAtom()) {
+ MathAtom & n = nextAtom();
+ if (n->asScriptInset() && n->asScriptInset()->hasUp()) {
+ pushLeft(n);
+ pos() = 0;
+ return true;
+ }
+ }
}
return goUp();
macroModeClose();
selHandle(sel);
- if (selection_)
- return goDown();
-
- // check whether we could move into an subscript on the right or on the left
- if (prevAtom() && prevAtom()->down()) {
- pushRight(prevAtom()->down());
- return true;
- }
+ if (!selection_) {
+ // check whether we could move into a subscript
+ if (hasPrevAtom()) {
+ MathAtom & p = prevAtom();
+ if (p->asScriptInset() && p->asScriptInset()->hasDown()) {
+ pushRight(p);
+ pos() = size();
+ return true;
+ }
+ }
- if (nextAtom() && nextAtom()->down()) {
- pushLeft(nextAtom()->down());
- return true;
+ if (hasNextAtom()) {
+ MathAtom & n = nextAtom();
+ if (n->asScriptInset() && n->asScriptInset()->hasDown()) {
+ pushLeft(n);
+ pos() = 0;
+ return true;
+ }
+ }
}
return goDown();
bool MathCursor::toggleLimits()
{
- MathAtom * t = prevAtom();
+ if (!hasPrevAtom())
+ return false;
+ MathScriptInset * t = prevAtom()->asScriptInset();
if (!t)
return false;
int old = t->limits();
int MathCursor::macroNamePos() const
{
for (int i = pos() - 1; i >= 0; --i) {
- MathInset * p = array().at(i)->nucleus();
- if (p && p->code() == LM_TC_TEX && p->getChar() == '\\')
+ MathAtom & p = array().at(i);
+ if (p->code() == LM_TC_TEX && p->getChar() == '\\')
return i;
}
return -1;
{
string s;
for (int i = macroNamePos(); i >= 0 && i < int(pos()); ++i)
- s += array().at(i)->nucleus()->getChar();
+ s += array().at(i)->getChar();
return s;
}
{
seldump("selPaste");
theSelection.paste(*this);
- selClear();
+ theSelection.grab(*this);
+ //selClear();
}
if (i1.idx_ == i2.idx_) {
MathXArray & c = i1.xcell();
- int x1 = c.xo() + c.pos2x(i1.pos_, i1.inner_);
+ int x1 = c.xo() + c.pos2x(i1.pos_);
int y1 = c.yo() - c.ascent();
- int x2 = c.xo() + c.pos2x(i2.pos_, i2.inner_);
+ int x2 = c.xo() + c.pos2x(i2.pos_);
int y2 = c.yo() + c.descent();
pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
} else {
- std::vector<MathInset::idx_type> indices = i1.par_->idxBetween(i1.idx_, i2.idx_);
+ std::vector<MathInset::idx_type> indices
+ = (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i) {
MathXArray & c = i1.xcell(indices[i]);
int x1 = c.xo();
}
-MathTextCodes MathCursor::nextCode() const
-{
- //return (pos() == size()) ? LM_TC_VAR : nextInset()->code();
- return LM_TC_VAR;
-}
-
-
void MathCursor::handleFont(MathTextCodes t)
{
macroModeClose();
getSelection(i1, i2);
if (i1.idx_ == i2.idx_) {
MathArray & ar = i1.cell();
- for (MathInset::pos_type pos = i1.pos_;
- pos != i2.pos_; ++pos) {
- MathInset * p = ar.at(pos)->nucleus();
- if (p)
- p->handleFont(t);
- }
+ for (MathInset::pos_type pos = i1.pos_; pos != i2.pos_; ++pos)
+ ar.at(pos)->handleFont(t);
}
} else
lastcode_ = (lastcode_ == t) ? LM_TC_VAR : t;
selCut();
p->cell(0) = theSelection.glue();
}
- insert(p); // this invalidates p!
- p = prevAtom()->nucleus();
- pushRight(p);
+ insert(MathAtom(p)); // this invalidates p!
+ pushRight(prevAtom());
}
#ifdef WITH_WARNINGS
#warning This should probably take cellXOffset and cellYOffset into account
#endif
- x = xarray().xo() + xarray().pos2x(pos(), inner());
+ x = xarray().xo() + xarray().pos2x(pos());
y = xarray().yo();
}
-MathInset * MathCursor::par() const
+MathAtom & MathCursor::par() const
{
- return cursor().par_;
+ return *cursor().par_;
}
}
-bool MathCursor::inner() const
-{
- return cursor().inner_;
-}
-
-
-bool & MathCursor::inner()
-{
- return cursor().inner_;
-}
-
-
bool MathCursor::inMacroMode() const
{
return macroNamePos() != -1;
MathArrayInset * MathCursor::enclosingArray(MathCursor::idx_type & idx) const
{
for (int i = Cursor_.size() - 1; i >= 0; --i) {
- if (Cursor_[i].par_->isArray()) {
+ MathArrayInset * p = (*Cursor_[i].par_)->asArrayInset();
+ if (p) {
idx = Cursor_[i].idx_;
- return static_cast<MathArrayInset *>(Cursor_[i].par_);
+ return p;
}
}
return 0;
MathScriptInset const * p = par()->asScriptInset();
if (p) {
// special handling for scripts
- const bool up = p->up();
+ const bool up = p->hasUp();
popLeft();
- if (nextAtom()) {
- if (up)
- nextAtom()->removeUp();
- else
- nextAtom()->removeDown();
- }
+ MathScriptInset * q = nextAtom()->asScriptInset();
+ if (q)
+ q->removeScript(up);
++pos();
array().insert(pos(), a);
return;
}
-/*
-char MathCursorPos::getChar() const
+bool MathCursor::hasPrevAtom() const
{
- return array().getChar(pos());
+ return pos() > 0;
}
-string MathCursorPos::readString()
+bool MathCursor::hasNextAtom() const
{
- string s;
- int code = nextCode();
- for ( ; OK() && nextCode() == code; Next())
- s += getChar();
-
- return s;
-}
-*/
-
-
-MathInset * MathCursor::prevInset() const
-{
- return prevAtom() ? prevAtom()->nucleus() : 0;
+ return pos() < size();
}
-MathInset * MathCursor::nextInset() const
-{
- return nextAtom() ? nextAtom()->nucleus() : 0;
-}
-
-
-MathSpaceInset * MathCursor::prevSpaceInset() const
-{
- MathInset * p = prevInset();
- return (p && p->isSpaceInset()) ? static_cast<MathSpaceInset *>(p) : 0;
-}
-
-
-MathAtom const * MathCursor::prevAtom() const
+MathAtom const & MathCursor::prevAtom() const
{
+ lyx::Assert(pos() > 0);
return array().at(pos() - 1);
}
-MathAtom * MathCursor::prevAtom()
+MathAtom & MathCursor::prevAtom()
{
+ lyx::Assert(pos() > 0);
return array().at(pos() - 1);
}
-MathAtom const * MathCursor::nextAtom() const
+MathAtom const & MathCursor::nextAtom() const
{
+ lyx::Assert(pos() < size());
return array().at(pos());
}
-MathAtom * MathCursor::nextAtom()
+MathAtom & MathCursor::nextAtom()
{
+ lyx::Assert(pos() < size());
return array().at(pos());
}
MathArray & MathCursor::array() const
{
static MathArray dummy;
- if (!par()) {
- lyxerr << "############ par_ not valid\n";
- return dummy;
- }
if (idx() >= par()->nargs()) {
lyxerr << "############ idx_ " << idx() << " not valid\n";
while (popRight())
;
- MathMatrixInset * p = outerPar();
+ MathMatrixInset * p = formula()->par()->asMatrixInset();
+ if (!p)
+ return;
+
if (p->getType() == LM_OT_SIMPLE || p->getType() == LM_OT_EQUATION) {
p->mutate(LM_OT_EQNARRAY);
idx() = 0;
int MathCursor::xpos() const
{
- return cellXOffset() + xarray().pos2x(pos(), inner());
+ return cellXOffset() + xarray().pos2x(pos());
}
return true;
// leave subscript to the nearest side
- if (par()->asScriptInset() && par()->asScriptInset()->down()) {
+ MathScriptInset * p = par()->asScriptInset();
+ if (p && p->hasDown()) {
if (pos() <= size() / 2)
popLeft();
else
int y0;
getPos(x0, y0);
std::vector<MathCursorPos> save = Cursor_;
+ MathAtom const & out = formula()->par();
y0 -= xarray().ascent();
- for (int y = y0 - 4; y > outerPar()->yo() - outerPar()->ascent(); y -= 4) {
+ for (int y = y0 - 4; y > out->yo() - out->ascent(); y -= 4) {
setPos(x0, y);
if (save != Cursor_ && xarray().yo() < y0)
return true;
return true;
// leave superscript to the nearest side
- if (par()->asScriptInset() && par()->asScriptInset()->up()) {
+ MathScriptInset * p = par()->asScriptInset();
+ if (p && p->hasUp()) {
if (pos() <= size() / 2)
popLeft();
else
int y0;
getPos(x0, y0);
std::vector<MathCursorPos> save = Cursor_;
+ MathAtom const & out = formula()->par();
y0 += xarray().descent();
- for (int y = y0 + 4; y < outerPar()->yo() + outerPar()->descent(); y += 4) {
+ for (int y = y0 + 4; y < out->yo() + out->descent(); y += 4) {
setPos(x0, y);
if (save != Cursor_ && xarray().yo() > y0)
return true;
}
-MathMatrixInset * MathCursor::outerPar() const
-{
- return
- static_cast<MathMatrixInset *>(const_cast<MathInset *>(formula_->par()));
-}
-
-
void MathCursor::interpret(string const & s)
{
//lyxerr << "interpret 1: '" << s << "'\n";
m = std::max(1u, m);
n = std::max(1u, n);
v_align += 'c';
- MathArrayInset * p = new MathArrayInset(m, n);
- p->valign(v_align[0]);
- p->halign(h_align);
- niceInsert(p);
+ niceInsert(MathAtom(new MathArrayInset(m, n, v_align[0], h_align)));
return;
}
if (s == "\\over" || s == "\\choose" || s == "\\atop") {
MathArray ar = array();
- MathInset * p = createMathInset(s.substr(1));
- p->cell(0).swap(array());
+ MathAtom t = createMathInset(s.substr(1));
+ t->asNestInset()->cell(0).swap(array());
pos() = 0;
- niceInsert(p);
+ niceInsert(t);
popRight();
left();
return;
// no macro mode
if (c == '^' || c == '_') {
const bool up = (c == '^');
- const bool in = inner();
selCut();
- if (in)
- ++pos();
- if (!prevAtom())
- insert(0);
- MathInset * par = prevAtom()->ensure(up);
- if (in)
- pushLeft(par);
- else
- pushRight(par);
+ if (hasPrevAtom() && prevAtom()->asScriptInset()) {
+ prevAtom()->asScriptInset()->ensure(up);
+ pushRight(prevAtom());
+ pos() = size();
+ idx() = up;
+ return;
+ }
+ if (hasNextAtom() && nextAtom()->asScriptInset()) {
+ nextAtom()->asScriptInset()->ensure(up);
+ pushLeft(nextAtom());
+ pos() = 0;
+ idx() = up;
+ return;
+ }
+ plainInsert(MathAtom(new MathScriptInset(up)));
+ pushRight(prevAtom());
+ idx() = up;
selPaste();
return;
}
}
if (strchr("#$%", c)) {
- insert(new MathSpecialCharInset(c));
+ insert(MathAtom(new MathSpecialCharInset(c)));
lastcode_ = LM_TC_VAR;
return;
}
MathArray & MathCursorPos::cell(MathCursor::idx_type idx) const
{
- return par_->cell(idx);
+ return (*par_)->cell(idx);
}
MathArray & MathCursorPos::cell() const
{
- return par_->cell(idx_);
+ return (*par_)->cell(idx_);
}
MathXArray & MathCursorPos::xcell(MathCursor::idx_type idx) const
{
- return par_->xcell(idx);
+ return (*par_)->xcell(idx);
}
MathXArray & MathCursorPos::xcell() const
{
- return par_->xcell(idx_);
-}
-
-
-MathAtom * MathCursorPos::at() const
-{
- return cell().at(pos_);
+ return (*par_)->xcell(idx_);
}
return normal;
}
+
+MathSpaceInset * MathCursor::prevSpaceInset() const
+{
+ if (!hasPrevAtom())
+ return 0;
+ return prevAtom()->asSpaceInset();
+}
class MathArray;
class MathXArray;
class Painter;
+class Selection;
class latexkeys;
/// Description of a position
struct MathCursorPos {
/// inset
- MathInset * par_;
+ MathAtom * par_;
/// cell index
MathInset::idx_type idx_;
/// cell position
MathInset::pos_type pos_;
- /// faked position "inside an atom"
- bool inner_;
/// returns cell corresponding to this position
MathArray & cell() const;
MathXArray & xcell() const;
/// returns xcell corresponding to this position
MathXArray & xcell(MathInset::idx_type idx) const;
-
- /// returns atom corresponding to this position
- MathAtom * at() const;
};
///
typedef MathInset::col_type col_type;
///
- explicit MathCursor(InsetFormulaBase *);
+ explicit MathCursor(InsetFormulaBase *, bool left);
///
- void insert(MathInset *);
+ void insert(MathAtom const &);
///
void insert(MathArray const &);
///
+ void paste(MathArray const &);
+ ///
void erase();
///
void backspace();
///
void plainErase();
///
- void plainInsert(MathInset * p);
+ void plainInsert(MathAtom const &);
///
- void niceInsert(MathInset * p);
+ void niceInsert(MathAtom const &);
///
void delLine();
///
void getPos(int & x, int & y);
///
- MathInset * par() const;
+ MathAtom & par() const;
/// return the next enclosing grid inset and the cursor's index in it
MathArrayInset * enclosingArray(idx_type &) const;
///
InsetFormulaBase const * formula();
///
- bool inner() const;
- ///
pos_type pos() const;
///
idx_type idx() const;
MathStyles style() const;
/// Make sure cursor position is valid
void normalize() const;
-
+
+ /// enter a MathInset
+ void push(MathAtom & par);
/// enter a MathInset from the front
- void pushLeft(MathInset * par);
+ void pushLeft(MathAtom & par);
/// enter a MathInset from the back
- void pushRight(MathInset * par);
+ void pushRight(MathAtom & par);
/// leave current MathInset to the left
bool popLeft();
/// leave current MathInset to the left
///
MathXArray & xarray() const;
///
- MathAtom const * prevAtom() const;
+ bool hasPrevAtom() const;
+ ///
+ bool hasNextAtom() const;
+ ///
+ MathAtom const & prevAtom() const;
///
- MathAtom * prevAtom();
+ MathAtom & prevAtom();
///
- MathAtom const * nextAtom() const;
+ MathAtom const & nextAtom() const;
///
- MathAtom * nextAtom();
+ MathAtom & nextAtom();
/// returns the selection
void getSelection(MathCursorPos &, MathCursorPos &) const;
///
pos_type last() const;
///
- MathMatrixInset * outerPar() const;
- ///
void seldump(char const * str) const;
///
void dump(char const * str) const;
///
void merge(MathArray const & arr);
///
- MathInset * nextInset() const;
- ///
- MathInset * prevInset() const;
- ///
MathScriptInset * prevScriptInset() const;
///
MathSpaceInset * prevSpaceInset() const;
+ /// glue adjacent atoms if possible
+ bool glueAdjacentAtoms();
+
+ ///
+ friend class Selection;
private:
/// moves cursor position one cell to the left
bool goUp();
/// moves position somehow down
bool goDown();
- /// glue adjacent atoms if possible
- void glueAdjacentAtoms();
///
string macroName() const;
///
void insert(char, MathTextCodes t);
/// can we enter the inset?
- bool openable(MathInset *, bool selection) const;
+ bool openable(MathAtom const &, bool selection) const;
/// can the setPos routine enter that inset?
- MathInset * positionable(MathAtom *, int x, int y) const;
- /// write access to "inner" flag
- bool & inner();
+ bool positionable(MathAtom const &, int x, int y) const;
/// write access to cursor cell position
pos_type & pos();
/// write access to cursor cell index
#include "math_stackrelinset.h"
-MathInset * createMathInset(latexkeys const * l)
+MathAtom createMathInset(latexkeys const * l)
{
switch (l->token) {
case LM_TK_FUNCLIM:
- return new MathFuncLimInset(l);
+ return MathAtom(new MathFuncLimInset(l));
case LM_TK_SPECIAL:
- return new MathSpecialCharInset(l->id);
+ return MathAtom(new MathSpecialCharInset(l->id));
case LM_TK_SYM:
case LM_TK_CMR:
case LM_TK_CMSY:
case LM_TK_CMEX:
case LM_TK_MSA:
case LM_TK_MSB:
- return new MathSymbolInset(l);
+ return MathAtom(new MathSymbolInset(l));
case LM_TK_STACK:
- return new MathStackrelInset;
+ return MathAtom(new MathStackrelInset);
case LM_TK_KERN:
- return new MathKernInset;
+ return MathAtom(new MathKernInset);
case LM_TK_BINOM:
case LM_TK_CHOOSE:
- return new MathBinomInset;
+ return MathAtom(new MathBinomInset);
case LM_TK_OVER:
case LM_TK_FRAC:
- return new MathFracInset;
+ return MathAtom(new MathFracInset);
case LM_TK_ATOP:
- return new MathFracInset(true);
+ return MathAtom(new MathFracInset(true));
case LM_TK_NOT:
- return new MathNotInset;
+ return MathAtom(new MathNotInset);
case LM_TK_SQRT:
- return new MathSqrtInset;
+ return MathAtom(new MathSqrtInset);
case LM_TK_ROOT:
- return new MathRootInset;
+ return MathAtom(new MathRootInset);
case LM_TK_DECORATION:
- return new MathDecorationInset(l->name);
+ return MathAtom(new MathDecorationInset(l->name));
case LM_TK_SPACE:
- return new MathSpaceInset(l->id);
+ return MathAtom(new MathSpaceInset(l->id));
case LM_TK_DOTS:
- return new MathDotsInset(l->name);
+ return MathAtom(new MathDotsInset(l->name));
}
- return new MathFuncInset(l->name);
+ return MathAtom(new MathFuncInset(l->name));
}
-MathInset * createMathInset(string const & s)
+MathAtom createMathInset(string const & s)
{
//cerr << "creating inset with name: '" << s << "'\n";
if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
- return new MathMacroArgument(s[1] - '0');
+ return MathAtom(new MathMacroArgument(s[1] - '0'));
if (s.size() == 3 && s[0] == '\\' && s[1] == '#' && s[2] >= '1' && s[2] <= '9')
- return new MathMacroArgument(s[2] - '0');
+ return MathAtom(new MathMacroArgument(s[2] - '0'));
latexkeys const * l = in_word_set(s);
if (l)
return createMathInset(l);
- if (MathMacroTable::hasTemplate(s))
- return new MathMacro(MathMacroTable::provideTemplate(s));
+ if (MathMacroTable::has(s))
+ return MathAtom(new MathMacro(s));
- return new MathFuncInset(s);
+ return MathAtom(new MathFuncInset(s));
}
#define MATH_FACTORY_H
#include "LString.h"
+#include "math_atom.h"
class MathInset;
class latexkeys;
-MathInset * createMathInset(string const &);
-MathInset * createMathInset(latexkeys const *);
+MathAtom createMathInset(string const &);
+MathAtom createMathInset(latexkeys const *);
#endif
}
+//////////////////////////////////////////////////////////////
+
+
MathGridInset::RowInfo::RowInfo()
: upperline_(false), lowerline_(false)
{}
+//////////////////////////////////////////////////////////////
+
+
MathGridInset::ColInfo::ColInfo()
: align_('c'), leftline_(false), rightline_(false), skip_(MATH_COLSEP)
{}
+//////////////////////////////////////////////////////////////
+
+
MathGridInset::MathGridInset(col_type m, row_type n)
: MathNestInset(m * n), rowinfo_(n), colinfo_(m), v_align_('c')
{
- if (m <= 0)
- lyxerr << "positve number of columns expected\n";
- if (n <= 0)
- lyxerr << "positve number of rows expected\n";
setDefaults();
}
+MathGridInset::MathGridInset(int m, int n, char v, string const & h)
+ : MathNestInset(m * n), rowinfo_(n), colinfo_(m), v_align_(v)
+{
+ setDefaults();
+ valign(v);
+ halign(h);
+}
+
+
MathInset::idx_type MathGridInset::index(row_type row, col_type col) const
{
return col + ncols() * row;
void MathGridInset::setDefaults()
{
+ if (ncols() <= 0)
+ lyxerr << "positve number of columns expected\n";
+ if (nrows() <= 0)
+ lyxerr << "positve number of rows expected\n";
for (col_type col = 0; col < ncols(); ++col) {
colinfo_[col].align_ = defaultColAlign(col);
colinfo_[col].skip_ = defaultColSpace(col);
// make sure an upcoming '[' does not break anything
MathArray const & c = cell(index(row + 1, 0));
- if (c.size() && c.begin()->nucleus()->getChar() == '[')
+ if (c.size() && (*c.begin())->getChar() == '[')
return "\\\\[0pt]\n";
return "\\\\\n";
{
if (idx < ncols())
return false;
+ int x = cellXOffset(idx) + xcell(idx).pos2x(pos);
idx -= ncols();
- pos = 0;
+ pos = xcell(idx).x2pos(x - cellXOffset(idx));
return true;
}
{
if (idx >= ncols() * (nrows() - 1))
return false;
+ int x = cellXOffset(idx) + xcell(idx).pos2x(pos);
idx += ncols();
- pos = 0;
+ pos = xcell(idx).x2pos(x - cellXOffset(idx));
return true;
}
/// Note: columns first!
MathGridInset(col_type m, row_type n);
///
+ MathGridInset(int m, int n, char valign, string const & halign);
+ ///
void write(std::ostream &, bool fragile) const;
///
void metrics(MathStyles st) const;
const RowInfo & rowinfo(row_type row) const;
///
RowInfo & rowinfo(row_type row);
- ///
- bool isGrid() const { return true; }
+ /// identifies GridInset
+ virtual MathGridInset * asGridInset() { return this; }
///
col_type ncols() const { return colinfo_.size(); }
class LaTeXFeatures;
+class MathArrayInset;
class MathCharInset;
+class MathGridInset;
+class MathNestInset;
class MathScriptInset;
+class MathMatrixInset;
+class MathSpaceInset;
+class MathMacroTemplate;
class MathInset {
public:
virtual void getXY(int & x, int & y) const;
///
virtual bool covers(int x, int y) const;
- /// identifies things that can get scripts
- virtual bool isScriptable() const { return false; }
- /// identifies ScriptInsets
- virtual bool isScriptInset() const { return false; }
- /// identifies SpaceInsets
- virtual bool isSpaceInset() const { return false; }
- /// identifies GridInsets
- virtual bool isGrid() const { return false; }
- /// identifies ArrayInsets
- virtual bool isArray() const { return false; }
+
+ /// identifies NestInsets
+ virtual MathNestInset * asNestInset() { return 0; }
/// identifies CharInsets
virtual MathCharInset const * asCharInset() const { return 0; }
/// identifies ScriptInsets
virtual MathScriptInset const * asScriptInset() const { return 0; }
+ /// identifies ScriptInsets
+ virtual MathScriptInset * asScriptInset() { return 0; }
+ /// identifies MatrixInsets
+ virtual MathMatrixInset const * asMatrixInset() const { return 0; }
+ /// identifies MatrixInsets
+ virtual MathMatrixInset * asMatrixInset() { return 0; }
+ /// identifies SpaceInset
+ virtual MathSpaceInset * asSpaceInset() { return 0; }
+ /// identifies GridInset
+ virtual MathGridInset * asGridInset() { return 0; }
+ /// identifies ArrayInsets
+ virtual MathArrayInset * asArrayInset() { return 0; }
+ /// identifies macro templates
+ virtual MathMacroTemplate * asMacroTemplate() { return 0; }
+
+ /// identifies things that can get scripts
+ virtual bool isScriptable() const { return false; }
///
virtual bool isActive() const { return nargs() > 0; }
///
virtual bool isRelOp() const { return false; }
///
virtual bool isMacro() const { return false; }
+
///
virtual char getChar() const { return 0; }
///
using std::endl;
-MathMacro::MathMacro(MathMacroTemplate const & t)
- : MathNestInset(t.numargs()), tmplate_(&t)
+MathMacro::MathMacro(string const & name)
+ : MathNestInset(MathMacroTable::provide(name)->asMacroTemplate()->numargs()),
+ tmplate_(MathMacroTable::provide(name))
{}
-MathMacro::MathMacro(MathMacro const & t)
- : MathNestInset(t), tmplate_(t.tmplate_) // don't copy 'expanded_'!
+MathMacro::MathMacro(MathMacro const & m)
+ : MathNestInset(m),
+ tmplate_(m.tmplate_) // don't copy 'expanded_'!
{}
const char * MathMacro::name() const
{
- return tmplate_->name().c_str();
+ return tmplate_->asMacroTemplate()->name().c_str();
}
MathMacroTable::dump();
lyxerr << "\n macro: '" << this << "'\n";
lyxerr << " name: '" << name() << "'\n";
- lyxerr << " template: '" << tmplate_ << "'\n";
- lyxerr << " template: '" << *tmplate_ << "'\n";
+ lyxerr << " template: '"; tmplate_->write(lyxerr, false); lyxerr << "'\n";
lyxerr << endl;
}
+
void MathMacro::write(std::ostream & os, bool fragile) const
{
os << '\\' << name();
#include "math_nestinset.h"
#include "math_macroarg.h"
+#include "LString.h"
class MathMacroTemplate;
class MathMacro : public MathNestInset {
public:
/// A macro can be built from an existing template
- explicit MathMacro(MathMacroTemplate const &);
+ explicit MathMacro(string const &);
///
MathMacro(MathMacro const &);
///
char const * name() const;
///
- MathMacroTemplate const * const tmplate_;
+ MathAtom & tmplate_;
///
mutable MathXArray expanded_;
};
lyxerr << "\n------------------------------------------\n";
table_type::const_iterator it;
for (it = macro_table.begin(); it != macro_table.end(); ++it)
- lyxerr << it->first << " [" << it->second.nargs() << "] : "
- << it->second << "\n";
+ lyxerr << it->first
+ << " [" << it->second->asMacroTemplate()->nargs() << "] : "
+ << it->second->cell(0) << "\n";
lyxerr << "------------------------------------------\n";
}
-void MathMacroTable::insertTemplate(MathMacroTemplate const & p)
-{
- if (macro_table.find(p.name()) != macro_table.end())
- lyxerr << "macro '" << p.name() << "' not new\n";
- macro_table[p.name()] = p;
-}
-
-
-MathMacroTemplate & MathMacroTable::provideTemplate(string const & name)
+MathAtom & MathMacroTable::provide(string const & name)
{
builtinMacros();
}
-void MathMacroTable::createTemplate
- (string const & name, int na, string const & text)
+void MathMacroTable::create(string const & name, int na, string const & text)
{
- MathMacroTemplate t(name, na);
- t.cell(0) = mathed_parse_cell(text);
- insertTemplate(t);
+ MathAtom t(new MathMacroTemplate(name, na));
+ t->cell(0) = mathed_parse_cell(text);
+ macro_table[name] = t;
}
-bool MathMacroTable::hasTemplate(string const & name)
+void MathMacroTable::create(string const & name, int na, MathArray const & ar)
{
- builtinMacros();
- return macro_table.find(name) != macro_table.end();
+ MathAtom t(new MathMacroTemplate(name, na));
+ t->cell(0) = ar;
+ macro_table[name] = t;
}
-MathMacro * MathMacroTable::cloneTemplate(string const & name)
+
+bool MathMacroTable::has(string const & name)
{
- return new MathMacro(provideTemplate(name));
+ builtinMacros();
+ return macro_table.find(name) != macro_table.end();
}
built = true;
//lyxerr[Debug::MATHED] << "Building macros\n";
- //createTemplate("emptyset", 0, "\\not0");
- createTemplate("notin", 0, "\\not\\in");
- createTemplate("slash", 0, "/");
+ //create("emptyset", 0, "\\not0");
+ create("notin", 0, "\\not\\in");
+ create("slash", 0, "/");
// fontmath.ltx
- createTemplate("lnot", 0, "\\neg");
- createTemplate("land", 0, "\\wedge");
- createTemplate("lor", 0, "\\vee");
- createTemplate("ne", 0, "\\neq");
- createTemplate("le", 0, "\\leq");
- createTemplate("ge", 0, "\\geq");
- createTemplate("owns", 0, "\\ni");
- createTemplate("gets", 0, "\\leftarrow");
- createTemplate("to", 0, "\\rightarrow");
- createTemplate("|", 0, "\\parallel");
+ create("lnot", 0, "\\neg");
+ create("land", 0, "\\wedge");
+ create("lor", 0, "\\vee");
+ create("ne", 0, "\\neq");
+ create("le", 0, "\\leq");
+ create("ge", 0, "\\geq");
+ create("owns", 0, "\\ni");
+ create("gets", 0, "\\leftarrow");
+ create("to", 0, "\\rightarrow");
+ create("|", 0, "\\parallel");
- createTemplate("longleftrightarrow", 0, "\\leftarrow\\kern-6mu\\rightarrow");
- createTemplate("Longleftrightarrow", 0, "\\Leftarrow\\kern-6mu\\Rightarrow");
- createTemplate("doteq", 0, "\\stackrel{\\cdot}{=}");
+ create("longleftrightarrow", 0, "\\leftarrow\\kern-6mu\\rightarrow");
+ create("Longleftrightarrow", 0, "\\Leftarrow\\kern-6mu\\Rightarrow");
+ create("doteq", 0, "\\stackrel{\\cdot}{=}");
- //createTemplate("models", 0, "|\\kern-9mu=");
+ //create("models", 0, "|\\kern-9mu=");
if (math_font_available(LM_TC_CMSY)) {
- createTemplate("longrightarrow", 0, "\\lyxbar\\kern-5mu\\rightarrow");
- createTemplate("longleftarrow", 0, "\\leftarrow\\kern-5mu\\lyxbar");
- createTemplate("mapsto", 0, "\\mapstochar\\rightarrow");
- createTemplate("longmapsto", 0, "\\mapstochar\\lyxbar\\kern-5mu\\rightarrow");
+ create("longrightarrow", 0, "\\lyxbar\\kern-5mu\\rightarrow");
+ create("longleftarrow", 0, "\\leftarrow\\kern-5mu\\lyxbar");
+ create("mapsto", 0, "\\mapstochar\\rightarrow");
+ create("longmapsto", 0, "\\mapstochar\\lyxbar\\kern-5mu\\rightarrow");
}
if (math_font_available(LM_TC_CMR)) {
- createTemplate("Longrightarrow", 0, "\\lyxeq\\kern-3mu\\Rightarrow");
- createTemplate("Longleftarrow", 0, "\\Leftarrow\\kern-9mu\\lyxeq");
+ create("Longrightarrow", 0, "\\lyxeq\\kern-3mu\\Rightarrow");
+ create("Longleftarrow", 0, "\\Leftarrow\\kern-9mu\\lyxeq");
}
if (math_font_available(LM_TC_CMM)) {
- createTemplate("hookrightarrow", 0, "\\lhook\\kern-5mu\\rightarrow");
- createTemplate("hookleftarrow", 0, "\\leftarrow\\kern-5mu\\rhook");
- createTemplate("bowtie", 0, "\\triangleright\\kern-3mu\\triangleleft");
+ create("hookrightarrow", 0, "\\lhook\\kern-5mu\\rightarrow");
+ create("hookleftarrow", 0, "\\leftarrow\\kern-5mu\\rhook");
+ create("bowtie", 0, "\\triangleright\\kern-3mu\\triangleleft");
}
if (math_font_available(LM_TC_MSA)) {
//amsfonts.sty
- createTemplate("dashrightarrow", 0, "\\lyxdabar\\lyxdabar\\lyxright");
- createTemplate("dashleftarrow", 0, "\\lyxleft\\lyxdabar\\lyxdabar");
- createTemplate("dasharrow", 0, "\\dashrightarrow");
- createTemplate("Box", 0, "\\square");
- createTemplate("Diamond", 0, "\\lozenge");
- createTemplate("leadsto", 0, "\\rightsquigarrow");
+ create("dashrightarrow", 0, "\\lyxdabar\\lyxdabar\\lyxright");
+ create("dashleftarrow", 0, "\\lyxleft\\lyxdabar\\lyxdabar");
+ create("dasharrow", 0, "\\dashrightarrow");
+ create("Box", 0, "\\square");
+ create("Diamond", 0, "\\lozenge");
+ create("leadsto", 0, "\\rightsquigarrow");
// amssymb.sty
- createTemplate("restriction", 0, "\\upharpoonright");
- createTemplate("Doteq", 0, "\\doteqdot");
- createTemplate("doublecup", 0, "\\Cup");
- createTemplate("doublecap", 0, "\\Cap");
- createTemplate("llless", 0, "\\lll");
- createTemplate("gggtr", 0, "\\ggg");
+ create("restriction", 0, "\\upharpoonright");
+ create("Doteq", 0, "\\doteqdot");
+ create("doublecup", 0, "\\Cup");
+ create("doublecap", 0, "\\Cap");
+ create("llless", 0, "\\lll");
+ create("gggtr", 0, "\\ggg");
}
- //createTemplate("lint", 4, "\\int_#1^#2#3 d#4");
- //createTemplate("silentmult", 0, "\\cdot");
- //createTemplate("binom", 2, "\\left(\\frac#1#2\\right)");
+ //create("lint", 4, "\\int_#1^#2#3 d#4");
+ //create("silentmult", 0, "\\cdot");
+ //create("binom", 2, "\\left(\\frac#1#2\\right)");
}
#include <map>
#include "LString.h"
-#include "math_macrotemplate.h"
+#include "math_atom.h"
#ifdef __GNUG__
#pragma interface
#endif
-
-class MathMacro;
-
+class MathArray;
///
struct MathMacroTable {
public:
///
- static void insertTemplate(MathMacroTemplate const &);
- ///
- static MathMacroTemplate & provideTemplate(string const &);
+ static void create(string const &, int, string const &);
///
- static bool hasTemplate(string const &);
+ static void create(string const &, int, MathArray const &);
///
- static MathMacro * cloneTemplate(string const &);
+ static MathAtom & provide(string const &);
///
- static void createTemplate(string const &, int, string const &);
+ static bool has(string const &);
///
static void builtinMacros();
private:
///
- typedef std::map<string, MathMacroTemplate> table_type;
+ typedef std::map<string, MathAtom> table_type;
//
static table_type macro_table;
public:
MathInset * MathMacroTemplate::clone() const
{
- lyxerr << "cloning MacroTemplate!\n";
+ //lyxerr << "cloning MacroTemplate!\n";
return new MathMacroTemplate(*this);
}
void draw(Painter &, int x, int y) const;
///
void metrics(MathStyles st) const;
+ /// identifies macro templates
+ MathMacroTemplate * asMacroTemplate() { return this; }
private:
///
int numargs_;
int firstRelOp(MathArray const & array)
{
for (MathArray::const_iterator it = array.begin(); it != array.end(); ++it)
- if (it->nucleus()->isRelOp())
+ if ((*it)->isRelOp())
return it - array.begin();
return array.size();
}
std::vector<string> const getLabelList() const;
///
void validate(LaTeXFeatures & features) const;
+ /// identifies MatrixInsets
+ virtual MathMatrixInset const * asMatrixInset() const { return this; }
+ /// identifies MatrixInsets
+ virtual MathMatrixInset * asMatrixInset() { return this; }
///
void addRow(row_type);
}
-void MathNestInset::push_back(MathInset * p)
+void MathNestInset::push_back(MathAtom const & t)
{
if (nargs())
- cells_.back().data_.push_back(p);
+ cells_.back().data_.push_back(t);
else
lyxerr << "can't push without a cell\n";
}
void draw(Painter &, int x, int y) const;
/// appends itself with macro arguments substituted
void substitute(MathMacro const & macro);
+ /// identifies NestInsets
+ MathNestInset * asNestInset() { return this; }
/// The left key
bool idxLeft(idx_type & idx, pos_type & pos) const;
///
bool isActive() const { return nargs() > 0; }
///
- void push_back(MathInset *);
+ void push_back(MathAtom const &);
///
void dump() const;
}
+void add(MathArray & ar, char c, MathTextCodes code)
+{
+ ar.push_back(MathAtom(new MathCharInset(c, code)));
+}
+
// These are TeX's catcodes
enum CatCode {
Parser(istream & is);
///
- MathMacroTemplate * parse_macro();
+ string parse_macro();
///
- MathMatrixInset * parse_normal();
+ bool parse_normal(MathAtom &);
///
void parse_into(MathArray & array, unsigned flags, MathTextCodes = LM_TC_MIN);
///
///
void error(string const & msg);
///
- void parse_lines(MathGridInset * p, bool numbered, bool outmost);
+ bool parse_lines(MathAtom & t, bool numbered, bool outmost);
private:
///
}
-void Parser::parse_lines(MathGridInset * p, bool numbered, bool outmost)
-{
+bool Parser::parse_lines(MathAtom & t, bool numbered, bool outmost)
+{
+ MathGridInset * p = t->asGridInset();
+ if (!p) {
+ lyxerr << "error in Parser::parse_lines() 1\n";
+ return false;
+ }
+
const int cols = p->ncols();
// save global variables
}
if (outmost) {
- MathMatrixInset * m = static_cast<MathMatrixInset *>(p);
+ MathMatrixInset * m = t->asMatrixInset();
+ if (!m) {
+ lyxerr << "error in Parser::parse_lines() 2\n";
+ return false;
+ }
m->numbered(row, curr_num_);
m->label(row, curr_label_);
if (curr_skip_.size()) {
// restore "global" variables
curr_num_ = saved_num;
curr_label_ = saved_label;
+
+ return true;
}
-MathMacroTemplate * Parser::parse_macro()
+string Parser::parse_macro()
{
+ string name = "{error}";
+
while (nextToken().cat() == catSpace)
getToken();
if (getToken().cs() != "newcommand") {
lyxerr << "\\newcommand expected\n";
- return 0;
+ return name;
}
if (getToken().cat() != catBegin) {
lyxerr << "'{' expected\n";
- return 0;
+ return name;
}
- string name = getToken().cs();
+ name = getToken().cs();
if (getToken().cat() != catEnd) {
lyxerr << "'}' expected\n";
- return 0;
+ return name;
}
- string arg = getArg('[', ']');
- int narg = arg.empty() ? 0 : atoi(arg.c_str());
- //lyxerr << "creating macro " << name << " with " << narg << "args\n";
- MathMacroTemplate * p = new MathMacroTemplate(name, narg);
- parse_into(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST);
- return p;
+ string arg = getArg('[', ']');
+ int narg = arg.empty() ? 0 : atoi(arg.c_str());
+ MathArray ar;
+ parse_into(ar, FLAG_BRACE | FLAG_BRACE_LAST);
+ MathMacroTable::create(name, narg, ar);
+
+ return name;
}
-MathMatrixInset * Parser::parse_normal()
+bool Parser::parse_normal(MathAtom & matrix)
{
while (nextToken().cat() == catSpace)
getToken();
Token const & t = getToken();
if (t.cat() == catMath || t.cs() == "(") {
- MathMatrixInset * p = new MathMatrixInset(LM_OT_SIMPLE);
- parse_into(p->cell(0), 0);
- return p;
+ matrix = MathAtom(new MathMatrixInset(LM_OT_SIMPLE));
+ parse_into(matrix->cell(0), 0);
+ return true;
}
if (!t.cs().size()) {
lyxerr << "start of math expected, got '" << t << "'\n";
- return 0;
+ return false;
}
string const & cs = t.cs();
if (cs == "[") {
curr_num_ = 0;
curr_label_.erase();
- MathMatrixInset * p = new MathMatrixInset(LM_OT_EQUATION);
+ matrix = MathAtom(new MathMatrixInset(LM_OT_EQUATION));
+ MathMatrixInset * p = matrix->asMatrixInset();
parse_into(p->cell(0), 0);
p->numbered(0, curr_num_);
p->label(0, curr_label_);
if (cs != "begin") {
lyxerr << "'begin' of un-simple math expected, got '" << cs << "'\n";
- return 0;
+ return false;
}
string const name = getArg('{', '}');
if (name == "equation" || name == "equation*") {
curr_num_ = !stared(name);
curr_label_.erase();
- MathMatrixInset * p = new MathMatrixInset(LM_OT_EQUATION);
+ matrix = MathAtom(new MathMatrixInset(LM_OT_EQUATION));
+ MathMatrixInset * p = matrix->asMatrixInset();
parse_into(p->cell(0), FLAG_END);
p->numbered(0, curr_num_);
p->label(0, curr_label_);
- return p;
+ return true;
}
if (name == "eqnarray" || name == "eqnarray*") {
- MathMatrixInset * p = new MathMatrixInset(LM_OT_EQNARRAY);
- parse_lines(p, !stared(name), true);
- return p;
+ matrix = MathAtom(new MathMatrixInset(LM_OT_EQNARRAY));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "align" || name == "align*") {
- MathMatrixInset * p = new MathMatrixInset(LM_OT_ALIGN);
- parse_lines(p, !stared(name), true);
- return p;
+ matrix = MathAtom(new MathMatrixInset(LM_OT_ALIGN));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "alignat" || name == "alignat*") {
- MathMatrixInset * p =
- new MathMatrixInset(LM_OT_ALIGNAT, 2 * atoi(getArg('{', '}').c_str()));
- parse_lines(p, !stared(name), true);
- return p;
+ int nc = 2 * atoi(getArg('{', '}').c_str());
+ matrix = MathAtom(new MathMatrixInset(LM_OT_ALIGNAT, nc));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "xalignat" || name == "xalignat*") {
- MathMatrixInset * p =
- new MathMatrixInset(LM_OT_XALIGNAT, 2 * atoi(getArg('{', '}').c_str()));
- parse_lines(p, !stared(name), true);
- return p;
+ int nc = 2 * atoi(getArg('{', '}').c_str());
+ matrix = MathAtom(new MathMatrixInset(LM_OT_XALIGNAT, nc));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "xxalignat") {
- MathMatrixInset * p =
- new MathMatrixInset(LM_OT_XXALIGNAT, 2 * atoi(getArg('{', '}').c_str()));
- parse_lines(p, !stared(name), true);
- return p;
+ int nc = 2 * atoi(getArg('{', '}').c_str());
+ matrix = MathAtom(new MathMatrixInset(LM_OT_XXALIGNAT, nc));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "multline" || name == "multline*") {
- MathMatrixInset * p = new MathMatrixInset(LM_OT_MULTLINE);
- parse_lines(p, !stared(name), true);
- return p;
+ matrix = MathAtom(new MathMatrixInset(LM_OT_MULTLINE));
+ return parse_lines(matrix, !stared(name), true);
}
if (name == "gather" || name == "gather*") {
- MathMatrixInset * p = new MathMatrixInset(LM_OT_GATHER);
- parse_lines(p, !stared(name), true);
- return p;
+ matrix = MathAtom(new MathMatrixInset(LM_OT_GATHER));
+ return parse_lines(matrix, !stared(name), true);
}
lyxerr[Debug::MATHED] << "1: unknown math environment: " << name << "\n";
- return 0;
+ return false;
}
MathTextCodes yyvarcode = LM_TC_MIN;
bool panic = false;
+ int limits = 0;
while (good()) {
Token const & t = getToken();
break;
else if (t.cat() == catLetter)
- array.push_back(new MathCharInset(t.character(), yyvarcode));
+ add(array, t.character(), yyvarcode);
else if (t.cat() == catSpace &&
(yyvarcode == LM_TC_TEXTRM || code == LM_TC_TEXTRM))
- array.push_back(new MathCharInset(' ', yyvarcode));
+ add(array, ' ', yyvarcode);
else if (t.cat() == catParameter) {
Token const & n = getToken();
- MathMacroArgument * p = new MathMacroArgument(n.character() - '0');
- array.push_back(p);
+ array.push_back(MathAtom(new MathMacroArgument(n.character() - '0')));
}
else if (t.cat() == catBegin) {
- array.push_back(new MathCharInset('{', LM_TC_TEX));
+ add(array, '{', LM_TC_TEX);
}
else if (t.cat() == catEnd) {
if (flags & FLAG_BRACE_LAST)
return;
- array.push_back(new MathCharInset('}', LM_TC_TEX));
+ add(array, '}', LM_TC_TEX);
}
else if (t.cat() == catAlign) {
lyxerr << "found tab unexpectedly, array: '" << array << "'\n";
- array.push_back(new MathCharInset('&', LM_TC_TEX));
+ add(array, '&', LM_TC_TEX);
}
else if (t.cat() == catSuper || t.cat() == catSub) {
bool up = (t.cat() == catSuper);
- if (array.empty())
- array.push_back(new MathCharInset(' '));
- parse_into(array.back().ensure(up)->cell(0), FLAG_ITEM);
+ MathScriptInset * p = 0;
+ if (array.size())
+ p = array.back()->asScriptInset();
+ if (!p || p->has(up)) {
+ array.push_back(MathAtom(new MathScriptInset(up)));
+ p = array.back()->asScriptInset();
+ }
+ p->ensure(up);
+ parse_into(p->cell(up), FLAG_ITEM);
+ p->limits(limits);
+ limits = 0;
}
else if (t.character() == ']' && (flags & FLAG_BRACK_END))
return;
else if (t.cat() == catOther)
- array.push_back(new MathCharInset(t.character(), yyvarcode));
+ add(array, t.character(), yyvarcode);
//
// codesequences
array.push_back(createMathInset("\\"));
}
- else if (t.cs() == "limits" && array.size())
- array.back().limits(1);
+ else if (t.cs() == "limits")
+ limits = 1;
- else if (t.cs() == "nolimits" && array.size())
- array.back().limits(-1);
+ else if (t.cs() == "nolimits")
+ limits = -1;
else if (t.cs() == "nonumber")
curr_num_ = false;
else if (t.cs() == "sqrt") {
char c = getChar();
if (c == '[') {
- array.push_back(new MathRootInset);
- parse_into(array.back().nucleus()->cell(0), FLAG_BRACK_END);
- parse_into(array.back().nucleus()->cell(1), FLAG_ITEM);
+ array.push_back(MathAtom(new MathRootInset));
+ parse_into(array.back()->cell(0), FLAG_BRACK_END);
+ parse_into(array.back()->cell(1), FLAG_ITEM);
} else {
putback();
- array.push_back(new MathSqrtInset);
- parse_into(array.back().nucleus()->cell(0), FLAG_ITEM);
+ array.push_back(MathAtom(new MathSqrtInset));
+ parse_into(array.back()->cell(0), FLAG_ITEM);
}
}
MathArray ar;
parse_into(ar, FLAG_RIGHT);
string r = getToken().asString();
- MathDelimInset * dl = new MathDelimInset(l, r);
+ MathAtom dl(new MathDelimInset(l, r));
dl->cell(0) = ar;
array.push_back(dl);
}
if (name == "array") {
string const valign = getArg('[', ']') + 'c';
string const halign = getArg('{', '}');
- MathArrayInset * m = new MathArrayInset(halign.size(), 1);
- m->valign(valign[0]);
- m->halign(halign);
- parse_lines(m, false, false);
- array.push_back(m);
+ array.push_back(
+ MathAtom(new MathArrayInset(halign.size(), 1, valign[0], halign)));
+ parse_lines(array.back(), false, false);
} else if (name == "split") {
- MathSplitInset * m = new MathSplitInset(1);
- parse_lines(m, false, false);
- array.push_back(m);
+ array.push_back(MathAtom(new MathSplitInset(1)));
+ parse_lines(array.back(), false, false);
} else
lyxerr[Debug::MATHED] << "unknow math inset begin '" << name << "'\n";
}
if (isValidLength(s))
break;
}
- array.push_back(new MathKernInset(s));
+ array.push_back(MathAtom(new MathKernInset(s)));
}
else if (t.cs() == "label") {
}
else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
- MathInset * p = createMathInset(t.cs());
+ MathAtom p = createMathInset(t.cs());
// search backward for position of last '{' if any
int pos;
for (pos = array.size() - 1; pos >= 0; --pos)
- if (array.at(pos)->nucleus()->getChar() == '{')
+ if (array.at(pos)->getChar() == '{')
break;
if (pos >= 0) {
// found it -> use the part after '{' as "numerator"
p->cell(0).swap(array);
parse_into(p->cell(1), FLAG_BLOCK);
}
- array.push_back(p);
+ array.push_back(MathAtom(p));
}
else if (t.cs().size()) {
MathArray ar;
parse_into(ar, FLAG_ITEM, t);
for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it)
- it->nucleus()->handleFont(t);
+ (*it)->handleFont(t);
array.push_back(ar);
// undo catcode changes
yyvarcode = static_cast<MathTextCodes>(l->id);
else {
- MathInset * p = createMathInset(t.cs());
+ MathAtom p = createMathInset(t.cs());
for (MathInset::idx_type i = 0; i < p->nargs(); ++i)
parse_into(p->cell(i), FLAG_ITEM);
array.push_back(p);
}
else {
- MathInset * p = createMathInset(t.cs());
- if (p) {
- for (MathInset::idx_type i = 0; i < p->nargs(); ++i)
- parse_into(p->cell(i), FLAG_ITEM);
- array.push_back(p);
- } else {
- error("Unrecognized token");
- //lyxerr[Debug::MATHED] << "[" << t << "]\n";
- lyxerr << t << "\n";
- }
+ MathAtom p = createMathInset(t.cs());
+ for (MathInset::idx_type i = 0; i < p->nargs(); ++i)
+ parse_into(p->cell(i), FLAG_ITEM);
+ array.push_back(p);
}
}
}
}
+
+
} // anonymous namespace
-MathMacroTemplate * mathed_parse_macro(string const & str)
+string mathed_parse_macro(string const & str)
{
istringstream is(str.c_str());
Parser parser(is);
return parser.parse_macro();
}
-MathMacroTemplate * mathed_parse_macro(istream & is)
+string mathed_parse_macro(istream & is)
{
Parser parser(is);
return parser.parse_macro();
}
-MathMacroTemplate * mathed_parse_macro(LyXLex & lex)
+string mathed_parse_macro(LyXLex & lex)
{
Parser parser(lex);
return parser.parse_macro();
-MathMatrixInset * mathed_parse_normal(string const & str)
+bool mathed_parse_normal(MathAtom & t, string const & str)
{
istringstream is(str.c_str());
Parser parser(is);
- return parser.parse_normal();
+ return parser.parse_normal(t);
}
-MathMatrixInset * mathed_parse_normal(istream & is)
+bool mathed_parse_normal(MathAtom & t, istream & is)
{
Parser parser(is);
- return parser.parse_normal();
+ return parser.parse_normal(t);
}
-MathMatrixInset * mathed_parse_normal(LyXLex & lex)
+bool mathed_parse_normal(MathAtom & t, LyXLex & lex)
{
Parser parser(lex);
- return parser.parse_normal();
+ return parser.parse_normal(t);
}
class MathMatrixInset;
class MathMacroTemplate;
+class MathAtom;
+class MathArray;
class LyXLex;
///
///
void ReadSymbols(string const & file);
-MathMatrixInset * mathed_parse_normal(string const &);
-MathMatrixInset * mathed_parse_normal(std::istream &);
-MathMatrixInset * mathed_parse_normal(LyXLex &);
+bool mathed_parse_normal(MathAtom &, string const &);
+bool mathed_parse_normal(MathAtom &, std::istream &);
+bool mathed_parse_normal(MathAtom &, LyXLex &);
-MathMacroTemplate * mathed_parse_macro(string const &);
-MathMacroTemplate * mathed_parse_macro(std::istream &);
-MathMacroTemplate * mathed_parse_macro(LyXLex &);
+string mathed_parse_macro(string const &);
+string mathed_parse_macro(std::istream &);
+string mathed_parse_macro(LyXLex &);
#endif
os << "] ";
}
+
bool MathRootInset::idxUp(int & idx, int & pos) const
{
if (idx == 0)
return false;
idx = 0;
- pos = 0;
+ pos = cell(0).size();
return true;
}
+
bool MathRootInset::idxDown(int & idx, int & pos) const
{
if (idx == 1)
#include <config.h>
#include "debug.h"
+#include "support.h"
#include "support/LOstream.h"
+#include "support/LAssert.h"
#ifdef __GNUG__
#pragma implementation
#include "math_scriptinset.h"
+MathScriptInset::MathScriptInset()
+ : MathNestInset(2), limits_(0)
+{
+ script_[0] = false;
+ script_[1] = false;
+}
+
+
MathScriptInset::MathScriptInset(bool up)
- : MathNestInset(1), up_(up)
-{}
+ : MathNestInset(2), limits_(0)
+{
+ script_[0] = !up;
+ script_[1] = up;
+}
+
MathInset * MathScriptInset::clone() const
return this;
}
-void MathScriptInset::write(std::ostream & os, bool fragile) const
+
+MathScriptInset * MathScriptInset::asScriptInset()
{
- cell(0).write(os, fragile);
+ return this;
}
-void MathScriptInset::metrics(MathStyles st) const
+MathXArray const & MathScriptInset::up() const
{
- size_ = st;
- xcell(0).metrics(st);
- width_ = xcell(0).width();
- ascent_ = xcell(0).ascent();
- descent_ = xcell(0).descent();
- //lyxerr << "MathScriptInset::metrics: w: " << width_ << " a: " << ascent_
- // << " d: " << descent_ << "\n";
+ return xcell(1);
}
-void MathScriptInset::draw(Painter & pain, int x, int y) const
+MathXArray const & MathScriptInset::down() const
+{
+ return xcell(0);
+}
+
+
+MathXArray & MathScriptInset::up()
+{
+ return xcell(1);
+}
+
+
+MathXArray & MathScriptInset::down()
{
+ return xcell(0);
+}
+
+
+void MathScriptInset::ensure(bool up)
+{
+ script_[up] = true;
+}
+
+
+int MathScriptInset::dy0(MathInset const * nuc) const
+{
+ int nd = ndes(nuc);
+ if (!hasDown())
+ return nd;
+ int des = down().ascent();
+ if (hasLimits(nuc))
+ des += nd + 2;
+ else
+ des = std::max(des, nd);
+ return des;
+}
+
+
+int MathScriptInset::dy1(MathInset const * nuc) const
+{
+ int na = nasc(nuc);
+ if (!hasUp())
+ return na;
+ int asc = up().descent();
+ if (hasLimits(nuc))
+ asc += na + 2;
+ else
+ asc = std::max(asc, na);
+ asc = std::max(asc, mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I'));
+ return asc;
+}
+
+
+int MathScriptInset::dx0(MathInset const * nuc) const
+{
+ lyx::Assert(hasDown());
+ return hasLimits(nuc) ? (width(nuc) - down().width()) / 2 : nwid(nuc);
+}
+
+
+int MathScriptInset::dx1(MathInset const * nuc) const
+{
+ lyx::Assert(hasUp());
+ return hasLimits(nuc) ? (width(nuc) - up().width()) / 2 : nwid(nuc);
+}
+
+
+int MathScriptInset::dxx(MathInset const * nuc) const
+{
+ //lyx::Assert(nuc());
+ return hasLimits(nuc) ? (width(nuc) - nwid(nuc)) / 2 : 0;
+}
+
+
+int MathScriptInset::ascent(MathInset const * nuc) const
+{
+ return dy1(nuc) + (hasUp() ? up().ascent() : 0);
+}
+
+
+int MathScriptInset::descent(MathInset const * nuc) const
+{
+ return dy0(nuc) + (hasDown() ? down().descent() : 0);
+}
+
+
+int MathScriptInset::width(MathInset const * nuc) const
+{
+ int wid = 0;
+ if (hasLimits(nuc)) {
+ wid = nwid(nuc);
+ if (hasUp())
+ wid = std::max(wid, up().width());
+ if (hasDown())
+ wid = std::max(wid, down().width());
+ } else {
+ if (hasUp())
+ wid = std::max(wid, up().width());
+ if (hasDown())
+ wid = std::max(wid, down().width());
+ wid += nwid(nuc);
+ }
+ return wid;
+}
+
+
+int MathScriptInset::nwid(MathInset const * nuc) const
+{
+ return nuc ?
+ nuc->width() :
+ mathed_char_width(LM_TC_TEX, LM_ST_TEXT, '.');
+}
+
+
+int MathScriptInset::nasc(MathInset const * nuc) const
+{
+ return nuc ? nuc->ascent()
+ : mathed_char_ascent(LM_TC_VAR, LM_ST_TEXT, 'I');
+}
+
+
+int MathScriptInset::ndes(MathInset const * nuc) const
+{
+ return nuc ? nuc->descent()
+ : mathed_char_descent(LM_TC_VAR, LM_ST_TEXT, 'I');
+}
+
+
+void MathScriptInset::metrics(MathStyles st) const
+{
+ metrics(0, st);
+}
+
+
+void MathScriptInset::metrics(MathInset const * nuc, MathStyles st) const
+{
+ MathNestInset::metrics(st);
+ if (nuc)
+ nuc->metrics(st);
+
+ ascent_ = ascent(nuc);
+ descent_ = descent(nuc);
+ width_ = width(nuc);
+}
+
+
+void MathScriptInset::draw(Painter & pain, int x, int y) const
+{
+ //lyxerr << "unexpected call to MathScriptInset::draw()\n";
+ draw(0, pain, x, y);
+}
+
+
+void MathScriptInset::draw(MathInset const * nuc, Painter & pain,
+ int x, int y) const
+{
xo(x);
yo(y);
- xcell(0).draw(pain, x, y);
+ if (nuc)
+ nuc->draw(pain, x + dxx(nuc), y);
+ else
+ drawStr(pain, LM_TC_TEX, LM_ST_TEXT, x + dxx(nuc), y, ".");
+ if (hasUp())
+ up().draw(pain, x + dx1(nuc), y - dy1(nuc));
+ if (hasDown())
+ down().draw(pain, x + dx0(nuc), y + dy0(nuc));
+}
+
+
+void MathScriptInset::write(std::ostream & os, bool fragile) const
+{
+ //lyxerr << "unexpected call to MathScriptInset::write()\n";
+ write(0, os, fragile);
+}
+
+
+void MathScriptInset::write(MathInset const * nuc, std::ostream & os,
+ bool fragile) const
+{
+ if (nuc) {
+ nuc->write(os, fragile);
+ if (nuc->takesLimits()) {
+ if (limits_ == -1)
+ os << "\\nolimits ";
+ if (limits_ == 1)
+ os << "\\limits ";
+ }
+ }
+ else
+ os << "{}";
+
+ if (hasDown() && down().data_.size()) {
+ os << "_{";
+ down().data_.write(os, fragile);
+ os << "}";
+ }
+
+ if (hasUp() && up().data_.size()) {
+ os << "^{";
+ up().data_.write(os, fragile);
+ os << "}";
+ }
+}
+
+
+bool MathScriptInset::hasLimits(MathInset const * nuc) const
+{
+ return limits_ == 1 || (limits_ == 0 && nuc && nuc->isScriptable());
+}
+
+
+void MathScriptInset::removeEmptyScripts()
+{
+ for (int i = 0; i <= 1; ++i)
+ if (script_[i] && !cell(i).size())
+ script_[i] = false;
+}
+
+
+void MathScriptInset::removeScript(bool up)
+{
+ cell(up).clear();
+ script_[up] = false;
+}
+
+
+bool MathScriptInset::has(bool up) const
+{
+ return script_[up];
+}
+
+
+bool MathScriptInset::hasUp() const
+{
+ return script_[1];
+}
+
+
+bool MathScriptInset::hasDown() const
+{
+ return script_[0];
}
class MathScriptInset : public MathNestInset {
public:
+ ///
+ MathScriptInset();
///
explicit MathScriptInset(bool up);
///
void metrics(MathStyles st) const;
///
void draw(Painter &, int x, int y) const;
+
+ ///
+ void write(MathInset const * nucleus, std::ostream &, bool fragile) const;
+ ///
+ void metrics(MathInset const * nucleus, MathStyles st) const;
+ ///
+ void draw(MathInset const * nucleus, Painter &, int x, int y) const;
+ ///
+ int ascent(MathInset const * nucleus) const;
+ ///
+ int descent(MathInset const * nucleus) const;
+ ///
+ int width(MathInset const * nucleus) const;
+
///
MathScriptInset const * asScriptInset() const;
///
- bool up() const { return up_; }
+ MathScriptInset * asScriptInset();
+
+ /// set limits
+ void limits(int lim) { limits_ = lim; }
+ ///
+ int limits() const { return limits_; }
+ ///
+ bool hasLimits(MathInset const * nucleus) const;
+ /// true if we have an "inner" position
+ MathXArray const & up() const;
+ /// returns subscript
+ MathXArray const & down() const;
+ /// returns superscript
+ MathXArray & up();
+ /// returns subscript
+ MathXArray & down();
+ /// do we have a superscript?
+ bool hasUp() const;
+ /// do we have a subscript?
+ bool hasDown() const;
+ /// do we have a script?
+ bool has(bool up) const;
+ /// remove script
+ void removeScript(bool up);
+ /// remove script
+ void removeEmptyScripts();
///
- bool down() const { return !up_; }
+ void ensure(bool up);
+
+public:
+ /// returns x offset for main part
+ int dxx(MathInset const * nuc) const;
+ /// returns width of nucleus if any
+ int nwid(MathInset const * nuc) const;
private:
+ /// returns y offset for superscript
+ int dy0(MathInset const * nuc) const;
+ /// returns y offset for subscript
+ int dy1(MathInset const * nuc) const;
+ /// returns x offset for superscript
+ int dx0(MathInset const * nuc) const;
+ /// returns x offset for subscript
+ int dx1(MathInset const * nuc) const;
+ /// returns ascent of nucleus if any
+ int nasc(MathInset const * nuc) const;
+ /// returns descent of nucleus if any
+ int ndes(MathInset const * nuc) const;
+
+ /// possible subscript (index 0) and superscript (index 1)
+ bool script_[2];
///
- bool up_;
+ int limits_;
};
#endif
///
void metrics(MathStyles st) const;
///
- bool isSpaceInset() const { return true; }
+ MathSpaceInset const * asSpaceInset() const { return this; }
+ ///
+ MathSpaceInset * asSpaceInset() { return this; }
///
void incSpace();
private:
#include "xarray.h"
#include "math_inset.h"
+#include "math_scriptinset.h"
#include "mathed/support.h"
#include "math_defs.h"
#include "Painter.h"
width_ = 0;
//lyxerr << "MathXArray::metrics(): '" << data_ << "'\n";
- for (size_type pos = 0; pos < data_.size(); ++pos) {
- MathAtom const * p = data_.at(pos);
- p->metrics(st);
- ascent_ = std::max(ascent_, p->ascent());
- descent_ = std::max(descent_, p->descent());
- width_ += p->width();
+
+ for (const_iterator it = begin(); it != end(); ++it) {
+ MathInset const * p = it->nucleus();
+ if (MathScriptInset const * q = data_.asScript(it)) {
+ q->metrics(p, st);
+ ascent_ = std::max(ascent_, q->ascent(p));
+ descent_ = std::max(descent_, q->descent(p));
+ width_ += q->width(p);
+ ++it;
+ } else {
+ p->metrics(st);
+ ascent_ = std::max(ascent_, p->ascent());
+ descent_ = std::max(descent_, p->descent());
+ width_ += p->width();
+ }
}
//lyxerr << "MathXArray::metrics(): '" << ascent_ << " "
// << descent_ << " " << width_ << "'\n";
return;
}
- for (size_type pos = 0; pos < data_.size(); ++pos) {
- MathAtom const * p = data_.at(pos);
- p->draw(pain, x, y);
- x += p->width();
+ for (const_iterator it = begin(); it != end(); ++it) {
+ MathInset const * p = it->nucleus();
+ if (MathScriptInset const * q = data_.asScript(it)) {
+ q->draw(p, pain, x, y);
+ x += q->width(p);
+ ++it;
+ } else {
+ p->draw(pain, x, y);
+ x += p->width();
+ }
}
}
-int MathXArray::pos2x(size_type targetpos, bool inner) const
+int MathXArray::pos2x(size_type targetpos) const
{
int x = 0;
- targetpos = std::min(targetpos, data_.size());
- for (size_type pos = 0; pos < targetpos; ++pos)
- x += width(pos);
- if (inner)
- x += innerwidth(targetpos);
+ const_iterator target = std::min(begin() + targetpos, end());
+ for (const_iterator it = begin(); it < target; ++it) {
+ MathInset const * p = it->nucleus();
+ if (MathScriptInset const * q = data_.asScript(it)) {
+ ++it;
+ if (it < target)
+ x += q->width(p);
+ else // "half" position
+ x += q->dxx(p) + q->nwid(p);
+ } else
+ x += p->width();
+ }
return x;
}
MathArray::size_type MathXArray::x2pos(int targetx) const
{
- size_type pos = 0;
- int lastx = 0;
- int currx = 0;
- for ( ; currx < targetx && pos < data_.size(); ++pos) {
+ const_iterator it = begin();
+ int lastx = 0;
+ int currx = 0;
+ for ( ; currx < targetx && it < end(); ++it) {
lastx = currx;
- currx += width(pos);
- }
- if (abs(lastx - targetx) < abs(currx - targetx) && pos > 0)
- --pos;
- return pos;
-}
+ int wid = 0;
+ MathInset const * p = it->nucleus();
+ if (MathScriptInset const * q = data_.asScript(it)) {
+ wid = q->width(p);
+ ++it;
+ } else
+ wid = p->width();
-int MathXArray::width(size_type pos) const
-{
- MathAtom const * t = data_.at(pos);
- return t ? t->width() : 0;
-}
-
-
-int MathXArray::innerwidth(size_type pos) const
-{
- MathAtom const * t = data_.at(pos);
- return t ? t->nwid() : 0;
+ currx += wid;
+ }
+ if (abs(lastx - targetx) < abs(currx - targetx) && it != begin())
+ --it;
+ return it - begin();
}
{
public:
///
- typedef MathArray::size_type size_type;
+ typedef MathArray::size_type size_type;
+ ///
+ typedef MathArray::const_iterator const_iterator;
///
MathXArray();
///
int yo() const { return yo_; }
///
- int pos2x(size_type pos, bool inner) const;
+ int pos2x(size_type pos) const;
///
size_type x2pos(int pos) const;
- ///
- int width(size_type pos) const;
- ///
- int innerwidth(size_type pos) const;
///
int ascent() const { return ascent_; }
int width() const { return width_; }
///
MathStyles style() const { return style_; }
-
+ ///
+ const_iterator begin() const { return data_.begin(); }
+ ///
+ const_iterator end() const { return data_.end(); }
+
+public:
///
MathArray data_;
///