]> git.lyx.org Git - features.git/commitdiff
Use references instead of pointers where possible
authorAndré Pönitz <poenitz@gmx.net>
Fri, 12 Oct 2001 12:02:49 +0000 (12:02 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Fri, 12 Oct 2001 12:02:49 +0000 (12:02 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2867 a592a061-630c-0410-9148-cb99ea01b6c8

37 files changed:
src/mathed/array.C
src/mathed/array.h
src/mathed/formula.C
src/mathed/formula.h
src/mathed/formulabase.C
src/mathed/formulabase.h
src/mathed/formulamacro.C
src/mathed/formulamacro.h
src/mathed/math_arrayinset.C
src/mathed/math_arrayinset.h
src/mathed/math_atom.C
src/mathed/math_atom.h
src/mathed/math_cursor.C
src/mathed/math_cursor.h
src/mathed/math_factory.C
src/mathed/math_factory.h
src/mathed/math_gridinset.C
src/mathed/math_gridinset.h
src/mathed/math_inset.h
src/mathed/math_macro.C
src/mathed/math_macro.h
src/mathed/math_macrotable.C
src/mathed/math_macrotable.h
src/mathed/math_macrotemplate.C
src/mathed/math_macrotemplate.h
src/mathed/math_matrixinset.C
src/mathed/math_matrixinset.h
src/mathed/math_nestinset.C
src/mathed/math_nestinset.h
src/mathed/math_parser.C
src/mathed/math_parser.h
src/mathed/math_rootinset.C
src/mathed/math_scriptinset.C
src/mathed/math_scriptinset.h
src/mathed/math_spaceinset.h
src/mathed/xarray.C
src/mathed/xarray.h

index 482d1c8d8519ce038e1c047310b00c5f9b8957ec..715350fda60eec914dc0ab26aec15d2fb55b2733 100644 (file)
@@ -8,6 +8,7 @@
 #include "debug.h"
 #include "array.h"
 #include "mathed/support.h"
+#include "support/LAssert.h"
 
 using std::ostream;
 using std::endl;
@@ -25,28 +26,38 @@ MathArray::MathArray(MathArray const & array, size_type from, size_type to)
 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);
 }
 
 
@@ -62,12 +73,6 @@ void MathArray::push_back(MathAtom const & t)
 }
 
 
-void MathArray::push_back(MathInset * p)
-{      
-       bf_.push_back(MathAtom(p));
-}
-
-
 void MathArray::push_back(MathArray const & array)
 {
        insert(size(), array);
@@ -127,14 +132,14 @@ MathAtom & MathArray::back()
 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() << ">";
 }
 
 
@@ -158,7 +163,7 @@ string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
                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();
        }
@@ -168,19 +173,27 @@ 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(); ++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);
                }
        }
 }
@@ -200,7 +213,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->nucleus()->validate(features);
 }
 
 
index 791427506552593468f1de324b06c90f7137d684..2f7cbe65588055ddcaaf1f769fbe9000b3c138f8 100644 (file)
@@ -20,7 +20,7 @@
 #include <iosfwd>
 #include "math_atom.h"
 
-class MathInset;
+class MathScriptInset;
 class MathMacro;
 class LaTeXFeatures;
 
@@ -64,7 +64,7 @@ public:
        void swap(MathArray &);
        
        ///
-       void insert(size_type pos, MathInset * inset);
+       void insert(size_type pos, MathAtom const &);
        ///
        void insert(size_type pos, MathArray const &);
 
@@ -76,12 +76,10 @@ public:
        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();
@@ -94,9 +92,9 @@ public:
        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;
        ///
@@ -111,6 +109,8 @@ public:
        iterator begin();
        ///
        iterator end();
+       ///
+       MathScriptInset const * asScript(const_iterator it) const;
 private:
        /// Buffer
        buffer_type bf_;
index 1a66a3663ce6166c1bea675ba602bfe4232538d0..0e4ab85af1c1f25b189d97144bcdeb0d860f4f42 100644 (file)
@@ -30,6 +30,7 @@
 #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"
@@ -48,40 +49,32 @@ using std::vector;
 
 
 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);
@@ -123,7 +116,7 @@ int InsetFormula::docbook(Buffer const * buf, ostream & os) const
 
 void InsetFormula::read(Buffer const *, LyXLex & lex)
 {
-       par(mathed_parse_normal(lex));
+       mathed_parse_normal(par_, lex);
        metrics();
 }
 
@@ -163,7 +156,7 @@ void InsetFormula::metrics() const
 
 vector<string> const InsetFormula::getLabelList() const
 {
-       return par_->getLabelList();
+       return mat()->getLabelList();
 }
 
 
@@ -187,9 +180,9 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                        //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);
                        }
@@ -202,9 +195,9 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                        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;
@@ -215,7 +208,7 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                        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()) {
@@ -236,13 +229,13 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
 
                        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;
@@ -260,7 +253,7 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                        int x;
                        int y;
                        mathcursor->getPos(x, y);
-                       par_->mutate(arg);
+                       mat()->mutate(arg);
                        mathcursor->setPos(x, y);
                        mathcursor->normalize();
                        updateLocal(bv, true);
@@ -272,10 +265,10 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                        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);
@@ -286,15 +279,15 @@ InsetFormula::localDispatch(BufferView * bv, kb_action action,
                {
                        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);
                }
@@ -312,33 +305,35 @@ void InsetFormula::handleExtern(const string & arg, BufferView *)
        //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();
 }
 
 
@@ -381,5 +376,5 @@ int InsetFormula::width(BufferView *, LyXFont const &) const
 
 MathInsetTypes InsetFormula::getType() const
 {
-       return par_->getType();
+       return mat()->getType();
 }
index bceefc0f334ea8b67298a3b2e9385015724b019d..501f1db2b10767f5075b4d24809b48253089cfa9 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "mathed/formulabase.h"
 #include "math_defs.h"
+#include "math_atom.h"
 
 class MathMatrixInset;
 
@@ -32,16 +33,10 @@ public:
        ///
        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;
@@ -80,17 +75,22 @@ public:
        ///
        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
index 4b3e34f50053ef3d29e0a80a7624a9ddb951f2e9..7d5f21c3a09256794ef140a2bb1e7bca9bea10b2 100644 (file)
@@ -123,19 +123,14 @@ string const InsetFormulaBase::editMessage() const
 
 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;
@@ -467,7 +462,6 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
        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;
@@ -477,6 +471,12 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
        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"));
@@ -513,7 +513,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
                //      p->incSpace();
                //else
                //      mathcursor->insert(new MathSpaceInset(1));
-               mathcursor->insert(new MathSpaceInset(1));
+               mathcursor->insert(MathAtom(new MathSpaceInset(1)));
                updateLocal(bv, true);
                break;
        }
@@ -539,7 +539,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
        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;
 
@@ -776,8 +776,7 @@ void mathDispatchGreek(BufferView * bv, string const & arg)
        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);
                }
        }
index 022b6352530dfa02ed7b4adad14ec6dd64de227d..f35889641ec9c380e16a349d305d92684f508e1f 100644 (file)
@@ -27,7 +27,7 @@
 
 class Buffer;
 class BufferView;
-class MathInset;
+class MathAtom;
 
 ///
 class InsetFormulaBase : public UpdatableInset {
@@ -85,10 +85,11 @@ public:
        ///
        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:
index cffb87b422402f68c96b943bf27e0e8a9dc626df..d98c7b05309aad3d324d927eccb5b3086a491e76 100644 (file)
@@ -52,16 +52,14 @@ InsetFormulaMacro::InsetFormulaMacro()
 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();
 }
 
@@ -75,20 +73,20 @@ Inset * InsetFormulaMacro::clone(Buffer const &, bool) const
 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;
 }
 
@@ -107,38 +105,34 @@ int InsetFormulaMacro::docbook(Buffer const * buf, ostream & os) const
 
 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();
 }
 
 
@@ -152,12 +146,12 @@ InsetFormulaMacro::localDispatch(BufferView * bv,
                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;
                }
                
@@ -168,33 +162,33 @@ InsetFormulaMacro::localDispatch(BufferView * bv,
 }
 
 
-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);
 }
 
 
@@ -222,9 +216,9 @@ void InsetFormulaMacro::draw(BufferView * bv, LyXFont const & f,
        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;
 }
 
index 44682779540246bdf843a25e66b2456ccb07c346..fdf37e37fabfe1ea33531e1a39da6a5554a2a597 100644 (file)
@@ -68,12 +68,12 @@ public:
        ///
        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;
 };
index b52d167f95c04c679c8bf24e837cc99f9c47db3f..ae9cfabbf491f82c744572b33616b1375b0565ba 100644 (file)
@@ -11,6 +11,11 @@ MathArrayInset::MathArrayInset(int m, int n)
 {}
 
 
+MathArrayInset::MathArrayInset(int m, int n, char valign, string const & halign)
+       : MathGridInset(m, n, valign, halign)
+{}
+
+
 MathInset * MathArrayInset::clone() const
 {
        return new MathArrayInset(*this);
index 45325c92ed051433c6915a21fc67310c5719b46d..ee7341d84372398a9f748445fa4d44a39d124c80 100644 (file)
@@ -14,13 +14,15 @@ public:
        ///
        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
index 0ab4f7737bbff8fe69e8914d9cb7566488f566df..8c1c6ed85cd10b42d61c31b8112ea187134f8902 100644 (file)
 #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)
@@ -74,73 +58,30 @@ MathAtom::~MathAtom()
 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)
 {
@@ -150,273 +91,3 @@ 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;
-}
index a97ad307bb15fbe93d807769424d06ee5d0a50ec..38c40469b0f575320208bcc9fea87b9c5a9bb2ee 100644 (file)
@@ -3,15 +3,10 @@
 #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.
@@ -22,13 +17,7 @@ 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: 
@@ -38,129 +27,23 @@ 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
index 5db7ff3c264dab1bd9328f5f2368729356a50fce..a89acb2933b2af9c044025b8e86a0880e5ac1ed5 100644 (file)
@@ -24,6 +24,7 @@
 #include <cctype>
 
 #include "support/lstrings.h"
+#include "support/LAssert.h"
 #include "debug.h"
 #include "LColor.h"
 #include "Painter.h"
@@ -58,24 +59,11 @@ struct Selection
                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]));
                }
@@ -87,20 +75,10 @@ struct Selection
                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();
                }
@@ -109,7 +87,8 @@ struct Selection
 
        void paste(MathCursor & cursor) const
        {
-               cursor.insert(glue());
+               MathArray ar = glue();
+               cursor.paste(ar);
        }
 
        // glues selection to one cell
@@ -136,8 +115,7 @@ Selection theSelection;
 #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
@@ -145,56 +123,63 @@ std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
 }
 
 
-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;
 }
@@ -202,17 +187,25 @@ bool MathCursor::popRight()
 
 
 #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";
@@ -242,36 +235,33 @@ void MathCursor::dump(char const *) const {}
 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())
@@ -280,58 +270,27 @@ MathInset * MathCursor::positionable(MathAtom * t, int x, int y) const
                //      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;
 }
@@ -348,9 +307,8 @@ bool MathCursor::left(bool sel)
        selHandle(sel);
        lastcode_ = LM_TC_VAR;
 
-       MathInset * p = prevInset();
-       if (openable(p, sel)) {
-               pushRight(p);
+       if (hasPrevAtom() && openable(prevAtom(), sel)) {
+               pushRight(prevAtom());
                return true;
        } 
        
@@ -369,9 +327,8 @@ bool MathCursor::right(bool sel)
        selHandle(sel);
        lastcode_ = LM_TC_VAR;
 
-       MathInset * p = nextInset();
-       if (openable(p, sel)) {
-               pushLeft(p);
+       if (hasNextAtom() && openable(nextAtom(), sel)) {
+               pushLeft(nextAtom());
                return true;
        }
 
@@ -382,7 +339,7 @@ bool MathCursor::right(bool sel)
 void MathCursor::first()
 {
        Cursor_.clear();
-       pushLeft(outerPar());
+       pushLeft(formula_->par());
 }
 
 
@@ -402,7 +359,7 @@ void MathCursor::setPos(int x, int y)
        lastcode_ = LM_TC_VAR;
        first();
 
-       cursor().par_  = outerPar();
+       cursor().par_  = &formula_->par();
 
        while (1) {
                idx() = 0;
@@ -414,7 +371,7 @@ void MathCursor::setPos(int x, int y)
                        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";
@@ -426,10 +383,10 @@ void MathCursor::setPos(int x, int y)
                }
                //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;
        }
@@ -467,25 +424,9 @@ void MathCursor::plainErase()
 }
 
 
-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();
 }
 
@@ -493,36 +434,30 @@ void MathCursor::plainInsert(MathInset * p)
 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
@@ -543,55 +478,35 @@ void MathCursor::insert(MathArray const & ar)
 }
 
 
-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();
 }
@@ -617,28 +532,15 @@ void MathCursor::erase()
                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();
@@ -665,18 +567,25 @@ bool MathCursor::up(bool sel)
        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();
@@ -689,18 +598,25 @@ bool MathCursor::down(bool sel)
        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();
@@ -709,7 +625,9 @@ bool MathCursor::down(bool sel)
 
 bool MathCursor::toggleLimits()
 {
-       MathAtom * t = prevAtom();
+       if (!hasPrevAtom())
+               return false;
+       MathScriptInset * t = prevAtom()->asScriptInset();
        if (!t)
                return false;
        int old = t->limits();
@@ -739,8 +657,8 @@ void MathCursor::macroModeClose()
 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;
@@ -751,7 +669,7 @@ string MathCursor::macroName() const
 {
        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;
 }
 
@@ -793,7 +711,8 @@ void MathCursor::selPaste()
 {
        seldump("selPaste");
        theSelection.paste(*this);
-       selClear();
+       theSelection.grab(*this);
+       //selClear();
 }
 
 
@@ -840,13 +759,14 @@ void MathCursor::drawSelection(Painter & pain) const
 
        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();
@@ -859,13 +779,6 @@ void MathCursor::drawSelection(Painter & pain) const
 }
 
 
-MathTextCodes MathCursor::nextCode() const
-{
-       //return (pos() == size()) ? LM_TC_VAR : nextInset()->code();
-       return LM_TC_VAR;
-}
-
-
 void MathCursor::handleFont(MathTextCodes t)
 {
        macroModeClose();
@@ -875,12 +788,8 @@ void MathCursor::handleFont(MathTextCodes t)
                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;
@@ -899,9 +808,8 @@ void MathCursor::handleNest(MathInset * p)
                selCut();
                p->cell(0) = theSelection.glue();
        }
-       insert(p); // this invalidates p!
-       p = prevAtom()->nucleus();      
-       pushRight(p);
+       insert(MathAtom(p)); // this invalidates p!
+       pushRight(prevAtom());
 }
 
 
@@ -910,14 +818,14 @@ void MathCursor::getPos(int & x, int & y)
 #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_;
 }
 
 
@@ -951,18 +859,6 @@ MathCursor::pos_type & MathCursor::pos()
 }
 
 
-bool MathCursor::inner() const
-{
-       return cursor().inner_;
-}
-
-
-bool & MathCursor::inner()
-{
-       return cursor().inner_;
-}
-
-
 bool MathCursor::inMacroMode() const
 {
        return macroNamePos() != -1;
@@ -978,9 +874,10 @@ bool MathCursor::selection() const
 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;
@@ -995,14 +892,11 @@ void MathCursor::pullArg(bool goright)
        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;
@@ -1064,64 +958,42 @@ MathCursor::row_type MathCursor::row() const
 }
 
 
-/*
-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());
 }
 
@@ -1129,10 +1001,6 @@ MathAtom * MathCursor::nextAtom()
 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";
@@ -1180,7 +1048,10 @@ void MathCursor::breakLine()
        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;
@@ -1259,7 +1130,7 @@ int MathCursor::cellYOffset() const
 
 int MathCursor::xpos() const
 {
-       return cellXOffset() + xarray().pos2x(pos(), inner());
+       return cellXOffset() + xarray().pos2x(pos());
 }
 
 
@@ -1283,7 +1154,8 @@ bool MathCursor::goUp()
                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
@@ -1296,8 +1168,9 @@ bool MathCursor::goUp()
        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;    
@@ -1314,7 +1187,8 @@ bool MathCursor::goDown()
                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
@@ -1327,8 +1201,9 @@ bool MathCursor::goDown()
        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;    
@@ -1350,13 +1225,6 @@ bool MathCursor::idxRight()
 }
 
 
-MathMatrixInset * MathCursor::outerPar() const
-{
-       return
-               static_cast<MathMatrixInset *>(const_cast<MathInset *>(formula_->par()));
-}
-
-
 void MathCursor::interpret(string const & s)
 {
        //lyxerr << "interpret 1: '" << s << "'\n";
@@ -1384,19 +1252,16 @@ void MathCursor::interpret(string const & s)
                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;
@@ -1448,17 +1313,24 @@ void MathCursor::interpret(char c)
        // 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;
        }
@@ -1494,7 +1366,7 @@ void MathCursor::interpret(char c)
        }
 
        if (strchr("#$%", c)) {
-               insert(new MathSpecialCharInset(c));    
+               insert(MathAtom(new MathSpecialCharInset(c)));  
                lastcode_ = LM_TC_VAR;
                return;
        }
@@ -1563,31 +1435,25 @@ bool operator<(MathCursorPos const & ti, MathCursorPos const & it)
 
 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_);
 }
 
 
@@ -1602,3 +1468,10 @@ MathCursorPos MathCursor::normalAnchor() const
        return normal;
 }
 
+
+MathSpaceInset * MathCursor::prevSpaceInset() const
+{
+       if (!hasPrevAtom())
+               return 0;
+       return prevAtom()->asSpaceInset();
+}
index d8d7a5b49bd636cf14de260a1f9d9c3b84addd12..f6e50b218a18aa5531db3ba10d998ff3069e1db0 100644 (file)
@@ -35,18 +35,17 @@ class InsetFormulaBase;
 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;
@@ -56,9 +55,6 @@ struct MathCursorPos {
        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;
 };
 
 /// 
@@ -82,12 +78,14 @@ public:
        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();
@@ -114,9 +112,9 @@ public:
        ///
        void plainErase();
        ///
-       void plainInsert(MathInset * p);
+       void plainInsert(MathAtom const &);
        ///
-       void niceInsert(MathInset * p);
+       void niceInsert(MathAtom const &);
 
        ///
        void delLine();
@@ -125,14 +123,12 @@ public:
        ///
        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;
@@ -202,11 +198,13 @@ public:
        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
@@ -217,13 +215,17 @@ public:
        ///
        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;
@@ -244,8 +246,6 @@ public:
        ///  
        pos_type last() const;
        ///
-       MathMatrixInset * outerPar() const;
-       ///
        void seldump(char const * str) const;
        ///
        void dump(char const * str) const;
@@ -253,13 +253,14 @@ public:
        ///
        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
@@ -274,8 +275,6 @@ private:
        bool goUp();
        /// moves position somehow down
        bool goDown();
-       /// glue adjacent atoms if possible
-       void glueAdjacentAtoms();
 
        ///
        string macroName() const;
@@ -284,11 +283,9 @@ private:
        ///
        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
index 7152b271594c89f392d7ba1f02eb76d6ce055b0c..4a6d21c336708dc8f6e0285e203b148b086e0d17 100644 (file)
 #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:
@@ -34,51 +34,51 @@ MathInset * createMathInset(latexkeys const * l)
        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));
 }
index 0123b5845cec8dc6125431b8cf4c7dd72afd51d9..56e0e916691b9dcc4f4112c69e8639c727451fb4 100644 (file)
@@ -2,11 +2,12 @@
 #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
index 6e7da5321399f29aa47e5481f6dc3dda691103f3..074b76fbfe3f400d9476f0d1f2075cb337d5b01f 100644 (file)
@@ -19,6 +19,9 @@ int const MATH_BORDER = 2;
 }
 
 
+////////////////////////////////////////////////////////////// 
+
+
 MathGridInset::RowInfo::RowInfo()
        : upperline_(false), lowerline_(false)
 {}
@@ -35,22 +38,33 @@ int MathGridInset::RowInfo::skipPixels() const
 
 
 
+////////////////////////////////////////////////////////////// 
+
+
 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;
@@ -59,6 +73,10 @@ MathInset::idx_type MathGridInset::index(row_type row, col_type col) const
 
 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);
@@ -268,7 +286,7 @@ string MathGridInset::eolString(row_type row) const
 
        // 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";
@@ -367,8 +385,9 @@ bool MathGridInset::idxUp(idx_type & idx, pos_type & pos) const
 {
        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;
 }
 
@@ -377,8 +396,9 @@ bool MathGridInset::idxDown(idx_type & idx, pos_type & pos) const
 {
        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;
 }
        
index 347441ee853831c5b17a15fa2e9fa90483c35c9f..b7fbd2f4d6d2c5ad50bb9f5b56f76d338fe25960 100644 (file)
@@ -62,6 +62,8 @@ public:
        /// 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;
@@ -87,8 +89,8 @@ public:
        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(); }
index d303aa2ca2b786015f2b1a1187d9eed587a16f97..9894c9ee732239118158f925717d7f1ce59bd838 100644 (file)
 
 
 class LaTeXFeatures;
+class MathArrayInset;
 class MathCharInset;
+class MathGridInset;
+class MathNestInset;
 class MathScriptInset;
+class MathMatrixInset;
+class MathSpaceInset;
+class MathMacroTemplate;
 
 class MathInset {
 public: 
@@ -166,26 +172,37 @@ 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; }
        ///
index 9dcf8a9aecca0fc0924507df3575e2d843546b95..7f6938b0263440b0bce68147a2966cb1bd53cf01 100644 (file)
 
 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_'!
 {}
 
 
@@ -51,7 +53,7 @@ MathInset * MathMacro::clone() const
 
 const char * MathMacro::name() const
 {
-       return tmplate_->name().c_str();
+       return tmplate_->asMacroTemplate()->name().c_str();
 }
 
 
@@ -139,11 +141,11 @@ void MathMacro::dump() const
        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();
index bfcfa94a2635078500459289475e27bdfe81c6d0..8cf2107f560eea439fac80e47d6dbd86d15e4962 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "math_nestinset.h"
 #include "math_macroarg.h"
+#include "LString.h"
 
 class MathMacroTemplate;
 
@@ -37,7 +38,7 @@ 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 &);
        ///
@@ -74,7 +75,7 @@ private:
        char const * name() const;
 
        ///
-       MathMacroTemplate const * const tmplate_;
+       MathAtom & tmplate_;
        ///
        mutable MathXArray expanded_;
 };
index 8f3e6383d377edd40bfdaf5c6a0e903e394ad02a..1e6902618a859d42125047ab9d8dc9540ca3fba7 100644 (file)
@@ -24,21 +24,14 @@ void MathMacroTable::dump()
        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();
        
@@ -53,25 +46,27 @@ MathMacroTemplate & MathMacroTable::provideTemplate(string const & name)
 }
 
 
-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();
 }
 
 
@@ -85,68 +80,68 @@ void MathMacroTable::builtinMacros()
        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)");
 }
index 2feaa00d5fe822126bb232342e926a9d82c6be9b..44f59c13576810346fca03c14855a52b861e7632 100644 (file)
@@ -4,34 +4,30 @@
 
 #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:
index 10ffb95ae4a44a7a64ca1055afb3d9727243207e..822d0e92114ee8e15c4f7d116168975f69ac644f 100644 (file)
@@ -24,7 +24,7 @@ MathMacroTemplate::MathMacroTemplate(string const & nm, int numargs)
 
 MathInset * MathMacroTemplate::clone() const
 {
-       lyxerr << "cloning MacroTemplate!\n";
+       //lyxerr << "cloning MacroTemplate!\n";
        return new MathMacroTemplate(*this);
 }
 
index 628a9bee68bfeb7bf5e879280262625d9703b837..aeefe5a2ce71746c685b0d57faf6d4a1febdc44b 100644 (file)
@@ -36,6 +36,8 @@ public:
        void draw(Painter &, int x, int y) const;
        ///
        void metrics(MathStyles st) const;
+       /// identifies macro templates
+       MathMacroTemplate * asMacroTemplate() { return this; }
 private:
        ///
        int numargs_;
index 6f0a9c09758e0b9599c62b8a0d9d27dc9fac26d7..bada6e475666015528c9eaf71a8275bff9c72f9d 100644 (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->nucleus()->isRelOp())
+               if ((*it)->isRelOp())
                        return it - array.begin();
        return array.size();
 }
index ffeeb60de12e4daf075f6e7c2c4a859ec0089b40..b90279af3bb0d9dad950a52b8f609dfe4401105a 100644 (file)
@@ -50,6 +50,10 @@ public:
        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);
index 54ef57e9b37c68f112d4bd1aad794f0f42033c95..5dccb4b5595670d1e2746dc1362ff1ec6c234c71 100644 (file)
@@ -148,10 +148,10 @@ void MathNestInset::dump() const
 }
 
 
-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";
 }
index b6156e0a3e91f3b0a445f7866423fda135e62227..5cf17786de0f11c708c2817b4efda77840831dc5 100644 (file)
@@ -24,6 +24,8 @@ public:
        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;
@@ -60,7 +62,7 @@ public:
        ///
        bool isActive() const { return nargs() > 0; }
        ///
-       void push_back(MathInset *);
+       void push_back(MathAtom const &);
        ///
        void dump() const;
 
index 4e2f0b63e1a57236042ae8b55813c9dadf8ed517..074ee0509b4b65be6ab2446fb87313b843a108f0 100644 (file)
@@ -62,6 +62,11 @@ bool stared(string const & s)
 }
 
 
+void add(MathArray & ar, char c, MathTextCodes code)
+{
+       ar.push_back(MathAtom(new MathCharInset(c, code)));
+}
+
 
 // These are TeX's catcodes
 enum CatCode {
@@ -199,9 +204,9 @@ public:
        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);
        ///
@@ -217,7 +222,7 @@ private:
        ///
        void error(string const & msg);
        ///
-       void parse_lines(MathGridInset * p, bool numbered, bool outmost);
+       bool parse_lines(MathAtom & t, bool numbered, bool outmost);
 
 private:
        ///
@@ -426,8 +431,14 @@ void Parser::error(string const & msg)
 }
 
 
-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
@@ -453,7 +464,11 @@ void Parser::parse_lines(MathGridInset * p, bool numbered, bool outmost)
                }
 
                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()) {
@@ -474,41 +489,46 @@ void Parser::parse_lines(MathGridInset * p, bool numbered, bool outmost)
        // 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();
@@ -516,14 +536,14 @@ MathMatrixInset * Parser::parse_normal()
        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();
@@ -531,7 +551,8 @@ MathMatrixInset * Parser::parse_normal()
        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_);
@@ -540,7 +561,7 @@ MathMatrixInset * Parser::parse_normal()
 
        if (cs != "begin") {
                lyxerr << "'begin' of un-simple math expected, got '" << cs << "'\n";
-               return 0;
+               return false;
        }
 
        string const name = getArg('{', '}');
@@ -548,60 +569,54 @@ MathMatrixInset * Parser::parse_normal()
        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;
 }
 
 
@@ -610,6 +625,7 @@ 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();
@@ -658,45 +674,52 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                        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
@@ -722,11 +745,11 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                        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;
@@ -737,13 +760,13 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                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);
                        }
                }
                
@@ -752,7 +775,7 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                        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);
                }
@@ -783,15 +806,12 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                        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";  
                }
@@ -811,7 +831,7 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                                if (isValidLength(s))
                                        break;
                        }
-                       array.push_back(new MathKernInset(s));
+                       array.push_back(MathAtom(new MathKernInset(s)));
                }
 
                else if (t.cs() == "label") {
@@ -825,11 +845,11 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                }
 
                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"
@@ -849,7 +869,7 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                                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()) {
@@ -867,7 +887,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->nucleus()->handleFont(t);
+                                               (*it)->handleFont(t);
                                        array.push_back(ar);
 
                                        // undo catcode changes
@@ -879,7 +899,7 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                                        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);
@@ -887,16 +907,10 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
                        }
 
                        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);
                        }
                }
 
@@ -917,6 +931,8 @@ void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
        }
 }
 
+
+
 } // anonymous namespace
 
 
@@ -932,20 +948,20 @@ MathArray mathed_parse_cell(string const & str)
 
 
 
-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();
@@ -953,21 +969,21 @@ MathMacroTemplate * mathed_parse_macro(LyXLex & lex)
 
 
 
-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);
 }
index 067d59b31368d856adc9fe1cf1d8dcc3c67a7115..cf06a946ceeed0beb536a291580cacaf57d8cd82 100644 (file)
@@ -28,6 +28,8 @@
 
 class MathMatrixInset;
 class MathMacroTemplate;
+class MathAtom;
+class MathArray;
 class LyXLex;
 
 ///
@@ -133,12 +135,12 @@ latexkeys const * in_word_set(string const & str);
 ///
 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
index 5e2cf7c7eaea9d4e149040ed8e205e2ce193e4f7..4760854461e16b54c97c023e0b39a413623f466d 100644 (file)
@@ -79,15 +79,17 @@ void MathRootInset::writeNormal(std::ostream & os) const
        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)
index 5fc4110ca4fbcc011318258a45e6f8fd90e7db54..305d22c86ad517fb9f2702a5be4e72934fe8269d 100644 (file)
@@ -1,6 +1,8 @@
 #include <config.h>
 #include "debug.h"
+#include "support.h"
 #include "support/LOstream.h"
+#include "support/LAssert.h"
 
 #ifdef __GNUG__
 #pragma implementation
@@ -9,9 +11,21 @@
 #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
@@ -25,27 +39,258 @@ MathScriptInset const * MathScriptInset::asScriptInset() 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];
 }
index 491d5a0e90cbad0c3a2dea8da5d2c2b31673814a..d4c5e62f40b72a70f87e0adf7abbe7f114ba5aef 100644 (file)
@@ -14,6 +14,8 @@
 
 class MathScriptInset : public MathNestInset {
 public:
+       ///
+       MathScriptInset();
        ///
        explicit MathScriptInset(bool up);
        ///
@@ -24,15 +26,75 @@ public:
        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
index b8afcb568bcd19d84f54ab8f08d7cda465d151ee..96b43441f969a35960a9533b31d242193280b369 100644 (file)
@@ -25,7 +25,9 @@ public:
        ///
        void metrics(MathStyles st) const;
        ///
-       bool isSpaceInset() const { return true; }
+       MathSpaceInset const * asSpaceInset() const { return this; }
+       ///
+       MathSpaceInset * asSpaceInset() { return this; }
        ///
        void incSpace();
 private:
index 2faafbed91926e30e881f093c22a8ef7f6e761f4..6f3ff8b3ca8fc9adb9ad93e9b3279027e777ba87 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "xarray.h"
 #include "math_inset.h"
+#include "math_scriptinset.h"
 #include "mathed/support.h"
 #include "math_defs.h"
 #include "Painter.h"
@@ -29,12 +30,21 @@ void MathXArray::metrics(MathStyles st) const
        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";
@@ -51,52 +61,60 @@ void MathXArray::draw(Painter & pain, int x, int y) const
                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();
 }
 
 
index ba5d073d7ca717a5a987965f4fb8b77b9bfeb7e3..8627f5e62ea8fffeacc3d3e9f8b8855040ff7417 100644 (file)
@@ -17,7 +17,9 @@ class MathXArray
 {
 public:
        ///
-       typedef MathArray::size_type    size_type;
+       typedef MathArray::size_type       size_type;
+       ///
+       typedef MathArray::const_iterator  const_iterator;
 
        ///
        MathXArray();
@@ -31,13 +33,9 @@ public:
        ///
        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_; }
@@ -49,8 +47,13 @@ public:
        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_;
        ///