]> git.lyx.org Git - lyx.git/blobdiff - src/cursor.C
rename a function
[lyx.git] / src / cursor.C
index 7f96e6e32908c7e2a00bd3b4621273b5511d75ee..50d630ec8501b1bb42a8129781f2fe6380658ebf 100644 (file)
 #include "funcrequest.h"
 #include "iterators.h"
 #include "lfuns.h"
+#include "lyxfunc.h" // only for setMessage()
 #include "lyxrc.h"
-#include "lyxtext.h"
 #include "lyxrow.h"
+#include "lyxtext.h"
 #include "paragraph.h"
 
 #include "insets/updatableinset.h"
@@ -34,6 +35,9 @@
 #include "mathed/math_support.h"
 
 #include "support/limited_stack.h"
+#include "support/std_sstream.h"
+
+#include "frontends/LyXView.h"
 
 #include <boost/assert.hpp>
 
@@ -67,7 +71,7 @@ void LCursor::reset()
        anchor_.push_back(CursorSlice());
        current_ = 0;
        cached_y_ = 0;
-       x_target_ = -1;
+       clearTargetX();
        selection_ = false;
        mark_ = false;
 }
@@ -75,53 +79,46 @@ void LCursor::reset()
 
 DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
 {
-       lyxerr << "\nLCursor::dispatch: " << *this << endl;
+       lyxerr << "\nLCursor::dispatch: cmd: " << cmd0 << endl << *this << endl;
        FuncRequest cmd = cmd0;
-
-       for (int i = cursor_.size() - 1; i >= 1; --i) {
-               current_ = i;
-               CursorSlice const & citem = cursor_[i];
-               lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
-               DispatchResult res = inset()->dispatch(*this, cmd);
-               if (res.dispatched()) {
-                       lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
-                       return DispatchResult(true, true);
-               }
-               // remove one level of cursor
-               switch (res.val()) {
+       disp_.update(true);
+       disp_.val(NONE);
+       for (current_ = cursor_.size() - 1; current_ >= 1; --current_) {
+               // the inset's dispatch() is supposed to reset the update and
+               // val flags if necessary 
+               inset()->dispatch(*this, cmd);
+               
+               // "Mutate" the request for semi-handled requests that need
+               // additional handling in outer levels.
+               switch (disp_.val()) {
+                       case NONE:
+                               // the inset handled the event fully
+                               current_ = cursor_.size() - 1;
+                               return DispatchResult(true, true);
                        case FINISHED:
-                               pop(i);
+                               // the inset handled the event partially
                                cmd = FuncRequest(LFUN_FINISHED_LEFT);
                                break;
                        case FINISHED_RIGHT:
-                               pop(i);
                                cmd = FuncRequest(LFUN_FINISHED_RIGHT);
                                break;
                        case FINISHED_UP:
-                               pop(i);
                                cmd = FuncRequest(LFUN_FINISHED_UP);
                                break;
                        case FINISHED_DOWN:
-                               pop(i);
                                cmd = FuncRequest(LFUN_FINISHED_DOWN);
                                break;
                        default:
-                               lyxerr << "not handled on level " << i << " val: " << res.val() << endl;
+                               //lyxerr << "not handled on level " << current_
+                               //      << " val: " << disp_.val() << endl;
                                break;
                }
        }
-       lyxerr << "trying to dispatch to main text " << bv_->text() << endl;
-       DispatchResult res = bv_->text()->dispatch(*this, cmd);
-       lyxerr << "   result: " << res.val() << endl;
-
-       if (!res.dispatched()) {
-               lyxerr << "trying to dispatch to bv " << bv_ << endl;
-               bool sucess = bv_->dispatch(cmd);
-               lyxerr << "   result: " << sucess << endl;
-               res.dispatched(sucess);
-       }
-
-       return res;
+       BOOST_ASSERT(current_ == 0);
+       bv_->text()->dispatch(*this, cmd);
+       //lyxerr << "   result: " << res.val() << endl;
+       current_ = cursor_.size() - 1;
+       return disp_;
 }
 
 
@@ -137,29 +134,24 @@ void LCursor::push(InsetBase * inset)
 
 void LCursor::pop(int depth)
 {
-       lyxerr << "LCursor::pop() to depth " << depth << endl;
-       while (int(cursor_.size()) > depth)
+       while (int(cursor_.size()) > depth + 1)
                pop();
+       lyxerr << "LCursor::pop() result: " << *this << endl;
 }
 
 
 void LCursor::pop()
 {
-       lyxerr << "LCursor::pop() a level" << endl;
-       //BOOST_ASSERT(!cursor_.empty());
-       if (cursor_.size() <= 1)
-               lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
-       else {
-               cursor_.pop_back();
-               anchor_.pop_back();
-               current_ = cursor_.size() - 1;
-       }
-       lyxerr << "LCursor::pop() current now: " << current_ << endl;
+       BOOST_ASSERT(cursor_.size() >= 1);
+       cursor_.pop_back();
+       anchor_.pop_back();
+       current_ = cursor_.size() - 1;
 }
 
 
 void LCursor::pushLeft(InsetBase * p)
 {
+       BOOST_ASSERT(!cursor_.empty());
        //lyxerr << "Entering inset " << t << " left" << endl;
        push(p);
        p->idxFirst(*this);
@@ -168,6 +160,7 @@ void LCursor::pushLeft(InsetBase * p)
 
 bool LCursor::popLeft()
 {
+       BOOST_ASSERT(!cursor_.empty());
        //lyxerr << "Leaving inset to the left" << endl;
        if (depth() <= 1) {
                if (depth() == 1)
@@ -182,6 +175,7 @@ bool LCursor::popLeft()
 
 bool LCursor::popRight()
 {
+       BOOST_ASSERT(!cursor_.empty());
        //lyxerr << "Leaving inset to the right" << endl;
        if (depth() <= 1) {
                if (depth() == 1)
@@ -190,13 +184,14 @@ bool LCursor::popRight()
        }
        inset()->notifyCursorLeaves(idx());
        pop();
-       posRight();
+       ++pos();
        return true;
 }
 
 
 CursorSlice & LCursor::current()
 {
+       BOOST_ASSERT(!cursor_.empty());
        //lyxerr << "accessing cursor slice " << current_
        //      << ": " << cursor_[current_] << endl;
        return cursor_[current_];
@@ -213,6 +208,7 @@ CursorSlice const & LCursor::current() const
 
 int LCursor::currentMode()
 {
+       BOOST_ASSERT(!cursor_.empty());
        for (int i = cursor_.size() - 1; i >= 1; --i) {
                int res = cursor_[i].inset()->currentMode();
                if (res != MathInset::UNDECIDED_MODE)
@@ -224,7 +220,7 @@ int LCursor::currentMode()
 
 LyXText * LCursor::innerText() const
 {
-       //lyxerr << "LCursor::innerText()  depth: " << cursor_.size() << endl;
+       BOOST_ASSERT(!cursor_.empty());
        if (cursor_.size() > 1) {
                // go up until first non-0 text is hit
                // (innermost text is 0 in mathed)
@@ -238,7 +234,7 @@ LyXText * LCursor::innerText() const
 
 CursorSlice const & LCursor::innerTextSlice() const
 {
-       //lyxerr << "LCursor::innerTextSlice()  depth: " << cursor_.size() << endl;
+       BOOST_ASSERT(!cursor_.empty());
        if (cursor_.size() > 1) {
                // go up until first non-0 text is hit
                // (innermost text is 0 in mathed)
@@ -252,53 +248,57 @@ CursorSlice const & LCursor::innerTextSlice() const
 
 void LCursor::updatePos()
 {
+       BOOST_ASSERT(!cursor_.empty());
        if (cursor_.size() > 1)
-               cached_y_ = bv_->top_y() + cursor_.back().inset()->y();
+               cached_y_ = bv_->top_y() + cursor_.back().inset()->yo();
+               //cached_y_ = cursor_.back().inset()->yo();
 }
 
 
-void LCursor::getDim(int & asc, int & desc) const
+void LCursor::getDim(int & asc, int & des) const
 {
-       LyXText * txt = innerText();
-
-       if (txt) {
-               Row const & row = *txt->cursorRow();
-               asc = row.baseline();
-               desc = row.height() - asc;
-       } else {
+       BOOST_ASSERT(!cursor_.empty());
+       if (inMathed()) {
+               BOOST_ASSERT(inset());
+               BOOST_ASSERT(inset()->asMathInset());
+               //inset()->asMathInset()->getCursorDim(asc, des);
                asc = 10;
-               desc = 10;
-               //innerInset()->getCursorDim(asc, desc);
+               des = 10;
+       } else {
+               Row const & row = textRow();
+               asc = row.baseline();
+               des = row.height() - asc;
        }
 }
 
 
 void LCursor::getPos(int & x, int & y) const
 {
-       if (cursor_.size() <= 1) {
-               x = bv_->text()->cursorX();
-               y = bv_->text()->cursorY();
-//             y -= bv_->top_y();
+       BOOST_ASSERT(!cursor_.empty());
+       x = 0;
+       y = 0;
+       if (cursor_.size() == 1) {
+               x = bv_->text()->cursorX(cursor_.front());
+               y = bv_->text()->cursorY(cursor_.front());
        } else {
-               if (inset()->asUpdatableInset()) {
-                       // Would be nice to clean this up to make some understandable sense...
-                       // Non-obvious. The reason we have to have these
-                       // extra checks is that the ->getCursor() calls rely
-                       // on the inset's own knowledge of its screen position.
-                       // If we scroll up or down in a big enough increment, the
-                       // inset->draw() is not called: this doesn't update
-                       // inset.top_baseline, so getCursor() returns an old value.
-                       // Ugly as you like.
-                       inset()->asUpdatableInset()->getCursorPos(cursor_.back().idx_, x, y);
-                       x += inset()->asUpdatableInset()->x();
-                       y += cached_y_;
-               } else if (inset()->asMathInset()) {
-                       getScreenPos(x, y);
-               } else {
-                       // this should not happen
-                       BOOST_ASSERT(false);
+               if (!inset()) {
+                       lyxerr << "#### LCursor::getPos: " << *this << endl;
+                       BOOST_ASSERT(inset());
                }
+               inset()->getCursorPos(cursor_.back(), x, y);
+               // getCursorPos gives _screen_ coordinates. We need to add
+               // top_y to get document coordinates. This is hidden in cached_y_.
+               //y += cached_y_ - inset()->yo();
+               // The rest is non-obvious. The reason we have to have these
+               // extra computation is that the getCursorPos() calls rely
+               // on the inset's own knowledge of its screen position.
+               // If we scroll up or down in a big enough increment,
+               // inset->draw() is not called: this doesn't update
+               // inset.yo_, so getCursor() returns an old value.
+               // Ugly as you like.
        }
+       //lyxerr << "#### LCursor::getPos: " << *this 
+       // << " x: " << x << " y: " << y << endl;
 }
 
 
@@ -397,7 +397,6 @@ CursorSlice const & LCursor::selBegin() const
 {
        if (!selection())
                return cursor_.back();
-       // can't use std::min as this creates a new object
        return anchor() < cursor_.back() ? anchor() : cursor_.back();
 }
 
@@ -406,6 +405,7 @@ CursorSlice & LCursor::selBegin()
 {
        if (!selection())
                return cursor_.back();
+       // can't use std::min as this returns a const ref
        return anchor() < cursor_.back() ? anchor() : cursor_.back();
 }
 
@@ -420,8 +420,9 @@ CursorSlice const & LCursor::selEnd() const
 
 CursorSlice & LCursor::selEnd()
 {
-       if (selection())
+       if (!selection())
                return cursor_.back();
+       // can't use std::min as this returns a const ref
        return anchor() > cursor_.back() ? anchor() : cursor_.back();
 }
 
@@ -453,9 +454,9 @@ void LCursor::clearSelection()
 }
 
 
-void LCursor::x_target(int x)
+int & LCursor::x_target()
 {
-       x_target_ = x;
+       return x_target_;
 }
 
 
@@ -465,25 +466,66 @@ int LCursor::x_target() const
 }
 
 
+void LCursor::clearTargetX()
+{
+       x_target_ = -1;
+}
+
+
+LyXText * LCursor::text() const
+{
+       return current_ ? current().text() : bv_->text();
+}
+
+
 Paragraph & LCursor::paragraph()
 {
+       BOOST_ASSERT(inTexted());
        return current_ ? current().paragraph() : *bv_->text()->getPar(par());
 }
 
 
 Paragraph const & LCursor::paragraph() const
 {
+       BOOST_ASSERT(inTexted());
        return current_ ? current().paragraph() : *bv_->text()->getPar(par());
 }
 
 
+Row & LCursor::textRow()
+{
+       return *paragraph().getRow(pos());
+}
+
+
+Row const & LCursor::textRow() const
+{
+       return *paragraph().getRow(pos());
+}
+
+
+LCursor::par_type LCursor::lastpar() const
+{
+       return inMathed() ? 0 : text()->paragraphs().size() - 1;
+}
+
+
 LCursor::pos_type LCursor::lastpos() const
 {
-       CursorSlice const & cur = current();
-       if (cur.inset() && cur.inset()->asMathInset())
-               return cell().size();
-       else
-               return paragraph().size();
+       InsetBase * inset = current().inset();
+       return inset && inset->asMathInset() ? cell().size() : paragraph().size();
+}
+
+
+LCursor::row_type LCursor::crow() const
+{
+       return paragraph().row(pos());
+}
+
+
+LCursor::row_type LCursor::lastcrow() const
+{
+       return paragraph().rows.size();
 }
 
 
@@ -536,15 +578,14 @@ MathArray & LCursor::cell()
 }
 
 
-void LCursor::info(std::ostream & os)
+void LCursor::info(std::ostream & os) const
 {
        for (int i = 1, n = depth(); i < n; ++i) {
                cursor_[i].inset()->infoize(os);
                os << "  ";
        }
-#warning FIXME
-       //if (pos() != 0)
-       //      prevAtom()->infoize2(os);
+       if (pos() != 0)
+               prevInset()->infoize2(os);
        // overwite old message
        os << "                    ";
 }
@@ -611,8 +652,9 @@ string LCursor::grabSelection()
 
 void LCursor::eraseSelection()
 {
-       CursorSlice i1 = selBegin();
-       CursorSlice i2 = selEnd();
+       //lyxerr << "LCursor::eraseSelection" << endl;
+       CursorSlice const & i1 = selBegin();
+       CursorSlice const & i2 = selEnd();
 #warning FIXME
        if (i1.inset()->asMathInset()) {
                if (i1.idx_ == i2.idx_) {
@@ -630,6 +672,7 @@ void LCursor::eraseSelection()
        } else {
                lyxerr << "can't erase this selection 1" << endl;
        }
+       //lyxerr << "LCursor::eraseSelection end" << endl;
 }
 
 
@@ -670,6 +713,7 @@ void LCursor::selCut()
 
 void LCursor::selDel()
 {
+       //lyxerr << "LCursor::selDel" << endl;
        if (selection()) {
                eraseSelection();
                selection() = false;
@@ -689,6 +733,7 @@ void LCursor::selPaste(size_t n)
 
 void LCursor::selHandle(bool sel)
 {
+       //lyxerr << "LCursor::selHandle" << endl;
        if (sel == selection())
                return;
        resetAnchor();
@@ -696,15 +741,9 @@ void LCursor::selHandle(bool sel)
 }
 
 
-void LCursor::selStart()
-{
-       resetAnchor();
-       selection() = true;
-}
-
-
 void LCursor::selClearOrDel()
 {
+       //lyxerr << "LCursor::selClearOrDel" << endl;
        if (lyxrc.auto_region_delete)
                selDel();
        else
@@ -714,9 +753,10 @@ void LCursor::selClearOrDel()
 
 std::ostream & operator<<(std::ostream & os, LCursor const & cur)
 {
-       os << "\n";
        for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i)
-               os << "  (" << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n";
+               os << " " << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n";
+       os << " current: " << cur.current_ << endl;
+       os << " selection: " << cur.selection_ << endl;
        return os;
 }
 
@@ -835,7 +875,7 @@ bool LCursor::openable(MathAtom const & t)
        // we can't move into anything new during selection
        if (depth() == anchor_.size())
                return false;
-       if (t.nucleus() != anchor_[depth()].inset())
+       if (!ptr_cmp(t.nucleus(), anchor_[depth()].inset()))
                return false;
 
        return true;
@@ -851,7 +891,7 @@ bool LCursor::inNucleus()
 bool LCursor::left()
 {
        autocorrect() = false;
-       x_target(-1); // "no target"
+       clearTargetX();
        if (inMacroMode()) {
                macroModeClose();
                return true;
@@ -859,8 +899,8 @@ bool LCursor::left()
 
        if (pos() != 0 && openable(prevAtom())) {
                posLeft();
-               push(inset());
-               inset()->idxFirst(*this);
+               push(nextAtom().nucleus());
+               inset()->idxLast(*this);
                return true;
        }
 
@@ -871,14 +911,15 @@ bool LCursor::left()
 bool LCursor::right()
 {
        autocorrect() = false;
-       x_target(-1); // "no target"
+       clearTargetX();
        if (inMacroMode()) {
                macroModeClose();
                return true;
        }
 
        if (pos() != lastpos() && openable(nextAtom())) {
-               pushLeft(inset());
+               pushLeft(nextAtom().nucleus());
+               inset()->idxFirst(*this);
                return true;
        }
 
@@ -893,7 +934,7 @@ bool positionable(CursorBase const & cursor, CursorBase const & anchor)
                return false;
 
        // anchor might be deeper, should have same path then
-       for (CursorBase::size_type i = 0; i < cursor.size(); ++i)
+       for (size_t i = 0; i < cursor.size(); ++i)
                if (cursor[i].inset() != anchor[i].inset())
                        return false;
 
@@ -911,7 +952,7 @@ void LCursor::setScreenPos(int x, int y)
                idx() = 0;
                pos() = 0;
        }
-       x_target(-1); // "no target"
+       clearTargetX();
 }
 
 
@@ -922,7 +963,7 @@ bool LCursor::home()
        macroModeClose();
        if (!inset()->idxHome(*this))
                return popLeft();
-       x_target(-1); // "no target"
+       clearTargetX();
        return true;
 }
 
@@ -933,7 +974,7 @@ bool LCursor::end()
        macroModeClose();
        if (!inset()->idxEnd(*this))
                return popRight();
-       x_target(-1); // "no target"
+       clearTargetX();
        return true;
 }
 
@@ -963,26 +1004,24 @@ void LCursor::plainInsert(MathAtom const & t)
 }
 
 
-void LCursor::insert2(string const & str)
-{
-       MathArray ar;
-       asArray(str, ar);
-       insert(ar);
-}
-
-
 void LCursor::insert(string const & str)
 {
-       //lyxerr << "inserting '" << str << "'" << endl;
+       lyxerr << "LCursor::insert str '" << str << "'" << endl;
        selClearOrDel();
+#if 0
        for (string::const_iterator it = str.begin(); it != str.end(); ++it)
                plainInsert(MathAtom(new MathCharInset(*it)));
+#else
+       MathArray ar;
+       asArray(str, ar);
+       insert(ar);
+#endif
 }
 
 
 void LCursor::insert(char c)
 {
-       //lyxerr << "inserting '" << c << "'" << endl;
+       //lyxerr << "LCursor::insert char '" << c << "'" << endl;
        selClearOrDel();
        plainInsert(MathAtom(new MathCharInset(c)));
 }
@@ -990,12 +1029,22 @@ void LCursor::insert(char c)
 
 void LCursor::insert(MathAtom const & t)
 {
+       //lyxerr << "LCursor::insert MathAtom: " << endl;
        macroModeClose();
        selClearOrDel();
        plainInsert(t);
 }
 
 
+void LCursor::insert(InsetBase * inset)
+{
+       if (inMathed())
+               insert(MathAtom(inset));
+       else
+               text()->insertInset(*this, inset);
+}
+
+
 void LCursor::niceInsert(string const & t)
 {
        MathArray ar;
@@ -1015,7 +1064,9 @@ void LCursor::niceInsert(MathAtom const & t)
        // enter the new inset and move the contents of the selection if possible
        if (t->isActive()) {
                posLeft();
-               pushLeft(inset());
+               // be careful here: don't use 'pushLeft(t)' as this we need to
+               // push the clone, not the original
+               pushLeft(nextAtom().nucleus());
                paste(safe);
        }
 }
@@ -1080,9 +1131,8 @@ bool LCursor::erase()
        }
 
        // delete empty cells if possible
-#warning FIXME
-       //if (cell().empty() && inset()->idxDelete(idx()))
-       //              return true;
+       if (pos() == lastpos() && inset()->idxDelete(idx()))
+               return true;
 
        // special behaviour when in last position of cell
        if (pos() == lastpos()) {
@@ -1163,31 +1213,14 @@ string LCursor::macroName()
 }
 
 
-void LCursor::drawSelection(PainterInfo & pi)
-{
-       if (!selection())
-               return;
-       CursorSlice i1 = selBegin();
-       CursorSlice i2 = selEnd();
-       i1.asMathInset()->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
-}
-
-
 void LCursor::handleNest(MathAtom const & a, int c)
 {
-       MathAtom at = a;
-       asArray(grabAndEraseSelection(), at.nucleus()->cell(c));
-       insert(at);
+       //lyxerr << "LCursor::handleNest: " << c << endl;
+       MathAtom t = a;
+       asArray(grabAndEraseSelection(), t.nucleus()->cell(c));
+       insert(t);
        posLeft();
-       pushLeft(inset());
-}
-
-
-void LCursor::getScreenPos(int & x, int & y) const
-{
-       BOOST_ASSERT(inset());
-       BOOST_ASSERT(inset()->asMathInset());
-       inset()->asMathInset()->getScreenPos(idx(), pos(), x, y);
+       pushLeft(nextAtom().nucleus());
 }
 
 
@@ -1197,16 +1230,18 @@ int LCursor::targetX() const
                return x_target();
        int x = 0;
        int y = 0;
-       getScreenPos(x, y);
+       getPos(x, y);
        return x;
 }
 
 
 MathHullInset * LCursor::formula() const
 {
-       for (int i = cursor_.size() - 1; i >= 1; --i)
-               if (cursor_[i].inset()->lyxCode() == InsetBase::MATH_CODE)
-                       return static_cast<MathHullInset *>(cursor_[i].inset());
+       for (int i = cursor_.size() - 1; i >= 1; --i) {
+               MathInset * inset = cursor_[i].inset()->asMathInset();
+               if (inset && inset->asHullInset())
+                       return static_cast<MathHullInset *>(inset);
+       }
        return 0;
 }
 
@@ -1262,17 +1297,15 @@ MathGridInset * LCursor::enclosingGrid(idx_type & idx) const
 
 void LCursor::pullArg()
 {
-#warning look here
-#if 0
+#warning Look here
        MathArray ar = cell();
-       if (popLeft()) {
+       if (popLeft() && inMathed()) {
                plainErase();
                cell().insert(pos(), ar);
                resetAnchor();
        } else {
-               formula()->mutateToText();
+               //formula()->mutateToText();
        }
-#endif
 }
 
 
@@ -1295,7 +1328,7 @@ void LCursor::normalize()
                       << idx() << ' ' << nargs()
                       << " in: " << inset() << endl;
        }
-       idx() = min(idx(), nargs() - 1);
+       idx() = min(idx(), lastidx());
 
        if (pos() > lastpos()) {
                lyxerr << "this should not really happen - 2: "
@@ -1327,16 +1360,17 @@ char LCursor::halign()
 
 bool LCursor::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!
+       // 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 think you know
+       // what you are doing!
   int xo = 0;
        int yo = 0;
-       getScreenPos(xo, yo);
+       getPos(xo, yo);
 
        // check if we had something else in mind, if not, this is the future goal
        if (x_target() == -1)
-               x_target(xo);
+               x_target() = xo;
        else
                xo = x_target();
 
@@ -1407,7 +1441,7 @@ bool LCursor::goUpDown(bool up)
 
                // any improvement so far?
                int xnew, ynew;
-               getScreenPos(xnew, ynew);
+               getPos(xnew, ynew);
                if (up ? ynew < yo : ynew > yo)
                        return true;
        }
@@ -1425,7 +1459,8 @@ bool LCursor::bruteFind(int x, int y, int xlow, int xhigh, int ylow, int yhigh)
                // avoid invalid nesting when selecting
                if (!selection() || positionable(it, anchor_)) {
                        int xo, yo;
-                       it.back().getScreenPos(xo, yo);
+                       CursorSlice & cur = it.back();
+                       cur.inset()->getCursorPos(cur, 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;
@@ -1454,13 +1489,13 @@ void LCursor::bruteFind2(int x, int y)
        double best_dist = 1e10;
 
        CursorBase it = cursor_;
-       it.back().pos(0);
+       it.back().pos() = 0;
        CursorBase et = cursor_;
-       int n = et.back().asMathInset()->cell(et.back().idx_).size();
-       et.back().pos(n);
+       et.back().pos() = et.back().asMathInset()->cell(et.back().idx_).size();
        for (int i = 0; ; ++i) {
                int xo, yo;
-               it.back().getScreenPos(xo, yo);
+               CursorSlice & cur = it.back();
+               cur.inset()->getCursorPos(cur, 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'
@@ -1500,6 +1535,7 @@ bool LCursor::idxRight()
 bool LCursor::script(bool up)
 {
        // Hack to get \\^ and \\_ working
+       lyxerr << "handling script: up: " << up << endl;
        if (inMacroMode() && macroName() == "\\") {
                if (up)
                        niceInsert(createMathInset("mathcircumflex"));
@@ -1516,23 +1552,22 @@ bool LCursor::script(bool up)
                idx() = up;
                pos() = 0;
        } else if (pos() != 0 && prevAtom()->asScriptInset()) {
-               prevAtom().nucleus()->asScriptInset()->ensure(up);
-               posLeft();
-               push(inset());
+               --pos();
+               nextAtom().nucleus()->asScriptInset()->ensure(up);
+               push(nextInset());
                idx() = up;
                pos() = lastpos();
        } else if (pos() != 0) {
                --pos();
-               cell()[pos()]
-                       = MathAtom(new MathScriptInset(nextAtom(), up));
-               push(inset());
+               cell()[pos()] = MathAtom(new MathScriptInset(nextAtom(), up));
+               push(nextInset());
                idx() = up;
                pos() = 0;
        } else {
                plainInsert(MathAtom(new MathScriptInset(up)));
-               posLeft();
+               --pos();
                nextAtom().nucleus()->asScriptInset()->ensure(up);
-               push(inset());
+               push(nextInset());
                idx() = up;
                pos() = 0;
        }
@@ -1544,7 +1579,7 @@ bool LCursor::script(bool up)
 bool LCursor::interpret(char c)
 {
        //lyxerr << "interpret 2: '" << c << "'" << endl;
-       x_target(-1); // "no target"
+       clearTargetX();
        if (inMacroArgMode()) {
                posLeft();
                plainErase();
@@ -1688,7 +1723,7 @@ void LCursor::lockToggle()
        } else if (popLeft() && pos() != lastpos()) {
                // ... or enclosing inset if we are in the last inset position
                nextAtom().nucleus()->lock(!nextAtom()->lock());
-               posRight();
+               ++pos();
        }
 }
 
@@ -1701,7 +1736,7 @@ CursorSlice LCursor::normalAnchor()
        }
        //lyx::BOOST_ASSERT(Anchor_.size() >= cursor.depth());
        // use Anchor on the same level as Cursor
-       CursorSlice normal = anchor_[depth() - 1];
+       CursorSlice normal = anchor_[current_];
 #if 0
        if (depth() < anchor_.size() && !(normal < xx())) {
                // anchor is behind cursor -> move anchor behind the inset
@@ -1718,35 +1753,35 @@ DispatchResult dispatch(LCursor & cur, 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: {
-                       CursorSlice & pos = cursor_.back();
-                       int x = 0;
-                       int y = 0;
-                       getScreenPos(x, y);
-                       if (x < cmd.x && pos() != 0) {
-                               DispatchResult const res = prevAtom().nucleus()->dispatch(cmd);
-                               if (res.dispatched())
-                                       return res;
-                       }
-                       if (x > cmd.x && pos() != lastpos()) {
-                               DispatchResult const res = inset()->dispatch(cmd);
-                               if (res.dispatched())
-                                       return res;
-                       }
+       case LFUN_MOUSE_PRESS:
+       case LFUN_MOUSE_MOTION:
+       case LFUN_MOUSE_RELEASE:
+       case LFUN_MOUSE_DOUBLE: {
+               CursorSlice & pos = cursor_.back();
+               int x = 0;
+               int y = 0;
+               getPos(x, y);
+               if (x < cmd.x && pos() != 0) {
+                       DispatchResult const res = prevAtom().nucleus()->dispatch(cmd);
+                       if (res.dispatched())
+                               return res;
                }
-               default:
-                       break;
+               if (x > cmd.x && pos() != lastpos()) {
+                       DispatchResult const res = inset()->dispatch(cmd);
+                       if (res.dispatched())
+                               return res;
+               }
+       }
+       default:
+       break;
        }
-       /...
 }
 */
 
 
 void LCursor::handleFont(string const & font)
 {
+       lyxerr << "LCursor::handleFont: " << font << endl;
        string safe;
        if (selection()) {
                macroModeClose();
@@ -1779,14 +1814,148 @@ void LCursor::handleFont(string const & font)
 }
 
 
-void LCursor::releaseMathCursor()
+bool LCursor::inMathed() const
 {
-       if (inMathed())
-               formula()->insetUnlock(bv());
+       return formula();
 }
 
 
-bool LCursor::inMathed() const
+bool LCursor::inTexted() const
 {
-       return formula();
+       return !formula();
+}
+
+
+InsetBase * LCursor::nextInset()
+{
+       if (pos() == lastpos())
+               return 0;
+       if (inMathed()) 
+               return nextAtom().nucleus();
+       return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0;
+}
+
+
+InsetBase * LCursor::prevInset()
+{
+       if (pos() == 0)
+               return 0;
+       if (inMathed()) 
+               return prevAtom().nucleus();
+       return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
+}
+
+
+InsetBase const * LCursor::prevInset() const
+{
+       if (pos() == 0)
+               return 0;
+       if (inMathed()) 
+               return prevAtom().nucleus();
+       return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
+}
+
+
+void LCursor::message(string const & msg) const
+{
+       bv().owner()->getLyXFunc().setMessage(msg);
+}
+
+
+void LCursor::errorMessage(string const & msg) const
+{
+       bv().owner()->getLyXFunc().setErrorMessage(msg);
+}
+
+
+string LCursor::selectionAsString(bool label) const
+{
+       if (!selection())
+               return string();
+
+       if (inTexted()) {
+               Buffer const & buffer = *bv().buffer();
+
+               // should be const ...
+               ParagraphList::iterator startpit = text()->getPar(selBegin());
+               ParagraphList::iterator endpit = text()->getPar(selEnd());
+               size_t const startpos = selBegin().pos();
+               size_t const endpos = selEnd().pos();
+
+               if (startpit == endpit)
+                       return startpit->asString(buffer, startpos, endpos, label);
+
+               // First paragraph in selection
+               string result =
+                       startpit->asString(buffer, startpos, startpit->size(), label) + "\n\n";
+
+               // The paragraphs in between (if any)
+               ParagraphList::iterator pit = startpit;
+               for (++pit; pit != endpit; ++pit)
+                       result += pit->asString(buffer, 0, pit->size(), label) + "\n\n";
+
+               // Last paragraph in selection
+               result += endpit->asString(buffer, 0, endpos, label);
+
+               return result;
+       }
+
+#warning an mathed?
+       return string();
+}
+
+
+string LCursor::currentState()
+{
+       if (inMathed()) {
+               std::ostringstream os;
+               info(os);
+               return os.str();
+       }
+       return text() ? text()->currentState(*this) : string();
+}
+
+
+// only used by the spellchecker
+void LCursor::replaceWord(string const & replacestring)
+{
+       LyXText * t = text();
+       BOOST_ASSERT(t);
+
+       t->replaceSelectionWithString(*this, replacestring);
+       t->setSelectionRange(*this, replacestring.length());
+
+       // Go back so that replacement string is also spellchecked
+       for (string::size_type i = 0; i < replacestring.length() + 1; ++i)
+               t->cursorLeft(*this, true);
+}
+
+
+void LCursor::update()
+{
+       bv().update();
+}
+
+
+string LCursor::getPossibleLabel()
+{
+       return inMathed() ? "eq:" : text()->getPossibleLabel(*this);
+}
+
+
+void LCursor::notdispatched()
+{
+       disp_.dispatched(false);
+}
+
+
+void LCursor::dispatched(dispatch_result_t res)
+{
+       disp_.val(res);
+}
+
+
+void LCursor::noupdate()
+{
+       disp_.update(false);
 }