]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/math_cursor.C
try to correct x position where curosr drops of inset.
[lyx.git] / src / mathed / math_cursor.C
index 77b4a35697818f30b349e962ee69bd4581e510c9..6a371a2a9b121baa0c54a7a1e87c38fa037328db 100644 (file)
 #include "frontends/Painter.h"
 #include "math_cursor.h"
 #include "formulabase.h"
+#include "funcrequest.h"
 #include "math_autocorrect.h"
 #include "math_arrayinset.h"
 #include "math_braceinset.h"
-#include "math_casesinset.h"
+#include "math_commentinset.h"
 #include "math_charinset.h"
 #include "math_extern.h"
 #include "math_factory.h"
@@ -80,7 +81,7 @@ MathCursor::~MathCursor()
   // ensure that 'notifyCursorLeave' is called
   while (popLeft())
     ;
-}   
+}
 
 
 void MathCursor::push(MathAtom & t)
@@ -91,7 +92,7 @@ void MathCursor::push(MathAtom & t)
 
 void MathCursor::pushLeft(MathAtom & t)
 {
-       //cerr << "Entering atom "; t->write(cerr, false); cerr << " left\n";
+       //lyxerr << "Entering atom " << t << " left\n";
        push(t);
        t->idxFirst(idx(), pos());
 }
@@ -99,7 +100,7 @@ void MathCursor::pushLeft(MathAtom & t)
 
 void MathCursor::pushRight(MathAtom & t)
 {
-       //cerr << "Entering atom "; t->write(cerr, false); cerr << " right\n";
+       //lyxerr << "Entering atom " << t << " right\n";
        posLeft();
        push(t);
        t->idxLast(idx(), pos());
@@ -170,20 +171,23 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const
        if (t->lock())
                return false;
 
-       if (t->asScriptInset())
-               return false;
-
        if (sel) {
                // we can't move into anything new during selection
                if (depth() == Anchor_.size())
                        return false;
-               if (t.nucleus() != Anchor_[depth()].par_)
+               if (t.operator->() != Anchor_[depth()].par_)
                        return false;
        }
        return true;
 }
 
 
+bool MathCursor::inNucleus() const
+{
+       return par()->asScriptInset() && idx() == 2;
+}
+
+
 bool MathCursor::posLeft()
 {
        if (pos() == 0)
@@ -281,10 +285,11 @@ void MathCursor::setPos(int x, int y)
                formula()->xlow(), formula()->xhigh(),
                formula()->ylow(), formula()->yhigh());
        if (!res) {
-               // this ccan happen on creation of "math-display"
+               // this can happen on creation of "math-display"
                dump("setPos 1.5");
                first();
        }
+       targetx_ = -1; // "no target"
        dump("setPos 2");
 }
 
@@ -299,6 +304,7 @@ bool MathCursor::home(bool sel)
        if (!par()->idxHome(idx(), pos()))
                return popLeft();
        dump("home 2");
+       targetx_ = -1; // "no target"
        return true;
 }
 
@@ -312,6 +318,7 @@ bool MathCursor::end(bool sel)
        if (!par()->idxEnd(idx(), pos()))
                return popRight();
        dump("end 2");
+       targetx_ = -1; // "no target"
        return true;
 }
 
@@ -405,33 +412,13 @@ void MathCursor::paste(MathArray const & ar)
 
 void MathCursor::paste(MathGridInset const & data)
 {
-       if (data.nargs() == 1) {
-               // single cell/part of cell
-               paste(data.cell(0));
-       } else {
-               // mulitple cells
-               idx_type idx; // index of upper left cell
-               MathGridInset * p = enclosingGrid(idx);
-               col_type const numcols = min(data.ncols(), p->ncols() - p->col(idx));
-               row_type const numrows = min(data.nrows(), p->nrows() - p->row(idx));
-               for (row_type row = 0; row < numrows; ++row) {
-                       for (col_type col = 0; col < numcols; ++col) {
-                               idx_type i = p->index(row + p->row(idx), col + p->col(idx));
-                               p->cell(i).push_back(data.cell(data.index(row, col)));
-                       }
-                       // append the left over horizontal cells to the last column
-                       idx_type i = p->index(row + p->row(idx), p->ncols() - 1);
-                       for (MathInset::col_type col = numcols; col < data.ncols(); ++col)
-                               p->cell(i).push_back(data.cell(data.index(row, col)));
-               }
-               // append the left over vertical cells to the last _cell_
-               idx_type i = p->nargs() - 1;
-               for (row_type row = numrows; row < data.nrows(); ++row)
-                       for (col_type col = 0; col < data.ncols(); ++col)
-                               p->cell(i).push_back(data.cell(data.index(row, col)));
-       }
+       ostringstream os;
+  WriteStream wi(os, false, false);
+  data.write(wi);
+       dispatch(FuncRequest(LFUN_PASTE, os.str()));
 }
 
+
 void MathCursor::backspace()
 {
        autocorrect_ = false;
@@ -445,14 +432,28 @@ void MathCursor::backspace()
                return;
        }
 
-       MathScriptInset * p = prevAtom()->asScriptInset();
-       if (p) {
-               p->removeScript(p->hasUp());
-               // Don't delete if there is anything left
-               if (p->hasUp() || p->hasDown())
+       if (inMacroMode()) {
+               MathUnknownInset * p = activeMacro();
+               if (p->name().size() > 1) {
+                       p->setName(p->name().substr(0, p->name().size() - 1));
                        return;
+               }
+       }
+
+/*
+       if (prevAtom()->asScriptInset()) {
+               // simply enter nucleus
+               left();
+               return;
        }
 
+       if (inNucleus()) {
+               // we are in nucleus
+               if (pos() == 1) {
+               }
+       }
+*/
+
        --pos();
        plainErase();
 }
@@ -480,39 +481,30 @@ void MathCursor::erase()
                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();
-}
-
-
-void MathCursor::delLine()
-{
-       autocorrect_ = false;
-       macroModeClose();
-
-       if (selection_) {
-               selDel();
+/*
+       // if we are standing in front of a script inset, grab item before us and
+       // move it into nucleus
+       // and remove first thing.
+       if (hasNextAtom() && nextAtom()->asScriptInset()) {
+               if (hasPrevAtom()) {
+                       MathAtom at = prevAtom();
+                       --pos();
+                       array().erase(pos());
+                       pushLeft(nextAtom());
+                       if (array().empty())
+                               array().push_back(at);
+                       else
+                               array()[0] = at;
+                       pos() = 1;
+               } else {
+                       pushLeft(nextAtom());
+                       array().clear();
+               }
                return;
        }
+*/
 
-       if (par()->nrows() > 1) {
-               // grid are the only things with more than one row...
-               lyx::Assert(par()->asGridInset());
-               par()->asGridInset()->delRow(hullRow());
-       }
-
-       if (idx() >= par()->nargs())
-               idx() = par()->nargs() - 1;
-
-       if (pos() > size())
-               pos() = size();
+       plainErase();
 }
 
 
@@ -546,11 +538,9 @@ bool MathCursor::down(bool sel)
 
 bool MathCursor::toggleLimits()
 {
-       if (!hasNextAtom())
-               return false;
-       MathScriptInset * t = nextAtom()->asScriptInset();
-       if (!t)
+       if (!hasNextAtom() || !nextAtom()->asScriptInset())
                return false;
+       MathScriptInset * t = nextAtom().nucleus()->asScriptInset();
        int old = t->limits();
        t->limits(old < 0 ? 1 : -1);
        return old != t->limits();
@@ -559,9 +549,9 @@ bool MathCursor::toggleLimits()
 
 void MathCursor::macroModeClose()
 {
-       MathUnknownInset * p = inMacroMode();
-       if (!p)
+       if (!inMacroMode())
                return;
+       MathUnknownInset * p = activeMacro();
        p->finalize();
        string s = p->name();
        --pos();
@@ -573,12 +563,13 @@ void MathCursor::macroModeClose()
 
 string MathCursor::macroName() const
 {
-       return inMacroMode() ? inMacroMode()->name() : string();
+       return inMacroMode() ? activeMacro()->name() : string();
 }
 
 
 void MathCursor::selClear()
 {
+       Anchor_.clear();
        selection_ = false;
 }
 
@@ -659,64 +650,42 @@ void MathCursor::selGet(MathArray & ar)
 }
 
 
-
-void MathCursor::drawSelection(MathPainterInfo & pain) const
+void MathCursor::drawSelection(MathPainterInfo & pi) const
 {
        if (!selection_)
                return;
-
        MathCursorPos i1;
        MathCursorPos i2;
        getSelection(i1, i2);
-
-       if (i1.idx_ == i2.idx_) {
-               MathXArray & c = i1.xcell();
-               int x1 = c.xo() + c.pos2x(i1.pos_);
-               int y1 = c.yo() - c.ascent();
-               int x2 = c.xo() + c.pos2x(i2.pos_);
-               int y2 = c.yo() + c.descent();
-               pain.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
-       } else {
-               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();
-                       int y1 = c.yo() - c.ascent();
-                       int x2 = c.xo() + c.width();
-                       int y2 = c.yo() + c.descent();
-                       pain.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
-               }
-       }
-
-#if 0
-       // draw anchor if different from selection boundary
-       MathCursorPos anc = Anchor_.back();
-       if (anc != i1 && anc != i2) {
-               MathXArray & c = anc.xcell();
-               int x  = c.xo() + c.pos2x(anc.pos_);
-               int y1 = c.yo() - c.ascent();
-               int y2 = c.yo() + c.descent();
-               pain.line(x, y1, x, y2, LColor::math);
-       }
-#endif
+       i1.par_->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
 }
 
 
-void MathCursor::handleNest(MathAtom const & at)
+void MathCursor::handleNest(MathAtom const & a)
 {
-       at->cell(0) = grabAndEraseSelection().glue();
+       MathAtom at = a;
+       at.nucleus()->cell(0) = grabAndEraseSelection().glue();
        insert(at);
        pushRight(prevAtom());
 }
 
 
-void MathCursor::getPos(int & x, int & y)
+void MathCursor::getPos(int & x, int & y) const
 {
        par()->getPos(idx(), pos(), x, y);
 }
 
 
+int MathCursor::targetX() const
+{
+       if (targetx_ != -1)
+               return targetx_;
+       int x = 0, y = 0;
+       getPos(x, y);
+       return x;
+}
+
+
 MathInset * MathCursor::par() const
 {
        return cursor().par_;
@@ -753,12 +722,24 @@ MathCursor::pos_type & MathCursor::pos()
 }
 
 
-MathUnknownInset * MathCursor::inMacroMode() const
+bool MathCursor::inMacroMode() const
 {
        if (!hasPrevAtom())
-               return 0;
-       MathUnknownInset * p = prevAtom()->asUnknownInset();
-       return (p && !p->final()) ? p : 0;
+               return false;
+       MathUnknownInset const * p = prevAtom()->asUnknownInset();
+       return p && !p->final();
+}
+
+
+MathUnknownInset * MathCursor::activeMacro()
+{
+       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : 0;
+}
+
+
+MathUnknownInset const * MathCursor::activeMacro() const
+{
+       return inMacroMode() ? prevAtom()->asUnknownInset() : 0;
 }
 
 
@@ -787,16 +768,10 @@ MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
 }
 
 
-MathHullInset * MathCursor::enclosingHull(MathCursor::idx_type & idx) const
+void MathCursor::popToHere(MathInset const * p)
 {
-       for (MathInset::difference_type i = depth() - 1; i >= 0; --i) {
-               MathHullInset * p = Cursor_[i].par_->asHullInset();
-               if (p) {
-                       idx = Cursor_[i].idx_;
-                       return p;
-               }
-       }
-       return 0;
+       while (depth() && Cursor_.back().par_ != p)
+               Cursor_.pop_back();
 }
 
 
@@ -818,20 +793,6 @@ void MathCursor::pullArg()
 {
        dump("pullarg");
        MathArray a = array();
-
-       MathScriptInset const * p = par()->asScriptInset();
-       if (p) {
-               // special handling for scripts
-               const bool up = p->hasUp();
-               popLeft();
-               MathScriptInset * q = nextAtom()->asScriptInset();
-               if (q)
-                       q->removeScript(up);
-               ++pos();
-               array().insert(pos(), a);
-               return;
-       }
-
        if (popLeft()) {
                plainErase();
                array().insert(pos(), a);
@@ -847,7 +808,7 @@ void MathCursor::touch()
        MathIterator::const_iterator it = Cursor_.begin();
        MathIterator::const_iterator et = Cursor_.end();
        for ( ; it != et; ++it)
-               it->xcell().touch();
+               it->cell().touch();
 }
 
 
@@ -855,7 +816,7 @@ void MathCursor::normalize()
 {
        if (idx() >= par()->nargs()) {
                lyxerr << "this should not really happen - 1: "
-                      << idx() << " " << par()->nargs() << "\n";
+                      << idx() << " " << par()->nargs() << " in: " << par() << "\n";
                dump("error 2");
        }
        idx() = min(idx(), par()->nargs() - 1);
@@ -874,7 +835,7 @@ void MathCursor::normalize()
        // remove empty scripts if possible
        if (1) {
                for (pos_type i = 0; i < size(); ++i) {
-                       MathScriptInset * p = array()[i]->asScriptInset();
+                       MathScriptInset * p = array()[i].nucleus()->asScriptInset();
                        if (p) {
                                p->removeEmptyScripts();
                                //if (p->empty())
@@ -894,22 +855,6 @@ MathCursor::size_type MathCursor::size() const
 }
 
 
-MathCursor::col_type MathCursor::hullCol() const
-{
-       idx_type idx = 0;
-       MathHullInset * p = enclosingHull(idx);
-       return p->col(idx);
-}
-
-
-MathCursor::row_type MathCursor::hullRow() const
-{
-       idx_type idx = 0;
-       MathHullInset * p = enclosingHull(idx);
-       return p->row(idx);
-}
-
-
 bool MathCursor::hasPrevAtom() const
 {
        return pos() > 0;
@@ -968,19 +913,6 @@ MathArray & MathCursor::array() const
 }
 
 
-MathXArray & MathCursor::xarray() const
-{
-       static MathXArray dummy;
-
-       if (depth() == 0) {
-               lyxerr << "############  depth() == 0 not valid\n";
-               return dummy;
-       }
-
-       return cursor().xcell();
-}
-
-
 void MathCursor::idxNext()
 {
        par()->idxNext(idx(), pos());
@@ -993,57 +925,6 @@ void MathCursor::idxPrev()
 }
 
 
-void MathCursor::splitCell()
-{
-       if (idx() + 1 == par()->nargs())
-               return;
-       MathArray ar = array();
-       ar.erase(0, pos());
-       array().erase(pos(), size());
-       ++idx();
-       pos() = 0;
-       array().insert(0, ar);
-}
-
-
-void MathCursor::breakLine()
-{
-       // leave inner cells
-       while (popRight())
-               ;
-
-       idx_type dummy;
-       MathHullInset * p = enclosingHull(dummy);
-       if (!p)
-               return;
-
-       if (p->getType() == "simple" || p->getType() == "equation") {
-               p->mutate("eqnarray");
-               idx() = 1;
-               pos() = 0;
-       } else {
-               p->addRow(hullRow());
-
-               // split line
-               const row_type r = hullRow();
-               for (col_type c = hullCol() + 1; c < p->ncols(); ++c)
-                       p->cell(p->index(r, c)).swap(p->cell(p->index(r + 1, c)));
-
-               // split cell
-               splitCell();
-               p->cell(idx()).swap(p->cell(idx() + p->ncols() - 1));
-       }
-}
-
-
-//void MathCursor::readLine(MathArray & ar) const
-//{
-//     idx_type base = row() * par()->ncols();
-//     for (idx_type off = 0; off < par()->ncols(); ++off)
-//             ar.push_back(par()->cell(base + off));
-//}
-
-
 char MathCursor::valign() const
 {
        idx_type idx;
@@ -1092,9 +973,8 @@ bool MathCursor::goUpDown(bool up)
        // Be warned: The 'logic' implemented in this function is highly fragile.
        // A distance of one pixel or a '<' vs '<=' _really_ matters.
        // So fiddle around with it only if you know what you are doing!
-       int xlow, xhigh, ylow, yhigh;
-
-  int xo, yo;
+  int xo = 0;
+       int yo = 0;
        getPos(xo, yo);
 
        // check if we had something else in mind, if not, this is the future goal
@@ -1106,7 +986,7 @@ bool MathCursor::goUpDown(bool up)
        // try neigbouring script insets
        // try left
        if (hasPrevAtom()) {
-               MathScriptInset * p = prevAtom()->asScriptInset();
+               MathScriptInset const * p = prevAtom()->asScriptInset();
                if (p && p->has(up)) {
                        --pos();
                        push(nextAtom());
@@ -1119,7 +999,7 @@ bool MathCursor::goUpDown(bool up)
 
        // try right
        if (hasNextAtom()) {
-               MathScriptInset * p = nextAtom()->asScriptInset();
+               MathScriptInset const * p = nextAtom()->asScriptInset();
                if (p && p->has(up)) {
                        push(nextAtom());
                        idx() = up;
@@ -1144,31 +1024,12 @@ bool MathCursor::goUpDown(bool up)
        while (1) {
                ///lyxerr << "updown: We are in " << *par() << " idx: " << idx() << '\n';
                // ask inset first
-               if (par()->idxUpDown(idx(), pos(), up)) {
-#ifdef WITH_WARNINGS
-#warning this code should be moved to individual insets that handle this
-#endif
-                       // position might have changed, so re-compute it
-                       getPos(xo, yo);
-                       // we found a cell that thinks it has something "below" us.
-                       //lyxerr << "updown: found inset that handles UpDown\n";
-                       xarray().boundingBox(xlow, xhigh, ylow, yhigh);
-                       // project (xo,yo) onto proper box
-                       //lyxerr << "\n   xo: " << xo << " yo: " << yo
-                       //       << "\n   xlow: " << xlow << " ylow: " << ylow
-                       //       << "\n   xhigh: " << xhigh << " yhigh: " << yhigh;
-                       xo = min(max(xo, xlow), xhigh);
-                       yo = min(max(yo, ylow), yhigh);
-                       //lyxerr << "\n   xo2: " << xo << " yo2: " << yo << "\n";
-                       bruteFind(xo, yo, xlow, xhigh, ylow, yhigh);
-                       //lyxerr << "updown: handled by final brute find\n";
+               if (par()->idxUpDown(idx(), pos(), up, targetx_))
                        return true;
-               }
 
-               // leave inset
-               if (!popLeft()) {
-                       // no such inset found, just take something "above"
-                       ///lyxerr << "updown: handled by strange case\n";
+               // no such inset found, just take something "above"
+               ///lyxerr << "updown: handled by strange case\n";
+               if (!popLeft())
                        return
                                bruteFind(xo, yo,
                                        formula()->xlow(),
@@ -1176,7 +1037,6 @@ bool MathCursor::goUpDown(bool up)
                                        up ? formula()->ylow() : yo + 4,
                                        up ? yo - 4 : formula()->yhigh()
                                );
-               }
 
                // any improvement so far?
                int xnew, ynew;
@@ -1222,14 +1082,6 @@ bool MathCursor::bruteFind
 }
 
 
-bool MathCursor::idxLineFirst()
-{
-       idx() -= idx() % par()->ncols();
-       pos() = 0;
-       return true;
-}
-
-
 bool MathCursor::idxLineLast()
 {
        idx() -= idx() % par()->ncols();
@@ -1260,15 +1112,6 @@ bool MathCursor::interpret(string const & s)
        //owner_->getIntl()->getTransManager().TranslateAndInsert(s[0], lt);
        //lyxerr << "trans: '" << s[0] << "'  int: " << int(s[0]) << endl;
 
-       if (s.size() >= 5 && s.substr(0, 5) == "cases") {
-               unsigned int n = 1;
-               istringstream is(s.substr(5).c_str());
-               is >> n;
-               n = max(1u, n);
-               niceInsert(MathAtom(new MathCasesInset(n)));
-               return true;
-       }
-
        if (s.size() >= 6 && s.substr(0, 6) == "matrix") {
                unsigned int m = 1;
                unsigned int n = 1;
@@ -1298,9 +1141,9 @@ bool MathCursor::interpret(string const & s)
        string name = s.substr(1);
 
        if (name == "over" || name == "choose" || name == "atop") {
-               MathArray ar = array();
                MathAtom t(createMathInset(name));
-               t->asNestInset()->cell(0).swap(array());
+               t.nucleus()->asNestInset()->cell(0) = array();
+               array().clear();
                pos() = 0;
                niceInsert(t);
                popRight();
@@ -1326,7 +1169,7 @@ bool MathCursor::script(bool up)
        // Hack to get \\^ and \\_ working
        if (inMacroMode() && macroName() == "\\") {
                if (up)
-                       interpret("\\mathcircumflex");
+                       niceInsert(createMathInset("mathcircumflex"));
                else
                        interpret('_');
                return true;
@@ -1334,19 +1177,25 @@ bool MathCursor::script(bool up)
 
        macroModeClose();
        MathGridInset safe = grabAndEraseSelection();
-       if (hasPrevAtom() && prevAtom()->asScriptInset()) {
-               prevAtom()->asScriptInset()->ensure(up);
+       if (inNucleus()) {
+               // we are in a nucleus of a script inset, move to _our_ script
+               par()->asScriptInset()->ensure(up);
+               idx() = up;
+               pos() = 0;
+       } else if (hasPrevAtom() && prevAtom()->asScriptInset()) {
+               prevAtom().nucleus()->asScriptInset()->ensure(up);
                pushRight(prevAtom());
                idx() = up;
                pos() = size();
-       } else if (hasNextAtom() && nextAtom()->asScriptInset()) {
-               nextAtom()->asScriptInset()->ensure(up);
+       } else if (hasPrevAtom()) {
+               --pos();
+               array()[pos()] = MathAtom(new MathScriptInset(nextAtom(), up));
                pushLeft(nextAtom());
                idx() = up;
                pos() = 0;
        } else {
                plainInsert(MathAtom(new MathScriptInset(up)));
-               prevAtom()->asScriptInset()->ensure(up);
+               prevAtom().nucleus()->asScriptInset()->ensure(up);
                pushRight(prevAtom());
                idx() = up;
                pos() = 0;
@@ -1365,7 +1214,7 @@ bool MathCursor::interpret(char c)
                --pos();
                plainErase();
                int n = c - '0';
-               MathMacroTemplate * p = formula()->par()->asMacroTemplate();
+               MathMacroTemplate const * p = formula()->par()->asMacroTemplate();
                if (p && 1 <= n && n <= p->numargs())
                        insert(MathAtom(new MathMacroArgument(c - '0')));
                else {
@@ -1380,14 +1229,8 @@ bool MathCursor::interpret(char c)
                string name = macroName();
                //lyxerr << "interpret name: '" << name << "'\n";
 
-               if (name.empty() && c == '\\') {
-                       backspace();
-                       interpret("\\backslash");
-                       return true;
-               }
-
                if (isalpha(c)) {
-                       inMacroMode()->name() += c;
+                       activeMacro()->setName(activeMacro()->name() + c);
                        return true;
                }
 
@@ -1395,10 +1238,13 @@ bool MathCursor::interpret(char c)
                if (name == "\\") {
                        // remove the '\\'
                        backspace();
-                       if (c == '\\')
-                               interpret("\\backslash");
-                       else
-                               interpret(string("\\") + c);
+                       if (c == '\\') {
+                               if (currentMode() == MathInset::TEXT_MODE)
+                                       niceInsert(createMathInset("textbackslash"));
+                               else
+                                       niceInsert(createMathInset("backslash"));
+                       } else
+                               niceInsert(createMathInset(string(1, c)));
                        return true;
                }
 
@@ -1434,6 +1280,12 @@ bool MathCursor::interpret(char c)
                return true;
        }
 
+       if (c == '\n') {
+               if (currentMode() == MathInset::TEXT_MODE) 
+                       insert(c);
+               return true;
+       }
+
        if (c == ' ') {
                if (currentMode() == MathInset::TEXT_MODE) {
                        // insert spaces in text mode,
@@ -1445,7 +1297,7 @@ bool MathCursor::interpret(char c)
                        return true;
                }
                if (hasPrevAtom() && prevAtom()->asSpaceInset()) {
-                       prevAtom()->asSpaceInset()->incSpace();
+                       prevAtom().nucleus()->asSpaceInset()->incSpace();
                        return true;
                }
                if (popRight())
@@ -1481,7 +1333,7 @@ bool MathCursor::interpret(char c)
        }
 
        if (c == '%') {
-               insert(createMathInset("%"));
+               niceInsert(MathAtom(new MathCommentInset));
                return true;
        }
 
@@ -1527,11 +1379,11 @@ void MathCursor::setSelection(MathIterator const & where, size_type n)
 void MathCursor::insetToggle()
 {
        if (hasNextAtom()) {
-               // toggle next inset ...
-               nextAtom()->lock(!nextAtom()->lock());
+               // toggle previous inset ...
+               nextAtom().nucleus()->lock(!nextAtom()->lock());
        } else if (popLeft() && hasNextAtom()) {
                // ... or enclosing inset if we are in the last inset position
-               nextAtom()->lock(!nextAtom()->lock());
+               nextAtom().nucleus()->lock(!nextAtom()->lock());
                posRight();
        }
 }
@@ -1591,7 +1443,8 @@ MathGridInset MathCursor::grabSelection() const
        // shouldn't we assert on i1.par_ == i2.par_?
        if (i1.idx_ == i2.idx_) {
                MathGridInset data(1, 1);
-               data.cell(0) = MathArray(i1.cell(), i1.pos_, i2.pos_);
+               MathArray::const_iterator it = i1.cell().begin();
+               data.cell(0) = MathArray(it + i1.pos_, it + i2.pos_);
                return data;
        }
        row_type r1, r2;
@@ -1621,7 +1474,7 @@ void MathCursor::eraseSelection()
                region(i1, i2, r1, r2, c1, c2);
                for (row_type row = r1; row <= r2; ++row)
                        for (col_type col = c1; col <= c2; ++col)
-                               p->cell(p->index(row, col)).erase();
+                               p->cell(p->index(row, col)).clear();
        }
        cursor() = i1;
 }
@@ -1655,97 +1508,36 @@ MathCursorPos MathCursor::normalAnchor() const
 }
 
 
-
-void MathCursor::handleExtern(const string & arg)
-{
-       string lang;
-       string extra;
-       istringstream iss(arg.c_str());
-       iss >> lang >> extra;
-       if (extra.empty())
-               extra = "noextra";
-
-
-       if (selection()) {
-               MathArray ar;
-               selGet(ar);
-               lyxerr << "use selection: " << ar << "\n";
-               insert(pipeThroughExtern(lang, extra, ar));
-               return;
-       }
-
-       MathArray eq;
-       eq.push_back(MathAtom(new MathCharInset('=')));
-
-       popToEnclosingHull();
-
-       idx_type idx = 0;
-       MathHullInset * hull = enclosingHull(idx);
-       lyx::Assert(hull);
-       idxLineFirst();
-
-       if (hull->getType() == "simple") {
-               MathArray::size_type pos = cursor().cell().find_last(eq);
-               MathArray ar;
-               if (pos == size()) {
-                       ar = array();
-                       lyxerr << "use whole cell: " << ar << "\n";
-               } else {
-                       ar = MathArray(array(), pos + 1, size());
-                       lyxerr << "use partial cell form pos: " << pos << "\n";
-               }
-               end();
-               insert(eq);
-               insert(pipeThroughExtern(lang, extra, ar));
-               return;
-       }
-
-       if (hull->getType() == "equation") {
-               lyxerr << "use equation inset\n";
-               hull->mutate("eqnarray");
-               MathArray & ar = cursor().cell();
-               lyxerr << "use cell: " << ar << "\n";
-               idxRight();
-               cursor().cell() = eq;
-               idxRight();
-               cursor().cell() = pipeThroughExtern(lang, extra, ar);
-               idxLineLast();
-               return;
-       }
-
-       {
-               lyxerr << "use eqnarray\n";
-               idxLineLast();
-               MathArray ar = cursor().cell();
-               lyxerr << "use cell: " << ar << "\n";
-               breakLine();
-               idxRight();
-               cursor().cell() = eq;
-               idxRight();
-               cursor().cell() = pipeThroughExtern(lang, extra, ar);
-               idxLineLast();
-       }
-
-}
-
-
-int MathCursor::dispatch(string const & cmd)
+MathInset::result_type MathCursor::dispatch(FuncRequest const & cmd)
 {
        // try to dispatch to adajcent items if they are not editable
        // actually, this should only happen for mouse clicks...
-       if (hasNextAtom() && !openable(nextAtom(), false))
-               if (int res = nextAtom()->dispatch(cmd, 0, 0))
+       idx_type d1;
+       pos_type d2;
+       if (hasNextAtom() && !openable(nextAtom(), false)) {
+               MathInset::result_type res = nextAtom().nucleus()->dispatch(cmd, d1, d2);
+               if (res != MathInset::UNDISPATCHED)
                        return res;
-       if (hasPrevAtom() && !openable(prevAtom(), false))
-               if (int res = prevAtom()->dispatch(cmd, 0, 0))
+       }
+       if (hasPrevAtom() && !openable(prevAtom(), false)) {
+               MathInset::result_type res = prevAtom().nucleus()->dispatch(cmd, d1, d2);
+               if (res != MathInset::UNDISPATCHED)
                        return res;
+       }
 
        for (int i = Cursor_.size() - 1; i >= 0; --i) {
                MathCursorPos & pos = Cursor_[i];
-               if (int res = pos.par_->dispatch(cmd, pos.idx_, pos.pos_))
+               MathInset::result_type const res
+                       = pos.par_->dispatch(cmd, pos.idx_, pos.pos_);
+               if (res != MathInset::UNDISPATCHED) {
+                       if (res == MathInset::DISPATCHED_POP) {
+                               Cursor_.shrink(i + 1);
+                               selClear();
+                       }
                        return res;
+               }
        }
-       return 0;
+       return MathInset::UNDISPATCHED;
 }