try to do with super- and subscripts what TeX does

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2722 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
André Pönitz 2001-09-11 10:58:17 +00:00
parent e670bed4c5
commit e4c58b72be
26 changed files with 742 additions and 473 deletions

View File

@ -1,3 +1,13 @@
2001-09-11 André Pönitz <poenitz@gmx.net>
* math_atom.[Ch]: new basic item in the MathArray
* array.[Ch]: move code over to math_atom
* math_scriptinset.[Ch]:
math_parser.C:
math_cursor.C: try to do with super- and subscripts what TeX does
2001-09-04 Jean-Marc Lasgouttes <Jean-Marc.Lasgouttes@inria.fr>
* math_parser.C (tokenize): add a .c_str() (needed with lyxstring)

View File

@ -20,6 +20,8 @@ libmathed_la_SOURCES = \
formulamacro.h \
math_arrayinset.C \
math_arrayinset.h \
math_atom.C \
math_atom.h \
math_binominset.C \
math_binominset.h \
math_charinset.C \

View File

@ -4,6 +4,7 @@
#include "math_inset.h"
#include "math_charinset.h"
#include "math_scriptinset.h"
#include "debug.h"
#include "array.h"
#include "mathed/support.h"
@ -11,35 +12,14 @@
using std::ostream;
using std::endl;
MathArray::MathArray()
{}
MathArray::~MathArray()
{
erase();
}
MathArray::MathArray(MathArray const & array)
: bf_(array.bf_)
{
deep_copy(begin(), end());
}
MathArray::MathArray(MathArray const & array, int from, int to)
: bf_(array.begin() + from, array.begin() + to)
{
deep_copy(begin(), end());
}
void MathArray::deep_copy(iterator from, iterator to)
{
for (iterator it = from; it != to; ++it)
*it = (*it)->clone();
}
{}
int MathArray::last() const
@ -52,41 +32,35 @@ void MathArray::substitute(MathMacro const & m)
{
MathArray tmp;
for (iterator it = begin(); it != end(); ++it)
(*it)->substitute(tmp, m);
it->substitute(tmp, m);
swap(tmp);
}
MathArray & MathArray::operator=(MathArray const & array)
MathAtom * MathArray::at(int pos)
{
MathArray tmp(array);
swap(tmp);
return *this;
return (0 <= pos && pos < size()) ? &bf_[pos] : 0;
}
MathInset * MathArray::nextInset(int pos)
MathAtom const * MathArray::at(int pos) const
{
return (pos == size()) ? 0 : bf_[pos];
}
MathInset const * MathArray::nextInset(int pos) const
{
return (pos == size()) ? 0 : bf_[pos];
return (0 <= pos && pos < size()) ? &bf_[pos] : 0;
}
void MathArray::insert(int pos, MathInset * p)
{
bf_.insert(begin() + pos, p);
//cerr << "\n 1: "; p->write(cerr, true); cerr << p << "\n";
// inserting th
bf_.insert(begin() + pos, MathAtom(p));
//cerr << "\n 2: "; p->write(cerr, true); cerr << p << "\n";
}
void MathArray::insert(int pos, MathArray const & array)
{
bf_.insert(begin() + pos, array.begin(), array.end());
deep_copy(begin() + pos, begin() + pos + array.size());
}
@ -142,15 +116,13 @@ void MathArray::erase(int pos)
void MathArray::erase(int pos1, int pos2)
{
for (iterator it = begin() + pos1; it != begin() + pos2; ++it)
delete *it;
bf_.erase(begin() + pos1, begin() + pos2);
}
MathInset * MathArray::back() const
MathAtom & MathArray::back()
{
return size() ? bf_.back() : 0;
return bf_.back();
}
@ -174,19 +146,21 @@ std::ostream & operator<<(std::ostream & os, MathArray const & ar)
return os;
}
// returns sequence of char with same code starting at it up to end
// it might be less, though...
string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
{
string s;
MathCharInset const * p = (*it)->asCharInset();
MathCharInset const * p = it->nucleus()->asCharInset();
if (!p)
return s;
MathTextCodes c = p->code();
while (it != end && (p = (*it)->asCharInset()) && p->code() == c) {
for (MathTextCodes c = p->code(); it != end; ++it) {
p = it->nucleus()->asCharInset();
if (!p || it->up() || it->down() || p->code() != c)
break;
s += p->getChar();
++it;
}
return s;
}
@ -194,18 +168,17 @@ string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
void MathArray::write(ostream & os, bool fragile) const
{
for (const_iterator it = begin(); it != end(); ) {
MathCharInset const * p = (*it)->asCharInset();
if (p) {
for (const_iterator it = begin(); it != end(); ++it) {
MathCharInset const * p = it->nucleus()->asCharInset();
if (p && !it->up() && !it->down()) {
// special handling for character sequences with the same code
string s = charSequence(it, end());
p->writeHeader(os);
os << s;
p->writeTrailer(os);
it += s.size();
it += s.size() - 1;
} else {
(*it)->write(os, fragile);
++it;
it->write(os, fragile);
}
}
}
@ -225,7 +198,7 @@ void MathArray::writeNormal(ostream & os) const
void MathArray::validate(LaTeXFeatures & features) const
{
for (const_iterator it = begin(); it != end(); ++it)
(*it)->validate(features);
it->validate(features);
}
@ -235,7 +208,6 @@ void MathArray::pop_back()
lyxerr << "pop_back from empty array!\n";
return;
}
delete back();
bf_.pop_back();
}

View File

@ -18,6 +18,7 @@
#include <vector>
#include <iosfwd>
#include "math_atom.h"
class MathInset;
class MathMacro;
@ -35,10 +36,11 @@ class LaTeXFeatures;
\author Lars Gullik Bjønnes
\version February 2001
*/
class MathArray {
public:
///
typedef std::vector<MathInset *> buffer_type;
typedef std::vector<MathAtom> buffer_type;
///
typedef buffer_type::const_iterator const_iterator;
///
@ -48,13 +50,7 @@ public:
///
MathArray();
///
MathArray(MathArray const &);
///
MathArray(MathArray const &, int from, int to);
///
MathArray & operator=(MathArray const &);
///
~MathArray();
///
int size() const;
@ -87,7 +83,7 @@ public:
///
void pop_back();
///
MathInset * back() const;
MathAtom & back();
///
void dump(std::ostream &) const;
@ -95,12 +91,11 @@ public:
void dump2(std::ostream &) const;
///
void substitute(MathMacro const &);
///
///
MathInset * nextInset(int pos);
MathAtom * at(int pos);
///
MathInset const * nextInset(int pos) const;
MathAtom const * at(int pos) const;
///
void write(std::ostream &, bool) const;
///
@ -116,8 +111,6 @@ public:
///
iterator end();
private:
///
void deep_copy(iterator from, iterator to);
/// Buffer
buffer_type bf_;
};

View File

@ -698,7 +698,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
result = FINISHED_RIGHT;
}
mathcursor->normalize();
//mathcursor->normalize();
if (was_macro != mathcursor->inMacroMode()
&& action >= 0 && action != LFUN_BACKSPACE)

376
src/mathed/math_atom.C Normal file
View File

@ -0,0 +1,376 @@
/*
* File: math_inset.C
* Purpose: Implementation of insets for mathed
* Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
* Created: January 1996
* Description:
*
* Dependencies: Xlib, XForms
*
* Copyright: 1996, 1997 Alejandro Aguilar Sierra
*
* Version: 0.8beta.
*
* You are free to use and modify this code under the terms of
* the GNU General Public Licence version 2 or later.
*/
#ifdef __GNUG__
#pragma implementation
#endif
#include "math_atom.h"
#include "math_scriptinset.h"
#include "debug.h"
#include "support.h"
#include "support/LAssert.h"
MathAtom::MathAtom()
: nucleus_(0), limits_(0), xo_(0), yo_(0)
{
script_[0] = 0;
script_[1] = 0;
}
MathAtom::MathAtom(MathInset * p)
: nucleus_(p), limits_(0), xo_(0), yo_(0)
{
script_[0] = 0;
script_[1] = 0;
}
MathAtom::MathAtom(MathAtom const & p)
{
copy(p);
}
void MathAtom::operator=(MathAtom const & p)
{
if (this != &p) {
done();
copy(p);
}
}
MathAtom::~MathAtom()
{
done();
}
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
{
return ascent() + descent();
}
std::ostream & operator<<(std::ostream & os, MathAtom const & atom)
{
atom.write(os, false);
return os;
}
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)
{
if (sz >= 0) {
size_ = sz;
flag = flag & ~LMPF_FIXED_SIZE;
}
}
*/
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];
}
int MathAtom::dy0() const
{
lyx::Assert(down());
int des = down()->ascent();
if (hasLimits())
des += ndes() + 2;
else
des = std::max(des, ndes());
return des;
}
int MathAtom::dy1() const
{
lyx::Assert(up());
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
{
int asc = nasc();
if (up())
asc += hasLimits() ? up()->height() + 2 : up()->ascent();
return asc;
}
int MathAtom::descent() const
{
int des = ndes();
if (down())
des += hasLimits() ? down()->height() + 2 : down()->descent();
return des;
}
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() : 0;
}
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);
if (up())
up()->xcell(0).draw(pain, x + dx1(), y - dy1());
if (down())
down()->xcell(0).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 (up()) {
os << "^{";
up()->write(os, fragile);
os << "}";
}
if (down()) {
os << "_{";
down()->write(os, fragile);
os << "}";
}
}
bool MathAtom::hasLimits() const
{
return
limits_ == 1 || (limits_ == 0 && nucleus() && nucleus()->isScriptable());
}
void MathAtom::substitute(MathArray & array, MathMacro const & m) const
{
if (nucleus())
nucleus()->substitute(array, m);
if (up())
up()->substitute(array, m);
if (down())
down()->substitute(array, 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;
}
}

150
src/mathed/math_atom.h Normal file
View File

@ -0,0 +1,150 @@
// -*- C++ -*-
#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.
Exactly where the subscript and superscript are drawn depends on the
size, and type, of the nucleus they are attached to.
Jules
*/
class LaTeXFeatures;
class MathCharInset;
class MathScriptInset;
class MathInset;
class MathMacro;
class MathArray;
class Painter;
class MathAtom {
public:
///
MathAtom();
///
MathAtom(MathAtom const &);
///
explicit MathAtom(MathInset * p);
///
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;
///
void handleFont(MathTextCodes) {}
/// make sure superscript is available
MathScriptInset * ensure(bool up);
/// delete subscript array if empty
void removeEmptyScripts();
/// 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;
/// returns superscript
MathScriptInset * up() const;
/// returns subscript
MathScriptInset * down() const;
///
MathInset * nucleus() const { return nucleus_; }
///
void substitute(MathArray &, const MathMacro &) const;
///
void write(std::ostream &, bool) const;
///
void writeNormal(std::ostream &) const;
protected:
/// possible subscript (index 0) and superscript (index 1)
MathScriptInset * script_[2];
///
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 superscript
int dx0() const;
/// returns x offset for subscript
int dx1() const;
/// returns x offset for main part
int dxx() const;
/// returns width of nucleus if any
int nwid() 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

View File

@ -147,14 +147,17 @@ bool MathCursor::popLeft()
if (Cursor_.size() <= 1)
return false;
Cursor_.pop_back();
//array().at(pos())->removeEmptyScripts();
return true;
}
bool MathCursor::popRight()
{
if (Cursor_.size() <= 1)
return false;
Cursor_.pop_back();
//array().at(pos())->removeEmptyScripts();
posRight();
return true;
}
@ -417,7 +420,8 @@ void MathCursor::insert(MathInset * p)
selDel();
}
array().insert(pos(), p);
array().insert(pos(), p); // this invalidates the pointer!
p = array().at(pos())->nucleus();
posRight();
}
@ -429,7 +433,10 @@ void MathCursor::niceInsert(MathInset * p)
return;
}
selCut();
insert(p);
//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";
if (p->nargs()) {
posLeft();
right(); // do not push for e.g. MathSymbolInset
@ -522,29 +529,15 @@ bool MathCursor::up(bool sel)
if (selection_)
return goUp();
// check whether we could move into an inset on the right or on the left
MathInset * p = nextInset();
if (p) {
int idxx, poss;
if (p->idxFirstUp(idxx, poss)) {
pushLeft(p);
idx() = idxx;
pos() = poss;
dump("up 3");
return true;
}
// check whether we could move into a superscript on the right or on the left
if (prevAtom() && prevAtom()->up()) {
pushRight(prevAtom()->up());
return true;
}
p = prevInset();
if (p) {
int idxx, poss;
if (p->idxLastUp(idxx, poss)) {
pushRight(p);
idx() = idxx;
pos() = poss;
dump("up 4");
return true;
}
if (nextAtom() && nextAtom()->up()) {
pushLeft(nextAtom()->up());
return true;
}
return goUp();
@ -560,31 +553,15 @@ bool MathCursor::down(bool sel)
if (selection_)
return goDown();
// check whether we could move into an inset on the right or on the left
MathInset * p = nextInset();
if (p) {
int idxx = 0;
int poss = 0;
if (p->idxFirstDown(idxx, poss)) {
pushLeft(p);
idx() = idxx;
pos() = poss;
dump("Down 3");
return true;
}
// check whether we could move into an subscript on the right or on the left
if (prevAtom() && prevAtom()->down()) {
pushRight(prevAtom()->down());
return true;
}
p = prevInset();
if (p) {
int idxx = 0;
int poss = 0;
if (p->idxLastDown(idxx, poss)) {
pushRight(p);
idx() = idxx;
pos() = poss;
dump("Down 4");
return true;
}
if (nextAtom() && nextAtom()->down()) {
pushLeft(nextAtom()->down());
return true;
}
return goDown();
@ -593,12 +570,12 @@ bool MathCursor::down(bool sel)
bool MathCursor::toggleLimits()
{
MathScriptInset * p = prevScriptInset();
if (!p)
MathAtom * t = prevAtom();
if (!t)
return false;
int old = p->limits();
p->limits(old < 0 ? 1 : -1);
return old != p->limits();
int old = t->limits();
t->limits(old < 0 ? 1 : -1);
return old != t->limits();
}
@ -624,10 +601,12 @@ void MathCursor::macroModeClose()
string MathCursor::macroName() const
{
string s;
int p = pos() - 1;
while (p >= 0 && array().nextInset(p)->code() == LM_TC_TEX) {
s = array().nextInset(p)->getChar() + s;
--p;
for (int i = pos() - 1; i >= 0; --i) {
MathInset * p = array().at(i)->nucleus();
if (p && p->code() == LM_TC_TEX)
s = p->getChar() + s;
else
break;
}
return s;
}
@ -752,8 +731,11 @@ void MathCursor::handleFont(MathTextCodes t)
getSelection(i1, i2);
if (i1.idx_ == i2.idx_) {
MathArray & ar = i1.cell();
for (int pos = i1.pos_; pos != i2.pos_; ++pos)
ar.nextInset(pos)->handleFont(t);
for (int pos = i1.pos_; pos != i2.pos_; ++pos) {
MathInset * p = ar.at(pos)->nucleus();
if (p)
p->handleFont(t);
}
}
} else
lastcode_ = (lastcode_ == t) ? LM_TC_VAR : t;
@ -772,7 +754,8 @@ void MathCursor::handleNest(MathInset * p)
selCut();
p->cell(0) = theSelection.glue();
}
insert(p);
insert(p); // this invalidates p!
p = prevAtom()->nucleus();
pushRight(p);
}
@ -935,36 +918,47 @@ string MathCursorPos::readString()
MathInset * MathCursor::prevInset() const
{
normalize();
if (!pos())
return 0;
return array().nextInset(pos() - 1);
return prevAtom() ? prevAtom()->nucleus() : 0;
}
MathInset * MathCursor::nextInset() const
{
normalize();
return array().nextInset(pos());
}
MathScriptInset * MathCursor::prevScriptInset() const
{
normalize();
MathInset * p = prevInset();
return (p && p->isScriptInset()) ? static_cast<MathScriptInset *>(p) : 0;
return nextAtom() ? nextAtom()->nucleus() : 0;
}
MathSpaceInset * MathCursor::prevSpaceInset() const
{
normalize();
MathInset * p = prevInset();
return (p && p->isSpaceInset()) ? static_cast<MathSpaceInset *>(p) : 0;
}
MathAtom const * MathCursor::prevAtom() const
{
return array().at(pos() - 1);
}
MathAtom * MathCursor::prevAtom()
{
return array().at(pos() - 1);
}
MathAtom const * MathCursor::nextAtom() const
{
return array().at(pos());
}
MathAtom * MathCursor::nextAtom()
{
return array().at(pos());
}
MathArray & MathCursor::array() const
{
static MathArray dummy;
@ -1231,24 +1225,12 @@ void MathCursor::interpret(string const & s)
if (c == '^' || c == '_') {
bool const up = (s[0] == '^');
selCut();
MathScriptInset * p = prevScriptInset();
if (!p) {
MathInset * b = prevInset();
if (b && b->isScriptable()) {
p = new MathScriptInset(up, !up, b->clone());
posLeft();
plainErase();
} else
p = new MathScriptInset(up, !up);
insert(p);
if (!prevInset()) {
insert('{', LM_TC_TEX);
insert('}', LM_TC_TEX);
}
pushRight(p);
if (up)
p->up(true);
else
p->down(true);
idx() = up ? 0 : 1;
pos() = 0;
MathInset * par = prevAtom()->ensure(up);
pushRight(par);
selPaste();
return;
}

View File

@ -24,6 +24,7 @@
#include "math_defs.h"
class MathInset;
class MathAtom;
class MathArrayInset;
class MathFuncInset;
class MathMatrixInset;
@ -204,6 +205,14 @@ public:
MathArray & array() const;
///
MathXArray & xarray() const;
///
MathAtom const * prevAtom() const;
///
MathAtom * prevAtom();
///
MathAtom const * nextAtom() const;
///
MathAtom * nextAtom();
/// returns the selection
void getSelection(MathCursorPos &, MathCursorPos &) const;

View File

@ -28,6 +28,12 @@ bool MathDecorationInset::upper() const
}
bool MathDecorationInset::isScriptable() const
{
return true;
}
bool MathDecorationInset::protect() const
{
return

View File

@ -27,6 +27,8 @@ public:
void metrics(MathStyles st) const;
///
void writeNormal(std::ostream & os) const;
///
bool isScriptable() const;
private:
///

View File

@ -2,7 +2,7 @@
MathDimInset::MathDimInset()
: width_(0), ascent_(0), descent_(0)
: MathInset(), width_(0), ascent_(0), descent_(0)
{}

View File

@ -65,8 +65,9 @@ MathInset * createMathInset(latexkeys const * l)
MathInset * createMathInset(string const & s)
{
//cerr << "creating inset with name: '" << s << "'\n";
latexkeys const * l = in_word_set(s);
if (l)
if (l)
return createMathInset(l);
if (MathMacroTable::hasTemplate(s))

View File

@ -17,6 +17,12 @@ MathInset * MathFuncLimInset::clone() const
}
bool MathFuncLimInset::isScriptable() const
{
return size_ == LM_ST_DISPLAY;
}
void MathFuncLimInset::write(ostream & os, bool /* fragile */) const
{
os << '\\' << sym_->name << ' ';

View File

@ -24,7 +24,7 @@ public:
///
void draw(Painter &, int x, int y) const;
///
bool isScriptable() const { return true; }
bool isScriptable() const;
private:
///

View File

@ -268,7 +268,7 @@ string MathGridInset::eolString(int row) const
// make sure an upcoming '[' does not break anything
MathArray const & c = cell(index(row + 1, 0));
if (c.size() && (*c.begin())->getChar() == '[')
if (c.begin() && c.begin()->nucleus()->getChar() == '[')
return "\\\\[0pt]\n";
return "\\\\\n";

View File

@ -20,6 +20,7 @@
#endif
#include "math_inset.h"
#include "math_scriptinset.h"
#include "debug.h"
@ -31,6 +32,10 @@ MathInset::MathInset()
{}
MathInset::~MathInset()
{}
int MathInset::height() const
{
return ascent() + descent();

View File

@ -39,14 +39,14 @@
class LaTeXFeatures;
class MathCharInset;
class MathScriptInset;
class MathInset {
public:
///
MathInset();
/// the virtual base destructor
virtual ~MathInset() {}
virtual ~MathInset();
/// draw the object, sets xo_ and yo_ cached values
virtual void draw(Painter &, int x, int y) const;
@ -186,6 +186,8 @@ public:
virtual char getChar() const { return 0; }
///
virtual MathTextCodes code() const { return LM_TC_MIN; }
/// identifies things that can get \limits or \nolimits
virtual bool takesLimits() const { return false; }
///
virtual void push_back(MathInset *);

View File

@ -36,7 +36,7 @@ int getCols(MathInsetTypes type)
int firstRelOp(MathArray const & array)
{
for (MathArray::const_iterator it = array.begin(); it != array.end(); ++it)
if ((*it)->isRelOp())
if (it->nucleus()->isRelOp())
return it - array.begin();
return array.size();
}
@ -92,6 +92,7 @@ char MathMatrixInset::defaultColAlign(int col)
return 'c';
}
int MathMatrixInset::defaultColSpace(int col)
{
switch (getType()) {

View File

@ -43,9 +43,13 @@ MathArray const & MathNestInset::cell(int i) const
void MathNestInset::substitute(MathArray & array, MathMacro const & m) const
{
#warning Huch?
/*
MathNestInset * p = clone();
array.push_back(clone());
for (int i = 0; i < nargs(); ++i)
array.back()->cell(i).substitute(m);
array.back().cellsubstitute(m);
*/
}

View File

@ -61,34 +61,6 @@ bool stared(string const & s)
return n && s[n - 1] == '*';
}
MathScriptInset * prevScriptInset(MathArray const & array)
{
MathInset * p = array.back();
return (p && p->isScriptInset()) ? static_cast<MathScriptInset *>(p) : 0;
}
MathInset * lastScriptInset(MathArray & array, bool up, int limits)
{
MathScriptInset * p = prevScriptInset(array);
if (!p) {
MathInset * b = array.back();
if (b && b->isScriptable()) {
p = new MathScriptInset(up, !up, b->clone());
array.pop_back();
} else {
p = new MathScriptInset(up, !up);
}
array.push_back(p);
}
if (up)
p->up(true);
else
p->down(true);
if (limits)
p->limits(limits);
return p;
}
// These are TeX's catcodes
@ -647,7 +619,6 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
MathTextCodes yyvarcode = LM_TC_MIN;
bool panic = false;
int limits = 0;
while (good()) {
Token const & t = getToken();
@ -723,12 +694,13 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
array.push_back(new MathCharInset('&', LM_TC_TEX));
}
else if (t.cat() == catSuper)
parse_into(lastScriptInset(array, true, limits)->cell(0), FLAG_ITEM);
else if (t.cat() == catSub)
parse_into(lastScriptInset(array, false, limits)->cell(1), FLAG_ITEM);
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);
}
else if (t.character() == ']' && (flags & FLAG_BRACK_END))
return;
@ -759,11 +731,11 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
array.push_back(createMathInset("\\"));
}
else if (t.cs() == "limits")
limits = 1;
else if (t.cs() == "limits" && array.size())
array.back().limits(1);
else if (t.cs() == "nolimits")
limits = -1;
else if (t.cs() == "nolimits" && array.size())
array.back().limits(-1);
else if (t.cs() == "nonumber")
curr_num_ = false;
@ -775,12 +747,12 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
char c = getChar();
if (c == '[') {
array.push_back(new MathRootInset);
parse_into(array.back()->cell(0), FLAG_BRACK_END);
parse_into(array.back()->cell(1), FLAG_ITEM);
parse_into(array.back().nucleus()->cell(0), FLAG_BRACK_END);
parse_into(array.back().nucleus()->cell(1), FLAG_ITEM);
} else {
putback();
array.push_back(new MathSqrtInset);
parse_into(array.back()->cell(0), FLAG_ITEM);
parse_into(array.back().nucleus()->cell(0), FLAG_ITEM);
}
}
@ -863,15 +835,12 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
}
else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
limits = 0;
MathInset * p = createMathInset(t.cs());
// search backward for position of last '{' if any
int pos;
for (pos = array.size() - 1; pos >= 0; --pos) {
MathInset * q = array.nextInset(pos);
if (q->getChar() == '{')
for (pos = array.size() - 1; pos >= 0; --pos)
if (array.at(pos)->nucleus()->getChar() == '{')
break;
}
if (pos >= 0) {
// found it -> use the part after '{' as "numerator", erase the '{'
p->cell(0) = MathArray(array, pos + 1, array.size());
@ -885,7 +854,6 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
}
else if (t.cs().size()) {
limits = 0;
latexkeys const * l = in_word_set(t.cs());
if (l) {
if (l->token == LM_TK_FONT) {
@ -900,7 +868,7 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
MathArray ar;
parse_into(ar, FLAG_ITEM, t);
for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it)
(*it)->handleFont(t);
it->nucleus()->handleFont(t);
array.push_back(ar);
// undo catcode changes

View File

@ -1,75 +1,26 @@
#include <config.h>
#include "debug.h"
#include "support.h"
#include "support/LOstream.h"
#ifdef __GNUG__
#pragma implementation
#endif
#include "math_scriptinset.h"
#include "support/LOstream.h"
#include "support.h"
MathScriptInset::MathScriptInset()
: MathNestInset(2), up_(false), down_(false), limits_(0), symbol_(0)
MathScriptInset::MathScriptInset(bool up)
: MathNestInset(1), up_(up)
{}
MathScriptInset::MathScriptInset(bool up, bool down, MathInset * symbol)
: MathNestInset(2), up_(up), down_(down), limits_(0), symbol_(symbol)
{}
MathScriptInset::MathScriptInset(MathScriptInset const & p)
: MathNestInset(p), up_(p.up_), down_(p.down_),
limits_(p.limits_), symbol_(p.symbol_ ? p.symbol_->clone() : 0)
{}
MathScriptInset::~MathScriptInset()
{
delete symbol_;
}
MathInset * MathScriptInset::clone() const
{
{
return new MathScriptInset(*this);
}
bool MathScriptInset::up() const
{
return up_;
}
bool MathScriptInset::down() const
{
return down_;
}
void MathScriptInset::up(bool b)
{
up_ = b;
}
void MathScriptInset::down(bool b)
{
down_ = b;
}
bool MathScriptInset::idxRight(int &, int &) const
{
return false;
}
bool MathScriptInset::idxLeft(int &, int &) const
{
return false;
}
#if 0
bool MathScriptInset::idxUp(int & idx, int & pos) const
{
@ -143,28 +94,6 @@ bool MathScriptInset::idxLastDown(int & idx, int & pos) const
return true;
}
void MathScriptInset::write(std::ostream & os, bool fragile) const
{
if (symbol_) {
symbol_->write(os, fragile);
if (limits())
os << (limits() == 1 ? "\\limits" : "\\nolimits");
}
if (up()) {
os << "^{";
cell(0).write(os, fragile);
os << "}";
}
if (down()) {
os << "_{";
cell(1).write(os, fragile);
os << "}";
}
os << " ";
}
void MathScriptInset::idxDelete(int & idx, bool & popit, bool & deleteit)
{
if (idx == 0)
@ -175,109 +104,28 @@ void MathScriptInset::idxDelete(int & idx, bool & popit, bool & deleteit)
deleteit = !(up() || down());
}
#endif
bool MathScriptInset::isActive() const
void MathScriptInset::write(std::ostream & os, bool fragile) const
{
return false;
}
int MathScriptInset::limits() const
{
return limits_;
}
void MathScriptInset::limits(int limits)
{
limits_ = limits;
}
bool MathScriptInset::hasLimits() const
{
return
symbol_ && (limits_ == 1 || (limits_ == 0 && size() == LM_ST_DISPLAY));
}
void MathScriptInset::writeNormal(std::ostream & os) const
{
if (limits() && symbol_)
os << "[" << (limits() ? "limits" : "nolimits") << "]";
if (up()) {
os << "[superscript ";
cell(0).writeNormal(os);
os << "] ";
}
if (down()) {
os << "[subscript ";
cell(1).writeNormal(os);
os << "] ";
}
cell(0).write(os, fragile);
}
void MathScriptInset::metrics(MathStyles st) const
{
size_ = st;
MathStyles tt = smallerStyleScript(st);
xcell(0).metrics(tt);
xcell(1).metrics(tt);
width_ = std::max(xcell(0).width(), xcell(1).width());
if (hasLimits()) {
symbol_->metrics(st);
int wid = symbol_->width();
ascent_ = symbol_->ascent();
descent_ = symbol_->descent();
width_ = std::max(width_, wid);
if (up()) {
ascent_ += xcell(0).height() + 2;
dy0_ = - (ascent_ - xcell(0).ascent());
}
if (down()) {
descent_ += xcell(1).height() + 2;
dy1_ = descent_ - xcell(1).descent();
}
dxx_ = (width_ - wid) / 2;
dx0_ = (width_ - xcell(0).width()) / 2;
dx1_ = (width_ - xcell(1).width()) / 2;
} else {
int asc = 0;
int des = 0;
int wid = 0;
mathed_char_height(LM_TC_VAR, st, 'I', asc, des);
if (symbol_) {
symbol_->metrics(st);
wid = symbol_->width();
asc = symbol_->ascent();
des = symbol_->descent();
}
ascent_ = up() ? xcell(0).height() + asc : 0;
descent_ = down() ? xcell(1).height() + des : 0;
width_ += wid;
dy0_ = - asc - xcell(0).descent();
dy1_ = des + xcell(1).ascent();
dx0_ = wid;
dx1_ = wid;
dxx_ = 0;
}
size_ = st;
xcell(0).metrics(st);
width_ = xcell(0).width();
ascent_ = xcell(0).ascent();
descent_ = xcell(0).descent();
}
void MathScriptInset::draw(Painter & pain, int x, int y) const
{
{
xo(x);
yo(y);
if (symbol_)
symbol_->draw(pain, x + dxx_, y);
if (up())
xcell(0).draw(pain, x + dx0_, y + dy0_);
if (down())
xcell(1).draw(pain, x + dx1_, y + dy1_);
xcell(0).draw(pain, x, y);
}

View File

@ -12,90 +12,22 @@
\author André Pönitz
*/
class MathScriptInset : public MathNestInset {
public:
///
MathScriptInset();
///
MathScriptInset(bool up, bool down, MathInset * = 0);
///
MathScriptInset(MathScriptInset const &);
///
~MathScriptInset();
MathScriptInset(bool up);
///
MathInset * clone() const;
///
void write(std::ostream &, bool fragile) const;
///
void writeNormal(std::ostream &) const;
///
void metrics(MathStyles st) const;
///
void draw(Painter &, int x, int y) const;
///
bool idxUp(int & idx, int & pos) const;
///
bool idxDown(int & idx, int & pos) const;
///
bool idxLeft(int & idx, int & pos) const;
///
bool idxRight(int & idx, int & pos) const;
///
bool idxFirst(int & idx, int & pos) const;
///
bool idxFirstUp(int & idx, int & pos) const;
///
bool idxFirstDown(int & idx, int & pos) const;
///
bool idxLast(int & idx, int & pos) const;
///
bool idxLastUp(int & idx, int & pos) const;
///
bool idxLastDown(int & idx, int & pos) const;
///
void idxDelete(int & idx, bool & popit, bool & deleteit);
///
bool up() const;
///
bool down() const;
///
void up(bool);
///
void down(bool);
///
void limits(int);
///
int limits() const;
///
bool isActive() const;
/// Identifies ScriptInsets
bool isScriptInset() const { return true; }
///
int xoffset() const { return dxx_; }
private:
///
bool hasLimits() const;
///
bool up_;
///
bool down_;
/// 1: \limits, -1: \nolimits, 0: use default
int limits_;
/// x offset cache for drawing the superscript
mutable int dx0_;
/// x offset cache for drawing the subscript
mutable int dx1_;
/// x offset cache for drawing the inner symbol
mutable int dxx_;
/// y offset cache for drawing the superscript
mutable int dy0_;
/// y offset cache for drawing the subscript
mutable int dy1_;
///
MathInset * symbol_;
};
#endif

View File

@ -102,6 +102,12 @@ bool MathSymbolInset::isRelOp() const
bool MathSymbolInset::isScriptable() const
{
return size_ == LM_ST_DISPLAY && sym_->token == LM_TK_CMEX;
}
bool MathSymbolInset::takesLimits() const
{
return sym_->token == LM_TK_CMEX;
}

View File

@ -27,6 +27,8 @@ public:
bool isRelOp() const;
///
bool isScriptable() const;
/// identifies things that can get \limits or \nolimits
bool takesLimits() const;
private:
///

View File

@ -11,9 +11,6 @@
#include "Painter.h"
#include "debug.h"
using std::max;
using std::min;
MathXArray::MathXArray()
: width_(0), ascent_(0), descent_(0), xo_(0), yo_(0), style_(LM_ST_TEXT)
@ -33,14 +30,11 @@ void MathXArray::metrics(MathStyles st) const
//lyxerr << "MathXArray::metrics(): '" << data_ << "'\n";
for (int pos = 0; pos < data_.size(); ++pos) {
MathInset const * p = data_.nextInset(pos);
MathAtom const * p = data_.at(pos);
p->metrics(st);
int asc = p->ascent();
int des = p->descent();
int wid = p->width();
ascent_ = max(ascent_, asc);
descent_ = max(descent_, des);
width_ += wid;
ascent_ = std::max(ascent_, p->ascent());
descent_ = std::max(descent_, p->descent());
width_ += p->width();
}
}
@ -56,7 +50,7 @@ void MathXArray::draw(Painter & pain, int x, int y) const
}
for (int pos = 0; pos < data_.size(); ++pos) {
MathInset const * p = data_.nextInset(pos);
MathAtom const * p = data_.at(pos);
p->draw(pain, x, y);
x += p->width();
}
@ -66,7 +60,7 @@ void MathXArray::draw(Painter & pain, int x, int y) const
int MathXArray::pos2x(int targetpos) const
{
int x = 0;
targetpos = min(targetpos, data_.size());
targetpos = std::min(targetpos, data_.size());
for (int pos = 0; pos < targetpos; ++pos)
x += width(pos);
return x;
@ -90,9 +84,8 @@ int MathXArray::x2pos(int targetx) const
int MathXArray::width(int pos) const
{
if (pos >= data_.size())
return 0;
return data_.nextInset(pos)->width();
MathAtom const * t = data_.at(pos);
return t ? t->width() : 0;
}
@ -101,4 +94,3 @@ std::ostream & operator<<(std::ostream & os, MathXArray const & ar)
os << ar.data_;
return os;
}