]> git.lyx.org Git - features.git/blobdiff - src/mathed/math_cursor.C
Replace LString.h with support/std_string.h,
[features.git] / src / mathed / math_cursor.C
index 5e89cc4b87dcac47d4ef45afeda15ffc1a9f23eb..96fdc1c7d9c7bd956f292ff63797cb143159b7d3 100644 (file)
@@ -1,40 +1,30 @@
-/*
- *  File:        math_cursor.C
- *  Purpose:     Interaction for mathed
- *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
- *  Created:     January 1996
- *  Description: Math interaction for a WYSIWYG math editor.
+/**
+ * \file math_cursor.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
  *
- *  Dependencies: Xlib, XForms
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
  *
- *  Copyright: 1996, Alejandro Aguilar Sierra
- *
- *   Version: 0.8beta, Math & Lyx project.
- *
- *   You are free to use and modify this code under the terms of
- *   the GNU General Public Licence version 2 or later.
+ * Full author contact details are available in file CREDITS.
  */
 
 #include <config.h>
-#include <lyxrc.h>
 
+#include <lyxrc.h>
 
-#include "support/lstrings.h"
 #include "support/LAssert.h"
+#include "support/limited_stack.h"
 #include "debug.h"
-#include "frontends/Painter.h"
+#include "support/std_sstream.h"
 #include "math_cursor.h"
 #include "formulabase.h"
 #include "funcrequest.h"
-#include "math_autocorrect.h"
 #include "math_braceinset.h"
 #include "math_commentinset.h"
 #include "math_charinset.h"
-#include "math_extern.h"
 #include "math_factory.h"
-#include "math_fontinset.h"
 #include "math_gridinset.h"
-#include "math_iterator.h"
 #include "math_macroarg.h"
 #include "math_macrotemplate.h"
 #include "math_mathmlstream.h"
 #include "math_support.h"
 #include "math_unknowninset.h"
 
-#include <algorithm>
-#include <cctype>
 
 //#define FILEDEBUG 1
 
+using namespace lyx::support;
+
 using std::endl;
 using std::min;
 using std::max;
@@ -58,7 +48,7 @@ using std::isalpha;
 
 
 // matheds own cut buffer
-string theCutBuffer;
+limited_stack<string> theCutBuffer;
 
 
 MathCursor::MathCursor(InsetFormulaBase * formula, bool front)
@@ -79,13 +69,13 @@ MathCursor::~MathCursor()
 
 void MathCursor::push(MathAtom & t)
 {
-       Cursor_.push_back(MathCursorPos(t.nucleus()));
+       Cursor_.push_back(CursorPos(t.nucleus()));
 }
 
 
 void MathCursor::pushLeft(MathAtom & t)
 {
-       //lyxerr << "Entering atom " << t << " left\n";
+       //lyxerr << "Entering atom " << t << " left" << endl;
        push(t);
        t->idxFirst(idx(), pos());
 }
@@ -93,7 +83,7 @@ void MathCursor::pushLeft(MathAtom & t)
 
 void MathCursor::pushRight(MathAtom & t)
 {
-       //lyxerr << "Entering atom " << t << " right\n";
+       //lyxerr << "Entering atom " << t << " right" << endl;
        posLeft();
        push(t);
        t->idxLast(idx(), pos());
@@ -102,13 +92,13 @@ void MathCursor::pushRight(MathAtom & t)
 
 bool MathCursor::popLeft()
 {
-       //cerr << "Leaving atom to the left\n";
+       //lyxerr << "Leaving atom to the left" << endl;
        if (depth() <= 1) {
                if (depth() == 1)
-                       par()->notifyCursorLeaves(idx());
+                       inset()->notifyCursorLeaves(idx());
                return false;
        }
-       par()->notifyCursorLeaves(idx());
+       inset()->notifyCursorLeaves(idx());
        Cursor_.pop_back();
        return true;
 }
@@ -116,13 +106,13 @@ bool MathCursor::popLeft()
 
 bool MathCursor::popRight()
 {
-       //cerr << "Leaving atom "; par()->write(cerr, false); cerr << " right\n";
+       //lyxerr << "Leaving atom "; inset()->write(cerr, false); cerr << " right" << endl;
        if (depth() <= 1) {
                if (depth() == 1)
-                       par()->notifyCursorLeaves(idx());
+                       inset()->notifyCursorLeaves(idx());
                return false;
        }
-       par()->notifyCursorLeaves(idx());
+       inset()->notifyCursorLeaves(idx());
        Cursor_.pop_back();
        posRight();
        return true;
@@ -150,7 +140,7 @@ bool MathCursor::popRight()
 bool MathCursor::isInside(MathInset const * p) const
 {
        for (unsigned i = 0; i < depth(); ++i)
-               if (Cursor_[i].par_ == p)
+               if (Cursor_[i].inset_ == p)
                        return true;
        return false;
 }
@@ -168,7 +158,7 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const
                // we can't move into anything new during selection
                if (depth() == Anchor_.size())
                        return false;
-               if (t.operator->() != Anchor_[depth()].par_)
+               if (t.operator->() != Anchor_[depth()].inset_)
                        return false;
        }
        return true;
@@ -177,7 +167,7 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const
 
 bool MathCursor::inNucleus() const
 {
-       return par()->asScriptInset() && idx() == 2;
+       return inset()->asScriptInset() && idx() == 2;
 }
 
 
@@ -243,7 +233,7 @@ void MathCursor::first()
 {
        Cursor_.clear();
        push(formula_->par());
-       par()->idxFirst(idx(), pos());
+       inset()->idxFirst(idx(), pos());
 }
 
 
@@ -251,7 +241,7 @@ void MathCursor::last()
 {
        Cursor_.clear();
        push(formula_->par());
-       par()->idxLast(idx(), pos());
+       inset()->idxLast(idx(), pos());
 }
 
 
@@ -264,7 +254,7 @@ bool positionable
 
        // anchor might be deeper, should have same path then
        for (MathIterator::size_type i = 0; i < cursor.size(); ++i)
-               if (cursor[i].par_ != anchor[i].par_)
+               if (cursor[i].inset_ != anchor[i].inset_)
                        return false;
 
        // position should be ok.
@@ -295,7 +285,7 @@ bool MathCursor::home(bool sel)
        autocorrect_ = false;
        selHandle(sel);
        macroModeClose();
-       if (!par()->idxHome(idx(), pos()))
+       if (!inset()->idxHome(idx(), pos()))
                return popLeft();
        dump("home 2");
        targetx_ = -1; // "no target"
@@ -309,7 +299,7 @@ bool MathCursor::end(bool sel)
        autocorrect_ = false;
        selHandle(sel);
        macroModeClose();
-       if (!par()->idxEnd(idx(), pos()))
+       if (!inset()->idxEnd(idx(), pos()))
                return popRight();
        dump("end 2");
        targetx_ = -1; // "no target"
@@ -325,14 +315,14 @@ void MathCursor::plainErase()
 
 void MathCursor::markInsert()
 {
-       //lyxerr << "inserting mark\n";
+       //lyxerr << "inserting mark" << endl;
        array().insert(pos(), MathAtom(new MathCharInset(0)));
 }
 
 
 void MathCursor::markErase()
 {
-       //lyxerr << "deleting mark\n";
+       //lyxerr << "deleting mark" << endl;
        array().erase(pos());
 }
 
@@ -345,9 +335,17 @@ void MathCursor::plainInsert(MathAtom const & t)
 }
 
 
+void MathCursor::insert2(string const & str)
+{
+       MathArray ar;
+       asArray(str, ar);
+       insert(ar);
+}
+
+
 void MathCursor::insert(string const & str)
 {
-       //lyxerr << "inserting '" << str << "'\n";
+       //lyxerr << "inserting '" << str << "'" << endl;
        selClearOrDel();
        for (string::const_iterator it = str.begin(); it != str.end(); ++it)
                plainInsert(MathAtom(new MathCharInset(*it)));
@@ -356,7 +354,7 @@ void MathCursor::insert(string const & str)
 
 void MathCursor::insert(char c)
 {
-       //lyxerr << "inserting '" << c << "'\n";
+       //lyxerr << "inserting '" << c << "'" << endl;
        selClearOrDel();
        plainInsert(MathAtom(new MathCharInset(c)));
 }
@@ -372,7 +370,8 @@ void MathCursor::insert(MathAtom const & t)
 
 void MathCursor::niceInsert(string const & t)
 {
-       MathArray ar = asArray(t);
+       MathArray ar;
+       asArray(t, ar);
        if (ar.size() == 1)
                niceInsert(ar[0]);
        else
@@ -420,12 +419,13 @@ bool MathCursor::backspace()
        }
 
        if (pos() == 0) {
-               if (par()->ncols() == 1 && par()->nrows() == 1 && depth() == 1 && size() == 0)
+               if (inset()->ncols() == 1 &&
+                         inset()->nrows() == 1 &&
+                         depth() == 1 &&
+                         size() == 0)
                        return false;
-               else{
-                       pullArg();
-                       return true;
-               }
+               pullArg();
+               return true;
        }
 
        if (inMacroMode()) {
@@ -438,7 +438,7 @@ bool MathCursor::backspace()
 
        --pos();
        plainErase();
-        return true;
+       return true;
 }
 
 
@@ -455,15 +455,15 @@ bool MathCursor::erase()
 
        // delete empty cells if possible
        if (array().empty())
-               if (par()->idxDelete(idx()))
+               if (inset()->idxDelete(idx()))
                        return true;
 
        // old behaviour when in last position of cell
        if (pos() == size()) {
-               if (par()->ncols() == 1 && par()->nrows() == 1 && depth() == 1 && size() == 0)
+               if (inset()->ncols() == 1 && inset()->nrows() == 1 && depth() == 1 && size() == 0)
                        return false;
                else{
-                       par()->idxGlue(idx());
+                       inset()->idxGlue(idx());
                        return true;
                }
        }
@@ -515,12 +515,12 @@ void MathCursor::macroModeClose()
        if (s == "\\")
                return;
 
-       string name = s.substr(1);
+       string const name = s.substr(1);
 
        // prevent entering of recursive macros
-       if (formula()->lyxCode() == Inset::MATHMACRO_CODE
+       if (formula()->lyxCode() == InsetOld::MATHMACRO_CODE
                        && formula()->getInsetName() == name)
-               lyxerr << "can't enter recursive macro\n";
+               lyxerr << "can't enter recursive macro" << endl;
 
        niceInsert(createMathInset(name));
 }
@@ -543,10 +543,10 @@ void MathCursor::selCopy()
 {
        dump("selCopy");
        if (selection_) {
-               theCutBuffer = grabSelection();
+               theCutBuffer.push(grabSelection());
                selection_ = false;
        } else {
-               theCutBuffer.erase();
+               //theCutBuffer.erase();
        }
 }
 
@@ -554,7 +554,7 @@ void MathCursor::selCopy()
 void MathCursor::selCut()
 {
        dump("selCut");
-       theCutBuffer = grabAndEraseSelection();
+       theCutBuffer.push(grabAndEraseSelection());
 }
 
 
@@ -568,11 +568,12 @@ void MathCursor::selDel()
 }
 
 
-void MathCursor::selPaste()
+void MathCursor::selPaste(size_t n)
 {
        dump("selPaste");
        selClearOrDel();
-       paste(theCutBuffer);
+       if (n < theCutBuffer.size())
+               paste(theCutBuffer[n]);
        //grabSelection();
        selection_ = false;
 }
@@ -607,21 +608,21 @@ void MathCursor::selClearOrDel()
 }
 
 
-void MathCursor::drawSelection(MathPainterInfo & pi) const
+void MathCursor::drawSelection(PainterInfo & pi) const
 {
        if (!selection_)
                return;
-       MathCursorPos i1;
-       MathCursorPos i2;
+       CursorPos i1;
+       CursorPos i2;
        getSelection(i1, i2);
-       i1.par_->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
+       i1.inset_->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
 }
 
 
 void MathCursor::handleNest(MathAtom const & a)
 {
        MathAtom at = a;
-       at.nucleus()->cell(0) = asArray(grabAndEraseSelection());
+       asArray(grabAndEraseSelection(), at.nucleus()->cell(0));
        insert(at);
        pushRight(prevAtom());
 }
@@ -629,7 +630,7 @@ void MathCursor::handleNest(MathAtom const & a)
 
 void MathCursor::getPos(int & x, int & y) const
 {
-       par()->getPos(idx(), pos(), x, y);
+       inset()->getPos(idx(), pos(), x, y);
 }
 
 
@@ -643,9 +644,9 @@ int MathCursor::targetX() const
 }
 
 
-MathInset * MathCursor::par() const
+MathInset * MathCursor::inset() const
 {
-       return cursor().par_;
+       return cursor().inset_;
 }
 
 
@@ -727,7 +728,7 @@ bool MathCursor::selection() const
 MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
 {
        for (MathInset::difference_type i = depth() - 1; i >= 0; --i) {
-               MathGridInset * p = Cursor_[i].par_->asGridInset();
+               MathGridInset * p = Cursor_[i].inset_->asGridInset();
                if (p) {
                        idx = Cursor_[i].idx_;
                        return p;
@@ -739,21 +740,21 @@ MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
 
 void MathCursor::popToHere(MathInset const * p)
 {
-       while (depth() && Cursor_.back().par_ != p)
+       while (depth() && Cursor_.back().inset_ != p)
                Cursor_.pop_back();
 }
 
 
 void MathCursor::popToEnclosingGrid()
 {
-       while (depth() && !Cursor_.back().par_->asGridInset())
+       while (depth() && !Cursor_.back().inset_->asGridInset())
                Cursor_.pop_back();
 }
 
 
 void MathCursor::popToEnclosingHull()
 {
-       while (depth() && !Cursor_.back().par_->asHullInset())
+       while (depth() && !Cursor_.back().inset_->asHullInset())
                Cursor_.pop_back();
 }
 
@@ -783,20 +784,20 @@ void MathCursor::touch()
 
 void MathCursor::normalize()
 {
-       if (idx() >= par()->nargs()) {
+       if (idx() >= inset()->nargs()) {
                lyxerr << "this should not really happen - 1: "
-                      << idx() << ' ' << par()->nargs()
-                      << " in: " << par() << endl;
+                      << idx() << ' ' << inset()->nargs()
+                      << " in: " << inset() << endl;
                dump("error 2");
        }
-       idx() = min(idx(), par()->nargs() - 1);
+       idx() = min(idx(), inset()->nargs() - 1);
 
        if (pos() > size()) {
                lyxerr << "this should not really happen - 2: "
                        << pos() << ' ' << size() <<  " in idx: " << idx()
                       << " in atom: '";
                WriteStream wi(lyxerr, false, true);
-               par()->write(wi);
+               inset()->write(wi);
                lyxerr << endl;
                dump("error 4");
        }
@@ -824,28 +825,28 @@ bool MathCursor::hasNextAtom() const
 
 MathAtom const & MathCursor::prevAtom() const
 {
-       lyx::Assert(pos() > 0);
+       Assert(pos() > 0);
        return array()[pos() - 1];
 }
 
 
 MathAtom & MathCursor::prevAtom()
 {
-       lyx::Assert(pos() > 0);
+       Assert(pos() > 0);
        return array()[pos() - 1];
 }
 
 
 MathAtom const & MathCursor::nextAtom() const
 {
-       lyx::Assert(pos() < size());
+       Assert(pos() < size());
        return array()[pos()];
 }
 
 
 MathAtom & MathCursor::nextAtom()
 {
-       lyx::Assert(pos() < size());
+       Assert(pos() < size());
        return array()[pos()];
 }
 
@@ -854,13 +855,13 @@ MathArray & MathCursor::array() const
 {
        static MathArray dummy;
 
-       if (idx() >= par()->nargs()) {
-               lyxerr << "############  idx_ " << idx() << " not valid\n";
+       if (idx() >= inset()->nargs()) {
+               lyxerr << "############  idx_ " << idx() << " not valid" << endl;
                return dummy;
        }
 
        if (depth() == 0) {
-               lyxerr << "############  depth() == 0 not valid\n";
+               lyxerr << "############  depth() == 0 not valid" << endl;
                return dummy;
        }
 
@@ -870,13 +871,13 @@ MathArray & MathCursor::array() const
 
 void MathCursor::idxNext()
 {
-       par()->idxNext(idx(), pos());
+       inset()->idxNext(idx(), pos());
 }
 
 
 void MathCursor::idxPrev()
 {
-       par()->idxPrev(idx(), pos());
+       inset()->idxPrev(idx(), pos());
 }
 
 
@@ -896,9 +897,9 @@ char MathCursor::halign() const
 }
 
 
-void MathCursor::getSelection(MathCursorPos & i1, MathCursorPos & i2) const
+void MathCursor::getSelection(CursorPos & i1, CursorPos & i2) const
 {
-       MathCursorPos anc = normalAnchor();
+       CursorPos anc = normalAnchor();
        if (anc < cursor()) {
                i1 = anc;
                i2 = cursor();
@@ -909,16 +910,16 @@ void MathCursor::getSelection(MathCursorPos & i1, MathCursorPos & i2) const
 }
 
 
-MathCursorPos & MathCursor::cursor()
+CursorPos & MathCursor::cursor()
 {
-       lyx::Assert(depth());
+       Assert(depth());
        return Cursor_.back();
 }
 
 
-MathCursorPos const & MathCursor::cursor() const
+CursorPos const & MathCursor::cursor() const
 {
-       lyx::Assert(depth());
+       Assert(depth());
        return Cursor_.back();
 }
 
@@ -947,7 +948,7 @@ bool MathCursor::goUpDown(bool up)
                        push(nextAtom());
                        idx() = up; // the superscript has index 1
                        pos() = size();
-                       ///lyxerr << "updown: handled by scriptinset to the left\n";
+                       ///lyxerr << "updown: handled by scriptinset to the left" << endl;
                        return true;
                }
        }
@@ -959,27 +960,30 @@ bool MathCursor::goUpDown(bool up)
                        push(nextAtom());
                        idx() = up;
                        pos() = 0;
-                       ///lyxerr << "updown: handled by scriptinset to the right\n";
+                       ///lyxerr << "updown: handled by scriptinset to the right" << endl;
                        return true;
                }
        }
 
-       // try current cell
+       // try current cell for e.g. text insets
+       if (inset()->idxUpDown2(idx(), pos(), up, targetx_))
+               return true;
+
        //xarray().boundingBox(xlow, xhigh, ylow, yhigh);
        //if (up)
        //      yhigh = yo - 4;
        //else
        //      ylow = yo + 4;
        //if (bruteFind(xo, yo, xlow, xhigh, ylow, yhigh)) {
-       //      lyxerr << "updown: handled by brute find in the same cell\n";
+       //      lyxerr << "updown: handled by brute find in the same cell" << endl;
        //      return true;
        //}
 
        // try to find an inset that knows better then we
        while (1) {
-               ///lyxerr << "updown: We are in " << *par() << " idx: " << idx() << '\n';
+               ///lyxerr << "updown: We are in " << *inset() << " idx: " << idx() << endl;
                // ask inset first
-               if (par()->idxUpDown(idx(), pos(), up, targetx_)) {
+               if (inset()->idxUpDown(idx(), pos(), up, targetx_)) {
                        // try to find best position within this inset
                        if (!selection())
                                bruteFind2(xo, yo);
@@ -987,7 +991,7 @@ bool MathCursor::goUpDown(bool up)
                }
 
                // no such inset found, just take something "above"
-               ///lyxerr << "updown: handled by strange case\n";
+               ///lyxerr << "updown: handled by strange case" << endl;
                if (!popLeft())
                        return
                                bruteFind(xo, yo,
@@ -1021,6 +1025,7 @@ bool MathCursor::bruteFind
                        it.back().getPos(xo, yo);
                        if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
                                double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+                               //lyxerr << "x: " << x << " y: " << y << " d: " << endl;
                                // '<=' in order to take the last possible position
                                // this is important for clicking behind \sum in e.g. '\sum_i a'
                                if (d <= best_dist) {
@@ -1049,12 +1054,13 @@ void MathCursor::bruteFind2(int x, int y)
        it.back().setPos(0);
        MathIterator et = Cursor_;
        et.back().setPos(it.cell().size());
-       while (1) {
+       for (int i = 0; ; ++i) {
                int xo, yo;
                it.back().getPos(xo, yo);
                double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
                // '<=' in order to take the last possible position
                // this is important for clicking behind \sum in e.g. '\sum_i a'
+               lyxerr << "i: " << i << " d: " << d << " best: " << best_dist << endl;
                if (d <= best_dist) {
                        best_dist = d;
                        Cursor_   = it;
@@ -1068,21 +1074,21 @@ void MathCursor::bruteFind2(int x, int y)
 
 bool MathCursor::idxLineLast()
 {
-       idx() -= idx() % par()->ncols();
-       idx() += par()->ncols() - 1;
+       idx() -= idx() % inset()->ncols();
+       idx() += inset()->ncols() - 1;
        pos() = size();
        return true;
 }
 
 bool MathCursor::idxLeft()
 {
-       return par()->idxLeft(idx(), pos());
+       return inset()->idxLeft(idx(), pos());
 }
 
 
 bool MathCursor::idxRight()
 {
-       return par()->idxRight(idx(), pos());
+       return inset()->idxRight(idx(), pos());
 }
 
 
@@ -1101,7 +1107,7 @@ bool MathCursor::script(bool up)
        string safe = grabAndEraseSelection();
        if (inNucleus()) {
                // we are in a nucleus of a script inset, move to _our_ script
-               par()->asScriptInset()->ensure(up);
+               inset()->asScriptInset()->ensure(up);
                idx() = up;
                pos() = 0;
        } else if (hasPrevAtom() && prevAtom()->asScriptInset()) {
@@ -1130,7 +1136,7 @@ bool MathCursor::script(bool up)
 
 bool MathCursor::interpret(char c)
 {
-       //lyxerr << "interpret 2: '" << c << "'\n";
+       //lyxerr << "interpret 2: '" << c << "'" << endl;
        targetx_ = -1; // "no target"
        if (inMacroArgMode()) {
                --pos();
@@ -1149,7 +1155,7 @@ bool MathCursor::interpret(char c)
        // handle macroMode
        if (inMacroMode()) {
                string name = macroName();
-               //lyxerr << "interpret name: '" << name << "'\n";
+               //lyxerr << "interpret name: '" << name << "'" << endl;
 
                if (isalpha(c)) {
                        activeMacro()->setName(activeMacro()->name() + c);
@@ -1202,7 +1208,7 @@ bool MathCursor::interpret(char c)
        selClearOrDel();
 
        if (c == '\\') {
-               //lyxerr << "starting with macro\n";
+               //lyxerr << "starting with macro" << endl;
                insert(MathAtom(new MathUnknownInset("\\", false)));
                return true;
        }
@@ -1233,18 +1239,8 @@ bool MathCursor::interpret(char c)
                return pos() != size();
        }
 
-       if (c == '#') {
-               insert(c);
-               return true;
-       }
-
-       if (c == '{' || c == '}') {
-               niceInsert(createMathInset(string(1, c)));
-               return true;
-       }
-
-       if (c == '$') {
-               insert(createMathInset("$"));
+       if (c == '{' || c == '}' || c == '#' || c == '&' || c == '$') {
+               createMathInset(string(1, c));
                return true;
        }
 
@@ -1291,7 +1287,7 @@ string MathCursor::info() const
        ostringstream os;
        os << "Math editor mode.  ";
        for (int i = 0, n = depth(); i < n; ++i) {
-               Cursor_[i].par_->infoize(os);
+               Cursor_[i].inset_->infoize(os);
                os << "  ";
        }
        if (hasPrevAtom())
@@ -1311,11 +1307,11 @@ unsigned MathCursor::depth() const
 
 namespace {
 
-void region(MathCursorPos const & i1, MathCursorPos const & i2,
+void region(CursorPos const & i1, CursorPos const & i2,
        MathInset::row_type & r1, MathInset::row_type & r2,
        MathInset::col_type & c1, MathInset::col_type & c2)
 {
-       MathInset * p = i1.par_;
+       MathInset * p = i1.inset_;
        c1 = p->col(i1.idx_);
        c2 = p->col(i2.idx_);
        if (c1 > c2)
@@ -1334,8 +1330,8 @@ string MathCursor::grabSelection() const
        if (!selection_)
                return string();
 
-       MathCursorPos i1;
-       MathCursorPos i2;
+       CursorPos i1;
+       CursorPos i2;
        getSelection(i1, i2);
 
        if (i1.idx_ == i2.idx_) {
@@ -1354,7 +1350,7 @@ string MathCursor::grabSelection() const
                for (col_type col = c1; col <= c2; ++col) {
                        if (col > c1)
                                data += '&';
-                       data += asString(i1.par_->cell(i1.par_->index(row, col)));
+                       data += asString(i1.inset_->cell(i1.inset_->index(row, col)));
                }
        }
        return data;
@@ -1363,13 +1359,13 @@ string MathCursor::grabSelection() const
 
 void MathCursor::eraseSelection()
 {
-       MathCursorPos i1;
-       MathCursorPos i2;
+       CursorPos i1;
+       CursorPos i2;
        getSelection(i1, i2);
        if (i1.idx_ == i2.idx_)
                i1.cell().erase(i1.pos_, i2.pos_);
        else {
-               MathInset * p = i1.par_;
+               MathInset * p = i1.inset_;
                row_type r1, r2;
                col_type c1, c2;
                region(i1, i2, r1, r2, c1, c2);
@@ -1392,15 +1388,15 @@ string MathCursor::grabAndEraseSelection()
 }
 
 
-MathCursorPos MathCursor::normalAnchor() const
+CursorPos MathCursor::normalAnchor() const
 {
        if (Anchor_.size() < depth()) {
                Anchor_ = Cursor_;
-               lyxerr << "unusual Anchor size\n";
+               lyxerr << "unusual Anchor size" << endl;
        }
        //lyx::Assert(Anchor_.size() >= cursor.depth());
        // use Anchor on the same level as Cursor
-       MathCursorPos normal = Anchor_[depth() - 1];
+       CursorPos normal = Anchor_[depth() - 1];
        if (depth() < Anchor_.size() && !(normal < cursor())) {
                // anchor is behind cursor -> move anchor behind the inset
                ++normal.pos_;
@@ -1409,28 +1405,53 @@ MathCursorPos MathCursor::normalAnchor() const
 }
 
 
-MathInset::result_type MathCursor::dispatch(FuncRequest const & cmd)
-{
+dispatch_result MathCursor::dispatch(FuncRequest const & cmd)
+{
+       // mouse clicks are somewhat special
+       // check
+       switch (cmd.action) {
+               case LFUN_MOUSE_PRESS:
+               case LFUN_MOUSE_MOTION:
+               case LFUN_MOUSE_RELEASE:
+               case LFUN_MOUSE_DOUBLE: {
+                       CursorPos & pos = Cursor_.back();
+                       dispatch_result res = UNDISPATCHED;
+                       int x = 0, y = 0;
+                       getPos(x, y);
+                       if (x < cmd.x && hasPrevAtom()) {
+                               res = prevAtom().nucleus()->dispatch(cmd, pos.idx_, pos.pos_);
+                               if (res != UNDISPATCHED)
+                                       return res;
+                       }
+                       if (x > cmd.x && hasNextAtom()) {
+                               res = nextAtom().nucleus()->dispatch(cmd, pos.idx_, pos.pos_);
+                               if (res != UNDISPATCHED)
+                                       return res;
+                       }
+               }
+               default:
+                       break;
+       }
+
        for (int i = Cursor_.size() - 1; i >= 0; --i) {
-               MathCursorPos & pos = Cursor_[i];
-               MathInset::result_type
-                       res = pos.par_->dispatch(cmd, pos.idx_, pos.pos_);
-               if (res != MathInset::UNDISPATCHED) {
-                       if (res == MathInset::DISPATCHED_POP) {
+               CursorPos & pos = Cursor_[i];
+               dispatch_result res = pos.inset_->dispatch(cmd, pos.idx_, pos.pos_);
+               if (res != UNDISPATCHED) {
+                       if (res == DISPATCHED_POP) {
                                Cursor_.shrink(i + 1);
                                selClear();
                        }
                        return res;
                }
        }
-       return MathInset::UNDISPATCHED;
+       return UNDISPATCHED;
 }
 
 
 MathInset::mode_type MathCursor::currentMode() const
 {
        for (int i = Cursor_.size() - 1; i >= 0; --i) {
-               MathInset::mode_type res = Cursor_[i].par_->currentMode();
+               MathInset::mode_type res = Cursor_[i].inset_->currentMode();
                if (res != MathInset::UNDECIDED_MODE)
                        return res;
        }
@@ -1476,7 +1497,6 @@ void releaseMathCursor(BufferView * bv)
 {
        if (mathcursor) {
                InsetFormulaBase * f =  mathcursor->formula();
-               f->hideInsetCursor(bv);
                delete mathcursor;
                mathcursor = 0;
                f->insetUnlock(bv);