From e4c58b72be2c1357a389f71b20e5c29809ed6cbf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Tue, 11 Sep 2001 10:58:17 +0000 Subject: [PATCH] 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 --- src/mathed/ChangeLog | 10 + src/mathed/Makefile.am | 2 + src/mathed/array.C | 80 +++---- src/mathed/array.h | 19 +- src/mathed/formulabase.C | 2 +- src/mathed/math_atom.C | 376 ++++++++++++++++++++++++++++++ src/mathed/math_atom.h | 150 ++++++++++++ src/mathed/math_cursor.C | 158 ++++++------- src/mathed/math_cursor.h | 9 + src/mathed/math_decorationinset.C | 6 + src/mathed/math_decorationinset.h | 2 + src/mathed/math_diminset.C | 2 +- src/mathed/math_factory.C | 3 +- src/mathed/math_funcliminset.C | 6 + src/mathed/math_funcliminset.h | 2 +- src/mathed/math_gridinset.C | 2 +- src/mathed/math_inset.C | 5 + src/mathed/math_inset.h | 6 +- src/mathed/math_matrixinset.C | 3 +- src/mathed/math_nestinset.C | 6 +- src/mathed/math_parser.C | 66 ++---- src/mathed/math_scriptinset.C | 190 ++------------- src/mathed/math_scriptinset.h | 72 +----- src/mathed/math_symbolinset.C | 6 + src/mathed/math_symbolinset.h | 2 + src/mathed/xarray.C | 24 +- 26 files changed, 739 insertions(+), 470 deletions(-) create mode 100644 src/mathed/math_atom.C create mode 100644 src/mathed/math_atom.h diff --git a/src/mathed/ChangeLog b/src/mathed/ChangeLog index 6997fabb52..ec3bde91da 100644 --- a/src/mathed/ChangeLog +++ b/src/mathed/ChangeLog @@ -1,3 +1,13 @@ +2001-09-11 André Pönitz + + * 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 * math_parser.C (tokenize): add a .c_str() (needed with lyxstring) diff --git a/src/mathed/Makefile.am b/src/mathed/Makefile.am index c83aa507ab..cc3b6915d3 100644 --- a/src/mathed/Makefile.am +++ b/src/mathed/Makefile.am @@ -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 \ diff --git a/src/mathed/array.C b/src/mathed/array.C index 593b6fe8d4..5b9b7cbbda 100644 --- a/src/mathed/array.C +++ b/src/mathed/array.C @@ -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(); } diff --git a/src/mathed/array.h b/src/mathed/array.h index f5c6d84923..939310945d 100644 --- a/src/mathed/array.h +++ b/src/mathed/array.h @@ -18,6 +18,7 @@ #include #include +#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 buffer_type; + typedef std::vector 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_; }; diff --git a/src/mathed/formulabase.C b/src/mathed/formulabase.C index cc131a3347..9e950a7942 100644 --- a/src/mathed/formulabase.C +++ b/src/mathed/formulabase.C @@ -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) diff --git a/src/mathed/math_atom.C b/src/mathed/math_atom.C new file mode 100644 index 0000000000..33ae8e4bf7 --- /dev/null +++ b/src/mathed/math_atom.C @@ -0,0 +1,376 @@ +/* + * File: math_inset.C + * Purpose: Implementation of insets for mathed + * Author: Alejandro Aguilar Sierra + * 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; + } +} diff --git a/src/mathed/math_atom.h b/src/mathed/math_atom.h new file mode 100644 index 0000000000..c5b7e7af0c --- /dev/null +++ b/src/mathed/math_atom.h @@ -0,0 +1,150 @@ +// -*- C++ -*- + +#ifndef MATH_ATOM_H +#define MATH_ATOM_H + +#include +#include + +#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 diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index b38a078b49..f9a8524493 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -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,33 +918,44 @@ 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()); + return nextAtom() ? nextAtom()->nucleus() : 0; } -MathScriptInset * MathCursor::prevScriptInset() const +MathSpaceInset * MathCursor::prevSpaceInset() const { - normalize(); MathInset * p = prevInset(); - return (p && p->isScriptInset()) ? static_cast(p) : 0; + return (p && p->isSpaceInset()) ? static_cast(p) : 0; } -MathSpaceInset * MathCursor::prevSpaceInset() const +MathAtom const * MathCursor::prevAtom() const { - normalize(); - MathInset * p = prevInset(); - return (p && p->isSpaceInset()) ? static_cast(p) : 0; + 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()); } @@ -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; } diff --git a/src/mathed/math_cursor.h b/src/mathed/math_cursor.h index 65d83ba2f2..3b9d2eb491 100644 --- a/src/mathed/math_cursor.h +++ b/src/mathed/math_cursor.h @@ -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; diff --git a/src/mathed/math_decorationinset.C b/src/mathed/math_decorationinset.C index 8d3d3501e8..d620ed9223 100644 --- a/src/mathed/math_decorationinset.C +++ b/src/mathed/math_decorationinset.C @@ -28,6 +28,12 @@ bool MathDecorationInset::upper() const } +bool MathDecorationInset::isScriptable() const +{ + return true; +} + + bool MathDecorationInset::protect() const { return diff --git a/src/mathed/math_decorationinset.h b/src/mathed/math_decorationinset.h index 58f74cca21..97b5b26681 100644 --- a/src/mathed/math_decorationinset.h +++ b/src/mathed/math_decorationinset.h @@ -27,6 +27,8 @@ public: void metrics(MathStyles st) const; /// void writeNormal(std::ostream & os) const; + /// + bool isScriptable() const; private: /// diff --git a/src/mathed/math_diminset.C b/src/mathed/math_diminset.C index f3065be8e3..23a595639b 100644 --- a/src/mathed/math_diminset.C +++ b/src/mathed/math_diminset.C @@ -2,7 +2,7 @@ MathDimInset::MathDimInset() - : width_(0), ascent_(0), descent_(0) + : MathInset(), width_(0), ascent_(0), descent_(0) {} diff --git a/src/mathed/math_factory.C b/src/mathed/math_factory.C index 975cd1f89b..f18c1afcb3 100644 --- a/src/mathed/math_factory.C +++ b/src/mathed/math_factory.C @@ -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)) diff --git a/src/mathed/math_funcliminset.C b/src/mathed/math_funcliminset.C index b527af5fa2..d281b9e23b 100644 --- a/src/mathed/math_funcliminset.C +++ b/src/mathed/math_funcliminset.C @@ -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 << ' '; diff --git a/src/mathed/math_funcliminset.h b/src/mathed/math_funcliminset.h index 9510979aa7..dce77a090a 100644 --- a/src/mathed/math_funcliminset.h +++ b/src/mathed/math_funcliminset.h @@ -24,7 +24,7 @@ public: /// void draw(Painter &, int x, int y) const; /// - bool isScriptable() const { return true; } + bool isScriptable() const; private: /// diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index daf70daa96..944d87dccd 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -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"; diff --git a/src/mathed/math_inset.C b/src/mathed/math_inset.C index 9bc2339067..e9e4bb654b 100644 --- a/src/mathed/math_inset.C +++ b/src/mathed/math_inset.C @@ -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(); diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 668be97414..05b134ebe8 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -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 *); diff --git a/src/mathed/math_matrixinset.C b/src/mathed/math_matrixinset.C index 0401b8ba17..cc2610e369 100644 --- a/src/mathed/math_matrixinset.C +++ b/src/mathed/math_matrixinset.C @@ -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()) { diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index ebe624c044..386798529f 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -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); +*/ } diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index 4903647a69..0fec5ffb2e 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -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(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 diff --git a/src/mathed/math_scriptinset.C b/src/mathed/math_scriptinset.C index 8ee73f85a1..a8bf9d6b7b 100644 --- a/src/mathed/math_scriptinset.C +++ b/src/mathed/math_scriptinset.C @@ -1,75 +1,26 @@ +#include +#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; + return new MathScriptInset(*this); } +#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()); } - -bool MathScriptInset::isActive() 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)); -} +#endif -void MathScriptInset::writeNormal(std::ostream & os) const +void MathScriptInset::write(std::ostream & os, bool fragile) 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); } - diff --git a/src/mathed/math_scriptinset.h b/src/mathed/math_scriptinset.h index e0d7e23222..3dc848f989 100644 --- a/src/mathed/math_scriptinset.h +++ b/src/mathed/math_scriptinset.h @@ -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 + diff --git a/src/mathed/math_symbolinset.C b/src/mathed/math_symbolinset.C index cf39db7fc4..10520453ec 100644 --- a/src/mathed/math_symbolinset.C +++ b/src/mathed/math_symbolinset.C @@ -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; } diff --git a/src/mathed/math_symbolinset.h b/src/mathed/math_symbolinset.h index 68054886a4..fa2b5bbf4b 100644 --- a/src/mathed/math_symbolinset.h +++ b/src/mathed/math_symbolinset.h @@ -27,6 +27,8 @@ public: bool isRelOp() const; /// bool isScriptable() const; + /// identifies things that can get \limits or \nolimits + bool takesLimits() const; private: /// diff --git a/src/mathed/xarray.C b/src/mathed/xarray.C index 9f90ef41ef..4aa396bfa8 100644 --- a/src/mathed/xarray.C +++ b/src/mathed/xarray.C @@ -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; } - -- 2.39.5