]> git.lyx.org Git - lyx.git/blobdiff - src/text3.C
more cursor dispatch
[lyx.git] / src / text3.C
index 4b83a107e304b47f19dd71ebb1f9902cc1467b76..ca40002a96bcbb4a3ab84564e511a76c51165dfb 100644 (file)
@@ -20,7 +20,9 @@
 #include "buffer.h"
 #include "bufferparams.h"
 #include "BufferView.h"
+#include "cursor.h"
 #include "debug.h"
+#include "dispatchresult.h"
 #include "factory.h"
 #include "funcrequest.h"
 #include "gettext.h"
@@ -29,8 +31,8 @@
 #include "lyxrc.h"
 #include "lyxrow.h"
 #include "paragraph.h"
+#include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
-#include "text_funcs.h"
 #include "undo.h"
 #include "vspace.h"
 
 
 #include "support/lstrings.h"
 #include "support/tostr.h"
-
 #include "support/std_sstream.h"
+
+#include "mathed/math_hullinset.h"
+
 #include <clocale>
 
 using bv_funcs::replaceSelection;
@@ -63,127 +67,227 @@ using std::vector;
 
 
 extern string current_layout;
-extern int bibitemMaxWidth(BufferView *, LyXFont const &);
 
 // the selection possible is needed, that only motion events are
-// used, where the bottom press event was on the drawing area too
+// used, where the button press event was on the drawing area too
 bool selection_possible = false;
 
 
 namespace {
 
-       void moveCursorUpdate(BufferView * bv, bool selecting)
-       {
-               LyXText * lt = bv->getLyXText();
-
-               //if (!lt->selection.set())
-    // lt->selection.cursor = lt->cursor;
+       // globals...
+       LyXFont freefont(LyXFont::ALL_IGNORE);
+       bool toggleall = false;
 
-               if (selecting || lt->selection.mark())
-                       lt->setSelection();
 
-               if (!lt->selection.set())
-                       bv->haveSelection(false);
+       void toggleAndShow(BufferView * bv, LyXText * text,
+               LyXFont const & font, bool toggleall = true)
+       {
+               if (!bv->available())
+                       return;
 
+               text->toggleFree(font, toggleall);
                bv->update();
-               bv->switchKeyMap();
+
+               if (font.language() != ignore_language ||
+                               font.number() != LyXFont::IGNORE) {
+                       CursorSlice & cur = text->cursor();
+                       Paragraph & par = *text->cursorPar();
+                       text->bidi.computeTables(par, *bv->buffer(),
+                               *par.getRow(cur.pos()));
+                       if (cur.boundary() !=
+                                       text->bidi.isBoundary(*bv->buffer(), par,
+                                                       cur.pos(),
+                                                       text->real_current_font))
+                               text->setCursor(cur.par(), cur.pos(),
+                                               false, !cur.boundary());
+               }
        }
 
 
-       void finishChange(BufferView * bv, bool selecting = false)
+       /// Apply the contents of freefont at the current cursor location.
+       void apply_freefont(BufferView * bv, LyXText * text)
        {
-               finishUndo();
-               moveCursorUpdate(bv, selecting);
+               toggleAndShow(bv, text, freefont, toggleall);
                bv->owner()->view_state_changed();
+               bv->owner()->message(_("Character set"));
        }
 
-       // check if the given co-ordinates are inside an inset at the
-       // given cursor, if one exists. If so, the inset is returned,
-       // and the co-ordinates are made relative. Otherwise, 0 is returned.
-       InsetOld * checkInset(LyXText & text,
-               LyXCursor const & cur, int & x, int & y)
+
+       /** Set the freefont using the contents of \param data dispatched from
+        *  the frontends and apply it at the current cursor location.
+        */
+       void update_and_apply_freefont(BufferView * bv, LyXText * text,
+               string const & data)
        {
-               lyx::pos_type const pos = cur.pos();
-               ParagraphList::iterator par = text.getPar(cur);
+               LyXFont font;
+               bool toggle;
+               if (bv_funcs::string2font(data, font, toggle)) {
+                       freefont = font;
+                       toggleall = toggle;
+                       apply_freefont(bv, text);
+               }
+       }
 
-               if (pos >= par->size() || !par->isInset(pos))
-                       return 0;
 
-               InsetOld /*const*/ * inset = par->getInset(pos);
+       void emph(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setEmph(LyXFont::TOGGLE);
+               toggleAndShow(bv, text, font);
+       }
 
-               if (!isEditableInset(inset))
-                       return 0;
 
-               // get inset dimensions
-               BOOST_ASSERT(par->getInset(pos));
+       void bold(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setSeries(LyXFont::BOLD_SERIES);
+               toggleAndShow(bv, text, font);
+       }
 
-               LyXFont const & font = text.getFont(par, pos);
 
-               int const width = inset->width();
-               int const inset_x = font.isVisibleRightToLeft()
-                       ? (cur.x() - width) : cur.x();
+       void noun(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setNoun(LyXFont::TOGGLE);
+               toggleAndShow(bv, text, font);
+       }
 
-               Box b(
-                       inset_x + inset->scroll(),
-                       inset_x + width,
-                       cur.y() - inset->ascent(),
-                       cur.y() + inset->descent()
-               );
 
-               if (!b.contains(x, y)) {
-                       lyxerr[Debug::GUI] << "Missed inset at x,y "
-                                          << x << ',' << y
-                                          << " box " << b << endl;
-                       return 0;
-               }
+       void lang(BufferView * bv, string const & l, LyXText * text)
+       {
+               Language const * lang = languages.getLanguage(l);
+               if (!lang)
+                       return;
 
-               text.setCursor(cur.par(), pos, true);
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setLanguage(lang);
+               toggleAndShow(bv, text, font);
+       }
 
-               x -= b.x1;
-               // The origin of an inset is on the baseline
-               y -= text.cursor.y();
 
-               return inset;
+       void code(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setFamily(LyXFont::TYPEWRITER_FAMILY); // no good
+               toggleAndShow(bv, text, font);
        }
 
-} // anon namespace
 
+       void sans(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setFamily(LyXFont::SANS_FAMILY);
+               toggleAndShow(bv, text, font);
+       }
 
-InsetOld * LyXText::checkInsetHit(int & x, int & y)
-{
-       int y_tmp = y + bv_owner->top_y();
 
-       LyXCursor cur;
-       setCursorFromCoordinates(cur, x, y_tmp);
+       void roman(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setFamily(LyXFont::ROMAN_FAMILY);
+               toggleAndShow(bv, text, font);
+       }
 
-       InsetOld * inset = checkInset(*this, cur, x, y_tmp);
-       if (inset) {
-               y = y_tmp;
-               return inset;
+
+       void styleReset(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_INHERIT, ignore_language);
+               toggleAndShow(bv, text, font);
        }
 
-       // look at previous position
-       if (cur.pos() == 0)
-               return 0;
 
-       // move back one
-       setCursor(cur, cur.par(), cur.pos() - 1, true);
+       void underline(BufferView * bv, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setUnderbar(LyXFont::TOGGLE);
+               toggleAndShow(bv, text, font);
+       }
+
+
+       void fontSize(BufferView * bv, string const & size, LyXText * text)
+       {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setLyXSize(size);
+               toggleAndShow(bv, text, font);
+       }
+
+
+       void moveCursor(LCursor & cur, bool selecting)
+       {
+               if (selecting || cur.mark())
+                       cur.setSelection();
+               if (!cur.selection())
+                       cur.bv().haveSelection(false);
+               cur.bv().switchKeyMap();
+       }
+
+
+       void finishChange(BufferView * bv, bool selecting = false)
+       {
+               finishUndo();
+               moveCursor(bv->cursor(), selecting);
+               bv->owner()->view_state_changed();
+       }
+
+} // anon namespace
+
+
+namespace bv_funcs {
+
+string const freefont2string()
+{
+       string data;
+       if (font2string(freefont, toggleall, data))
+               return data;
+       return string();
+}
 
-       inset = checkInset(*this, cur, x, y_tmp);
-       if (inset)
-               y = y_tmp;
-       return inset;
 }
 
 
-bool LyXText::gotoNextInset(vector<InsetOld::Code> const & codes,
+InsetBase * LyXText::checkInsetHit(int x, int y)
+{
+       ParagraphList::iterator pit;
+       ParagraphList::iterator end;
+
+       getParsInRange(paragraphs(),
+                      bv()->top_y(),
+                      bv()->top_y() + bv()->workHeight(),
+                      pit, end);
+
+       lyxerr << "checkInsetHit: x: " << x << " y: " << y << endl;
+       for ( ; pit != end; ++pit) {
+               InsetList::iterator iit = pit->insetlist.begin();
+               InsetList::iterator iend = pit->insetlist.end();
+               for ( ; iit != iend; ++iit) {
+                       InsetBase * inset = iit->inset;
+#if 1
+                       lyxerr << "examining inset " << inset
+                       //<< " xo/yo: " << inset->xo() << "/" << inset->yo()
+                               << " xo: " << inset->xo() << "..." << inset->xo() + inset->width()
+                               << " yo: " << inset->yo() - inset->ascent() << "..."
+                               << inset->yo() + inset->descent() << endl;
+#endif
+                       if (inset->covers(x, y - bv()->top_y())) {
+                               lyxerr << "Hit inset: " << inset << endl;
+                               return inset;
+                       }
+               }
+       }
+       lyxerr << "No inset hit. " << endl;
+       return 0;
+}
+
+
+bool LyXText::gotoNextInset(vector<InsetOld_code> const & codes,
                            string const & contents)
 {
-       ParagraphList::iterator end = ownerParagraphs().end();
+       ParagraphList::iterator end = paragraphs().end();
        ParagraphList::iterator pit = cursorPar();
-       pos_type pos = cursor.pos();
+       pos_type pos = cursor().pos();
 
-       InsetOld * inset;
+       InsetBase * inset;
        do {
                if (pos + 1 < pit->size()) {
                        ++pos;
@@ -208,198 +312,146 @@ bool LyXText::gotoNextInset(vector<InsetOld::Code> const & codes,
 }
 
 
-void LyXText::gotoInset(vector<InsetOld::Code> const & codes,
-                       bool same_content)
+void LyXText::gotoInset(vector<InsetOld_code> const & codes, bool same_content)
 {
-       bv()->beforeChange(this);
+       LCursor & cur = bv()->cursor();
+       cur.clearSelection();
 
        string contents;
-       if (same_content && cursor.pos() < cursorPar()->size()
-           && cursorPar()->isInset(cursor.pos())) {
-               InsetOld const * inset = cursorPar()->getInset(cursor.pos());
+       if (same_content
+           && cur.pos() < cur.lastpos()
+           && cur.paragraph().isInset(cur.pos())) {
+               InsetBase const * inset = cur.paragraph().getInset(cur.pos());
                if (find(codes.begin(), codes.end(), inset->lyxCode())
                    != codes.end())
                        contents = static_cast<InsetCommand const *>(inset)->getContents();
        }
 
        if (!gotoNextInset(codes, contents)) {
-               if (cursor.pos() || cursorPar() != ownerParagraphs().begin()) {
-                       LyXCursor tmp = cursor;
-                       cursor.par(0);
-                       cursor.pos(0);
+               if (cur.pos() || cur.par() != 0) {
+                       CursorSlice tmp = cursor();
+                       cur.par() = 0;
+                       cur.pos() = 0;
                        if (!gotoNextInset(codes, contents)) {
-                               cursor = tmp;
-                               bv()->owner()->message(_("No more insets"));
+                               cursor() = tmp;
+                               cur.bv().owner()->message(_("No more insets"));
                        }
                } else {
-                       bv()->owner()->message(_("No more insets"));
+                       cur.bv().owner()->message(_("No more insets"));
                }
        }
-       bv()->update();
-       selection.cursor = cursor;
+       cur.bv().update();
+       cur.resetAnchor();
 }
 
 
-void LyXText::gotoInset(InsetOld::Code code, bool same_content)
+void LyXText::gotoInset(InsetOld_code code, bool same_content)
 {
-       gotoInset(vector<InsetOld::Code>(1, code), same_content);
+       gotoInset(vector<InsetOld_code>(1, code), same_content);
 }
 
 
 void LyXText::cursorPrevious()
 {
-       int y = bv_owner->top_y();
+       LCursor & cur = bv()->cursor();
+       pos_type cpos = cur.pos();
+       lyx::paroffset_type cpar = cur.par();
 
-       RowList::iterator rit = cursorRow();
+       int x = bv()->cursor().x_target();
+       int y = bv()->top_y();
+       setCursorFromCoordinates(x, y);
 
-       if (rit == firstRow()) {
-               if (y > 0)
-                       bv()->updateScrollbar();
-               return;
-       }
-
-       setCursorFromCoordinates(cursor.x_fix(), y);
-       finishUndo();
-
-       int new_y;
-       if (rit == bv()->text->cursorRow()) {
+       if (cpar == cur.par() && cpos == cur.pos()) {
                // we have a row which is taller than the workarea. The
                // simplest solution is to move to the previous row instead.
                cursorUp(true);
-               return;
-               // This is what we used to do, so we wouldn't skip right past
-               // tall rows, but it's not working right now.
-       } else {
-               if (inset_owner) {
-                       new_y = bv()->text->cursor.y()
-                               + bv()->theLockingInset()->insetInInsetY() + y
-                               + rit->height()
-                               - bv()->workHeight() + 1;
-               } else {
-                       new_y = cursor.y()
-                               - rit->baseline()
-                               + rit->height()
-                               - bv()->workHeight() + 1;
-               }
        }
 
-       LyXCursor cur;
-       ParagraphList::iterator pit = cursorPar();
-       previousRow(pit, rit);
-       setCursor(cur, parOffset(pit), rit->pos(), false);
-       if (cur.y() > bv_owner->top_y())
-               cursorUp(true);
        bv()->updateScrollbar();
+       finishUndo();
 }
 
 
 void LyXText::cursorNext()
 {
-       int topy = bv_owner->top_y();
-
-       RowList::iterator rit = cursorRow();
-       if (rit == lastRow()) {
-               int y = cursor.y() - rit->baseline() + cursorRow()->height();
-               if (y > topy + bv()->workHeight())
-                       bv_owner->updateScrollbar();
-               return;
-       }
-
-       int y = topy + bv_owner->workHeight();
-       if (inset_owner && !topy) {
-               y -= (bv_owner->text->cursor.y()
-                         - bv_owner->top_y()
-                         + bv_owner->theLockingInset()->insetInInsetY());
-       }
+       LCursor & cur = bv()->cursor();
+       pos_type cpos = cur.pos();
+       lyx::paroffset_type cpar = cur.par();
 
-       ParagraphList::iterator dummypit;
-       Row const & rr = *getRowNearY(y, dummypit);
-       y = dummypit->y + rr.y_offset();
+       int x = cur.x_target();
+       int y = bv()->top_y() + bv()->workHeight();
+       setCursorFromCoordinates(x, y);
 
-       setCursorFromCoordinates(cursor.x_fix(), y);
-       // + bv->workHeight());
-       finishUndo();
-
-       int new_y;
-       if (rit == bv_owner->text->cursorRow()) {
+       if (cpar == cur.par() && cpos == cur.pos()) {
                // we have a row which is taller than the workarea. The
                // simplest solution is to move to the next row instead.
                cursorDown(true);
-               return;
-               // This is what we used to do, so we wouldn't skip right past
-               // tall rows, but it's not working right now.
-#if 0
-               new_y = bv->top_y() + bv->workHeight();
-#endif
-       } else {
-               if (inset_owner) {
-                       new_y = bv()->text->cursor.y()
-                               + bv()->theLockingInset()->insetInInsetY()
-                               + y - rit->baseline();
-               } else {
-                       new_y = cursor.y() - cursorRow()->baseline();
-               }
        }
 
-       ParagraphList::iterator pit = cursorPar();
-       nextRow(pit, rit);
-       LyXCursor cur;
-       setCursor(cur, parOffset(pit), rit->pos(), false);
-       if (cur.y() < bv_owner->top_y() + bv()->workHeight())
-               cursorDown(true);
        bv()->updateScrollbar();
+       finishUndo();
 }
 
 
 namespace {
 
-void specialChar(LyXText * lt, BufferView * bv, InsetSpecialChar::Kind kind)
+void specialChar(LyXText * text, BufferView * bv, InsetSpecialChar::Kind kind)
 {
        bv->update();
        InsetSpecialChar * new_inset = new InsetSpecialChar(kind);
-       replaceSelection(lt);
+       replaceSelection(text);
        if (!bv->insertInset(new_inset))
                delete new_inset;
        else
-               bv->updateInset(new_inset);
+               bv->update();
 }
 
 
-void doInsertInset(LyXText * lt, FuncRequest const & cmd,
-                  bool edit, bool pastesel)
+void doInsertInset(BufferView * bv, FuncRequest const & cmd,
+       bool edit, bool pastesel)
 {
-       InsetOld * inset = createInset(cmd);
-       BufferView * bv = cmd.view();
-
-       if (inset) {
-               bool gotsel = false;
-               if (lt->selection.set()) {
-                       bv->owner()->dispatch(FuncRequest(LFUN_CUT));
-                       gotsel = true;
-               }
-               if (bv->insertInset(inset)) {
-                       if (edit) {
-                               FuncRequest cmd(bv, LFUN_INSET_EDIT, "left");
-                               inset->dispatch(cmd);
-                       }
-                       if (gotsel && pastesel)
-                               bv->owner()->dispatch(FuncRequest(LFUN_PASTE));
-               }
-               else
-                       delete inset;
+       InsetBase * inset = createInset(bv, cmd);
+       if (!inset)
+               return;
+
+       bool gotsel = false;
+       if (bv->cursor().selection()) {
+               bv->owner()->dispatch(FuncRequest(LFUN_CUT));
+               gotsel = true;
+       }
+       if (bv->insertInset(inset)) {
+               if (edit)
+                       inset->edit(bv->cursor(), true);
+               if (gotsel && pastesel)
+                       bv->owner()->dispatch(FuncRequest(LFUN_PASTE));
+       } else {
+               delete inset;
        }
 }
 
 } // anon namespace
 
 
-dispatch_result LyXText::dispatch(FuncRequest const & cmd)
+void LyXText::number()
+{
+       LyXFont font(LyXFont::ALL_IGNORE);
+       font.setNumber(LyXFont::TOGGLE);
+       toggleAndShow(bv(), this, font);
+}
+
+
+bool LyXText::rtl() const
+{
+       return cursorPar()->isRightToLeftPar(bv()->buffer()->params());
+}
+
+
+DispatchResult LyXText::dispatch(LCursor & cur, FuncRequest const & cmd)
 {
-       lyxerr[Debug::ACTION] << "LyXText::dispatch: action[" << cmd.action
-                             <<"] arg[" << cmd.argument << ']' << "xy[" <<
-                                 cmd.x << ',' << cmd.y << ']' << endl;
+       lyxerr[Debug::ACTION] << "LyXText::dispatch: cmd: " << cmd << endl;
+       //lyxerr << "*** LyXText::dispatch: cmd: " << cmd << endl;
 
-       BufferView * bv = cmd.view();
+       BufferView * bv = &cur.bv();
 
        switch (cmd.action) {
 
@@ -408,8 +460,8 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                bool start = !pit->params().startOfAppendix();
 
                // ensure that we have only one start_of_appendix in this document
-               ParagraphList::iterator tmp = ownerParagraphs().begin();
-               ParagraphList::iterator end = ownerParagraphs().end();
+               ParagraphList::iterator tmp = paragraphs().begin();
+               ParagraphList::iterator end = paragraphs().end();
 
                for (; tmp != end; ++tmp) {
                        if (tmp->params().startOfAppendix()) {
@@ -426,33 +478,32 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                // we can set the refreshing parameters now
                updateCounters();
                redoParagraph(cursorPar());
-               setCursor(cursorPar(), cursor.pos());
                bv->update();
                break;
        }
 
        case LFUN_DELETE_WORD_FORWARD:
-               bv->beforeChange(this);
+               cur.clearSelection();
                deleteWordForward();
                finishChange(bv);
                break;
 
        case LFUN_DELETE_WORD_BACKWARD:
-               bv->beforeChange(this);
+               cur.clearSelection();
                deleteWordBackward();
                finishChange(bv);
                break;
 
        case LFUN_DELETE_LINE_FORWARD:
-               bv->beforeChange(this);
+               cur.clearSelection();
                deleteLineForward();
                finishChange(bv);
                break;
 
        case LFUN_WORDRIGHT:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
+               if (!cur.mark())
+                       cur.clearSelection();
+               if (rtl())
                        cursorLeftOneWord();
                else
                        cursorRightOneWord();
@@ -460,9 +511,9 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_WORDLEFT:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
+               if (!cur.mark())
+                       cur.clearSelection();
+               if (rtl())
                        cursorRightOneWord();
                else
                        cursorLeftOneWord();
@@ -470,97 +521,99 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_BEGINNINGBUF:
-               if (!selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorTop();
                finishChange(bv);
                break;
 
        case LFUN_ENDBUF:
-               if (selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorBottom();
                finishChange(bv);
                break;
 
        case LFUN_RIGHTSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
-                       cursorLeft(bv);
+               if (!cur.selection())
+                       cur.resetAnchor();
+               if (rtl())
+                       cursorLeft(true);
                else
-                       cursorRight(bv);
+                       cursorRight(true);
                finishChange(bv, true);
                break;
 
        case LFUN_LEFTSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
-                       cursorRight(bv);
+               if (!cur.selection())
+                       cur.resetAnchor();
+               if (rtl())
+                       cursorRight(true);
                else
-                       cursorLeft(bv);
+                       cursorLeft(true);
                finishChange(bv, true);
                break;
 
        case LFUN_UPSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorUp(true);
                finishChange(bv, true);
                break;
 
        case LFUN_DOWNSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorDown(true);
                finishChange(bv, true);
                break;
 
        case LFUN_UP_PARAGRAPHSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorUpParagraph();
                finishChange(bv, true);
                break;
 
        case LFUN_DOWN_PARAGRAPHSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorDownParagraph();
                finishChange(bv, true);
                break;
 
        case LFUN_PRIORSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorPrevious();
                finishChange(bv, true);
                break;
 
        case LFUN_NEXTSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorNext();
                finishChange(bv, true);
                break;
 
        case LFUN_HOMESEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorHome();
                finishChange(bv, true);
                break;
 
        case LFUN_ENDSEL:
-               if (!selection.set())
-                       selection.cursor = cursor;
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorEnd();
                finishChange(bv, true);
                break;
 
        case LFUN_WORDRIGHTSEL:
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
+               if (!cur.selection())
+                       cur.resetAnchor();
+               if (rtl())
                        cursorLeftOneWord();
                else
                        cursorRightOneWord();
@@ -568,7 +621,9 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_WORDLEFTSEL:
-               if (cursorPar()->isRightToLeftPar(bv->buffer()->params()))
+               if (!cur.selection())
+                       cur.resetAnchor();
+               if (rtl())
                        cursorRightOneWord();
                else
                        cursorLeftOneWord();
@@ -576,172 +631,110 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_WORDSEL: {
-               LyXCursor cur1 = cursor;
-               LyXCursor cur2;
-               ::getWord(*this, cur1, cur2, lyx::WHOLE_WORD, ownerParagraphs());
-               setCursor(cur1.par(), cur1.pos());
-               bv->beforeChange(this);
-               setCursor(cur2.par(), cur2.pos());
+               selectWord(lyx::WHOLE_WORD);
                finishChange(bv, true);
                break;
        }
 
-       case LFUN_RIGHT: {
-               bool is_rtl = cursorPar()->isRightToLeftPar(bv->buffer()->params());
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               if (is_rtl)
-                       cursorLeft(false);
-               if (cursor.pos() < cursorPar()->size()
-                   && cursorPar()->isInset(cursor.pos())
-                   && isHighlyEditableInset(cursorPar()->getInset(cursor.pos()))) {
-                       InsetOld * tmpinset = cursorPar()->getInset(cursor.pos());
-                       cmd.message(tmpinset->editMessage());
-                       FuncRequest cmd1(bv, LFUN_INSET_EDIT, is_rtl ? "right" : "left");
-                       tmpinset->dispatch(cmd1);
-                       break;
-               }
-               if (!is_rtl)
-                       cursorRight(false);
+       case LFUN_RIGHT:
                finishChange(bv);
-               break;
-       }
+               return moveRight();
 
-       case LFUN_LEFT: {
-               // This is soooo ugly. Isn`t it possible to make
-               // it simpler? (Lgb)
-               bool const is_rtl = cursorPar()->isRightToLeftPar(bv->buffer()->params());
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               LyXCursor const cur = cursor;
-               if (!is_rtl)
-                       cursorLeft(false);
-               if ((is_rtl || cur != cursor) && // only if really moved!
-                   cursor.pos() < cursorPar()->size() &&
-                   cursorPar()->isInset(cursor.pos()) &&
-                   isHighlyEditableInset(cursorPar()->getInset(cursor.pos()))) {
-                       InsetOld * tmpinset = cursorPar()->getInset(cursor.pos());
-                       cmd.message(tmpinset->editMessage());
-                       FuncRequest cmd1(bv, LFUN_INSET_EDIT, is_rtl ? "left" : "right");
-                       tmpinset->dispatch(cmd1);
-                       break;
-               }
-               if (is_rtl)
-                       cursorRight(false);
+       case LFUN_LEFT:
                finishChange(bv);
-               break;
-       }
+               return moveLeft();
 
        case LFUN_UP:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               cursorUp(false);
                finishChange(bv);
-               break;
+               return moveUp();
 
        case LFUN_DOWN:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               cursorDown(false);
                finishChange(bv);
-               break;
+               return moveDown();
 
        case LFUN_UP_PARAGRAPH:
-               if (!selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorUpParagraph();
                finishChange(bv);
                break;
 
        case LFUN_DOWN_PARAGRAPH:
-               if (!selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorDownParagraph();
                finishChange(bv, false);
                break;
 
        case LFUN_PRIOR:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               cursorPrevious();
+               if (!cur.mark())
+                       cur.clearSelection();
                finishChange(bv, false);
+               if (cur.par() == 0 && cursorRow() == firstRow())
+                       return DispatchResult(false, FINISHED_UP);
+               cursorPrevious();
                break;
 
        case LFUN_NEXT:
-               if (!selection.mark())
-                       bv->beforeChange(this);
-               cursorNext();
+               if (!cur.mark())
+                       cur.clearSelection();
                finishChange(bv, false);
+               if (cur.par() == cur.lastpar() && cursorRow() == lastRow())
+                       return DispatchResult(false, FINISHED_DOWN);
+               cursorNext();
                break;
 
        case LFUN_HOME:
-               if (!selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorHome();
                finishChange(bv, false);
                break;
 
        case LFUN_END:
-               if (!selection.mark())
-                       bv->beforeChange(this);
+               if (!cur.mark())
+                       cur.clearSelection();
                cursorEnd();
                finishChange(bv, false);
                break;
 
        case LFUN_BREAKLINE: {
-               lyx::pos_type body = cursorPar()->beginningOfBody();
+               lyx::pos_type body = cursorPar()->beginOfBody();
 
                // Not allowed by LaTeX (labels or empty par)
-               if (cursor.pos() <= body)
+               if (cursor().pos() <= body)
                        break;
 
                replaceSelection(bv->getLyXText());
                insertInset(new InsetNewline);
-               setCursor(cursorPar(), cursor.pos());
-               moveCursorUpdate(bv, false);
+               moveCursor(cur, false);
                break;
        }
 
        case LFUN_DELETE:
-               if (!selection.set()) {
+               if (!cur.selection()) {
                        Delete();
-                       selection.cursor = cursor;
+                       cur.resetAnchor();
                        // It is possible to make it a lot faster still
                        // just comment out the line below...
                } else {
                        cutSelection(true, false);
                }
-               moveCursorUpdate(bv, false);
+               moveCursor(cur, false);
                bv->owner()->view_state_changed();
                break;
 
        case LFUN_DELETE_SKIP:
                // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
-               if (!selection.set()) {
-                       if (cursor.pos() == cursorPar()->size()) {
+               if (!cur.selection()) {
+                       if (cursor().pos() == cursorPar()->size()) {
                                cursorRight(bv);
-                               ParagraphParameters & params = cursorPar()->params();
-                               if (cursor.pos() == 0
-                                   && !(params.spaceTop() == VSpace (VSpace::NONE))) {
-                                       setParagraph(
-                                                params.lineTop(),
-                                                params.lineBottom(),
-                                                params.pagebreakTop(),
-                                                params.pagebreakBottom(),
-                                                VSpace(VSpace::NONE),
-                                                params.spaceBottom(),
-                                                params.spacing(),
-                                                params.align(),
-                                                params.labelWidthString(), 0);
-                                       cursorLeft(bv);
-                               } else {
-                                       cursorLeft(bv);
-                                       Delete();
-                                       selection.cursor = cursor;
-                               }
+                               cursorLeft(bv);
+                               Delete();
+                               cur.resetAnchor();
                        } else {
                                Delete();
-                               selection.cursor = cursor;
+                               cur.resetAnchor();
                        }
                } else {
                        cutSelection(true, false);
@@ -751,10 +744,10 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
 
 
        case LFUN_BACKSPACE:
-               if (!selection.set()) {
+               if (!cur.selection()) {
                        if (bv->owner()->getIntl().getTransManager().backspace()) {
                                backspace();
-                               selection.cursor = cursor;
+                               cur.resetAnchor();
                                // It is possible to make it a lot faster still
                                // just comment out the line below...
                        }
@@ -768,24 +761,11 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
 
        case LFUN_BACKSPACE_SKIP:
                // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
-               if (!selection.set()) {
-                       ParagraphParameters & params = cursorPar()->params();
-                       if (cursor.pos() == 0 && !(params.spaceTop() == VSpace(VSpace::NONE))) {
-                               setParagraph(
-                                        params.lineTop(),
-                                        params.lineBottom(),
-                                        params.pagebreakTop(),
-                                        params.pagebreakBottom(),
-                                        VSpace(VSpace::NONE),
-                                  params.spaceBottom(),
-                                        params.spacing(),
-                                        params.align(),
-                                        params.labelWidthString(), 0);
-                       } else {
-                               LyXCursor cur = cursor;
-                               backspace();
-                               selection.cursor = cur;
-                       }
+               if (!cur.selection()) {
+#warning look here
+                       //CursorSlice cur = cursor();
+                       backspace();
+                       //anchor() = cur;
                } else {
                        cutSelection(true, false);
                }
@@ -796,7 +776,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                replaceSelection(bv->getLyXText());
                breakParagraph(bv->buffer()->paragraphs(), 0);
                bv->update();
-               selection.cursor = cursor;
+               cur.resetAnchor();
                bv->switchKeyMap();
                bv->owner()->view_state_changed();
                break;
@@ -805,7 +785,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                replaceSelection(bv->getLyXText());
                breakParagraph(bv->buffer()->paragraphs(), 1);
                bv->update();
-               selection.cursor = cursor;
+               cur.resetAnchor();
                bv->switchKeyMap();
                bv->owner()->view_state_changed();
                break;
@@ -814,27 +794,20 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                // When at the beginning of a paragraph, remove
                // indentation and add a "defskip" at the top.
                // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
-               LyXCursor cur = cursor;
+#warning look here
+//             CursorSlice cur = cursor();
                replaceSelection(bv->getLyXText());
                if (cur.pos() == 0) {
-                       ParagraphParameters & params = getPar(cur)->params();
-                       if (params.spaceTop() == VSpace(VSpace::NONE)) {
-                               setParagraph(
-                                        params.lineTop(),
-                                        params.lineBottom(),
-                                        params.pagebreakTop(),
-                                        params.pagebreakBottom(),
-                                        VSpace(VSpace::DEFSKIP), params.spaceBottom(),
-                                        params.spacing(),
-                                        params.align(),
-                                        params.labelWidthString(), 1);
-                       }
-               }
-               else {
+                       ParagraphParameters & params = getPar(cur.current())->params();
+                       setParagraph(
+                                       params.spacing(),
+                                       params.align(),
+                                       params.labelWidthString(), 1);
+               } else {
                        breakParagraph(bv->buffer()->paragraphs(), 0);
                }
                bv->update();
-               selection.cursor = cur;
+//     anchor() = cur;
                bv->switchKeyMap();
                bv->owner()->view_state_changed();
                break;
@@ -882,14 +855,32 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
        }
 
+       case LFUN_INSET_APPLY: {
+               string const name = cmd.getArg(0);
+               InsetBase * inset = bv->owner()->getDialogs().getOpenInset(name);
+               if (inset)
+                       inset->dispatch(cur, FuncRequest(LFUN_INSET_MODIFY, cmd.argument));
+               else
+                       dispatch(cur, FuncRequest(LFUN_INSET_INSERT, cmd.argument));
+               break;
+       }
+
+       case LFUN_INSET_INSERT: {
+               InsetBase * inset = createInset(bv, cmd);
+               if (inset && !bv->insertInset(inset))
+                       delete inset;
+               break;
+       }
+
        case LFUN_INSET_SETTINGS:
-               BOOST_ASSERT(bv->theLockingInset());
-               bv->theLockingInset()->getLockingInset()->showInsetDialog(bv);
+               if (cur.inset() && cur.inset()->asUpdatableInset())
+                       cur.inset()->asUpdatableInset()->showInsetDialog(bv);
                break;
 
        case LFUN_INSET_TOGGLE:
-               bv->beforeChange(this);
-               toggleInset();
+               cur.clearSelection();
+               if (!toggleInset())
+                       return DispatchResult(false);
                bv->update();
                bv->switchKeyMap();
                break;
@@ -898,8 +889,8 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                if (cursorPar()->layout()->free_spacing)
                        insertChar(' ');
                else
-                       doInsertInset(this, cmd, false, false);
-               moveCursorUpdate(bv, false);
+                       doInsertInset(bv, cmd, false, false);
+               moveCursor(cur, false);
                break;
 
        case LFUN_HYPHENATION:
@@ -922,33 +913,6 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                specialChar(this, bv, InsetSpecialChar::MENU_SEPARATOR);
                break;
 
-       case LFUN_MARK_OFF:
-               bv->beforeChange(this);
-               bv->update();
-               selection.cursor = cursor;
-               cmd.message(N_("Mark off"));
-               break;
-
-       case LFUN_MARK_ON:
-               bv->beforeChange(this);
-               selection.mark(true);
-               bv->update();
-               selection.cursor = cursor;
-               cmd.message(N_("Mark on"));
-               break;
-
-       case LFUN_SETMARK:
-               bv->beforeChange(this);
-               if (selection.mark()) {
-                       cmd.message(N_("Mark removed"));
-               } else {
-                       selection.mark(true);
-                       cmd.message(N_("Mark set"));
-               }
-               selection.cursor = cursor;
-               bv->update();
-               break;
-
        case LFUN_UPCASE_WORD:
                changeCase(LyXText::text_uppercase);
                bv->update();
@@ -965,20 +929,20 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_TRANSPOSE_CHARS:
-               recUndo(cursor.par());
+               recUndo(cursor().par());
                redoParagraph();
                bv->update();
                break;
 
        case LFUN_PASTE:
-               cmd.message(_("Paste"));
+               cur.message(_("Paste"));
                replaceSelection(bv->getLyXText());
 #warning FIXME Check if the arg is in the domain of available selections.
                if (isStrUnsignedInt(cmd.argument))
                        pasteSelection(strToUnsignedInt(cmd.argument));
                else
                        pasteSelection(0);
-               clearSelection(); // bug 393
+               cur.clearSelection(); // bug 393
                bv->update();
                bv->switchKeyMap();
                finishUndo();
@@ -986,31 +950,36 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
 
        case LFUN_CUT:
                cutSelection(true, true);
-               cmd.message(_("Cut"));
+               cur.message(_("Cut"));
                bv->update();
                break;
 
        case LFUN_COPY:
                copySelection();
-               cmd.message(_("Copy"));
+               cur.message(_("Copy"));
                break;
 
        case LFUN_BEGINNINGBUFSEL:
-               if (inset_owner)
-                       return UNDISPATCHED;
+               if (in_inset_)
+                       return DispatchResult(false);
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorTop();
                finishChange(bv, true);
                break;
 
        case LFUN_ENDBUFSEL:
-               if (inset_owner)
-                       return UNDISPATCHED;
+               if (in_inset_)
+                       return DispatchResult(false);
+               if (!cur.selection())
+                       cur.resetAnchor();
                cursorBottom();
                finishChange(bv, true);
                break;
 
        case LFUN_GETXY:
-               cmd.message(tostr(cursor.x()) + ' ' + tostr(cursor.y()));
+               cur.message(tostr(cursorX(cur.current())) + ' '
+                         + tostr(cursorY(cur.current())));
                break;
 
        case LFUN_SETXY: {
@@ -1028,15 +997,15 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
 
        case LFUN_GETFONT:
                if (current_font.shape() == LyXFont::ITALIC_SHAPE)
-                       cmd.message("E");
+                       cur.message("E");
                else if (current_font.shape() == LyXFont::SMALLCAPS_SHAPE)
-                       cmd.message("N");
+                       cur.message("N");
                else
-                       cmd.message("0");
+                       cur.message("0");
                break;
 
        case LFUN_GETLAYOUT:
-               cmd.message(tostr(cursorPar()->layout()));
+               cur.message(cursorPar()->layout()->name());
                break;
 
        case LFUN_LAYOUT: {
@@ -1049,7 +1018,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                // function list/array with information about what
                // functions needs arguments and their type.
                if (cmd.argument.empty()) {
-                       cmd.errorMessage(_("LyX function 'layout' needs an argument."));
+                       cur.errorMessage(_("LyX function 'layout' needs an argument."));
                        break;
                }
 
@@ -1067,18 +1036,18 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                }
 
                if (!hasLayout) {
-                       cmd.errorMessage(string(N_("Layout ")) + cmd.argument +
+                       cur.errorMessage(string(N_("Layout ")) + cmd.argument +
                                N_(" not known"));
                        break;
                }
 
                bool change_layout = (current_layout != layout);
 
-               if (!change_layout && selection.set() &&
-                       selection.start.par() != selection.end.par())
+               if (!change_layout && cur.selection() &&
+                       cur.selBegin().par() != cur.selEnd().par())
                {
-                       ParagraphList::iterator spit = getPar(selection.start);
-                       ParagraphList::iterator epit = boost::next(getPar(selection.end));
+                       ParagraphList::iterator spit = getPar(cur.selBegin());
+                       ParagraphList::iterator epit = boost::next(getPar(cur.selEnd()));
                        while (spit != epit) {
                                if (spit->layout()->name() != current_layout) {
                                        change_layout = true;
@@ -1099,34 +1068,30 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
        }
 
        case LFUN_PASTESELECTION: {
-               // this was originally a beforeChange(bv->text), i.e
-               // the outermost LyXText!
-               bv->beforeChange(this);
+               cur.clearSelection();
                string const clip = bv->getClipboard();
                if (!clip.empty()) {
                        if (cmd.argument == "paragraph")
                                insertStringAsParagraphs(clip);
                        else
                                insertStringAsLines(clip);
-                       clearSelection();
                        bv->update();
                }
                break;
        }
 
        case LFUN_GOTOERROR:
-               gotoInset(InsetOld::ERROR_CODE, false);
+               gotoInset(InsetBase::ERROR_CODE, false);
                break;
 
        case LFUN_GOTONOTE:
-               gotoInset(InsetOld::NOTE_CODE, false);
+               gotoInset(InsetBase::NOTE_CODE, false);
                break;
 
-       case LFUN_REFERENCE_GOTO:
-       {
-               vector<InsetOld::Code> tmp;
-               tmp.push_back(InsetOld::LABEL_CODE);
-               tmp.push_back(InsetOld::REF_CODE);
+       case LFUN_REFERENCE_GOTO: {
+               vector<InsetOld_code> tmp;
+               tmp.push_back(InsetBase::LABEL_CODE);
+               tmp.push_back(InsetBase::REF_CODE);
                gotoInset(tmp, true);
                break;
        }
@@ -1134,7 +1099,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
        case LFUN_QUOTE: {
                replaceSelection(bv->getLyXText());
                ParagraphList::iterator pit = cursorPar();
-               lyx::pos_type pos = cursor.pos();
+               lyx::pos_type pos = cursor().pos();
                char c;
                if (!pos)
                        c = ' ';
@@ -1170,99 +1135,67 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                for (int i = 0; i < datetmp_len; i++)
                        insertChar(datetmp[i]);
 
-               selection.cursor = cursor;
-               moveCursorUpdate(bv, false);
+               cur.resetAnchor();
+               moveCursor(cur, false);
                break;
        }
 
        case LFUN_MOUSE_TRIPLE:
-               if (!bv->buffer())
-                       break;
-               if (!isInInset() && bv->theLockingInset())
-                       break;
-               if (cmd.button() == mouse_button::button1) {
+               if (bv->buffer() && cmd.button() == mouse_button::button1) {
+                       selection_possible = true;
                        cursorHome();
-                       selection.cursor = cursor;
+                       cur.resetAnchor();
                        cursorEnd();
-                       setSelection();
-                       bv->update();
-                       bv->haveSelection(selection.set());
+                       cur.setSelection();
+                       bv->haveSelection(cur.selection());
                }
                break;
 
        case LFUN_MOUSE_DOUBLE:
-               if (!bv->buffer())
-                       break;
-               if (!isInInset() && bv->theLockingInset())
-                       break;
-               if (cmd.button() == mouse_button::button1) {
+               if (bv->buffer() && cmd.button() == mouse_button::button1) {
+                       selection_possible = true;
                        selectWord(lyx::WHOLE_WORD_STRICT);
-                       bv->update();
-                       bv->haveSelection(selection.set());
+                       bv->haveSelection(cur.selection());
                }
                break;
 
-       case LFUN_MOUSE_MOTION:
-       {
+       case LFUN_MOUSE_MOTION: {
+#if 0
                // Only use motion with button 1
                //if (ev.button() != mouse_button::button1)
                //      return false;
+               // don't set anchor_
+               bv->cursor().cursor_ = cur.cursor_;
 
                if (!bv->buffer())
                        break;
-
-               // Check for inset locking
-               if (bv->theLockingInset()) {
-                       InsetOld * tli = bv->theLockingInset();
-                       LyXCursor cursor = bv->text->cursor;
-                       LyXFont font = bv->text->getFont(cursorPar(), cursor.pos());
-                       int width = tli->width();
-                       int inset_x = font.isVisibleRightToLeft()
-                               ? cursor.x() - width : cursor.x();
-                       int start_x = inset_x + tli->scroll();
-                       FuncRequest cmd1 = cmd;
-                       cmd1.x = cmd.x - start_x;
-                       cmd1.y = cmd.y - cursor.y() + bv->top_y();
-                       tli->dispatch(cmd1);
-                       break;
-               }
-
-               // The test for not selection possible is needed, that only motion
-               // events are used, where the bottom press event was on
-               //  the drawing area too
+               // The test for not selection possible is needed, that
+               // only motion events are used, where the bottom press
+               // event was on the drawing area too
                if (!selection_possible) {
-                       lyxerr[Debug::ACTION]
-                               << "BufferView::Pimpl::Dispatch: no selection possible\n";
+                       lyxerr[Debug::ACTION] << "BufferView::Pimpl::"
+                               "Dispatch: no selection possible\n";
                        break;
                }
+               RowList::iterator cursorrow = cursorRow();
+
+               setCursorFromCoordinates(cmd.x, cmd.y);
 
-               RowList::iterator cursorrow = bv->text->cursorRow();
-               bv->text->setCursorFromCoordinates(cmd.x, cmd.y + bv->top_y());
-       #if 0
-               // sorry for this but I have a strange error that the y value jumps at
-               // a certain point. This seems like an error in my xforms library or
-               // in some other local environment, but I would like to leave this here
-               // for the moment until I can remove this (Jug 20020418)
-               if (y_before < bv->text->cursor.y())
-                       lyxerr << y_before << ':'
-                              << bv->text->cursor.y() << endl;
-       #endif
                // This is to allow jumping over large insets
-               if (cursorrow == bv->text->cursorRow()) {
-                       if (cmd.y >= bv->workHeight())
-                               bv->text->cursorDown(false);
-                       else if (cmd.y < 0)
-                               bv->text->cursorUp(false);
+               // FIXME: shouldn't be top-text-specific
+               if (cursorrow == cursorRow() && !in_inset_) {
+                       if (cmd.y - bv->top_y() >= bv->workHeight())
+                               cursorDown(true);
+                       else if (cmd.y - bv->top_y() < 0)
+                               cursorUp(true);
                }
-
-               bv->text->setSelection();
-               bv->update();
+               cur.setSelection();
+#endif
                break;
        }
 
        // Single-click on work area
-       case LFUN_MOUSE_PRESS:
-       {
+       case LFUN_MOUSE_PRESS: {
                if (!bv->buffer())
                        break;
 
@@ -1279,57 +1212,20 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                        break;
                }
 
-               int x = cmd.x;
-               int y = cmd.y;
-               InsetOld * inset_hit = bv->text->checkInsetHit(x, y);
-
                // Middle button press pastes if we have a selection
                // We do this here as if the selection was inside an inset
                // it could get cleared on the unlocking of the inset so
                // we have to check this first
                bool paste_internally = false;
-               if (cmd.button() == mouse_button::button2 && selection.set()) {
+               if (cmd.button() == mouse_button::button2 && cur.selection()) {
                        bv->owner()->dispatch(FuncRequest(LFUN_COPY));
                        paste_internally = true;
                }
 
-               int const screen_first = bv->top_y();
-
-               if (bv->theLockingInset()) {
-                       // We are in inset locking mode
-
-                       // Check whether the inset was hit. If not reset mode,
-                       // otherwise give the event to the inset
-                       if (inset_hit == bv->theLockingInset()) {
-                               FuncRequest cmd1(bv, LFUN_MOUSE_PRESS, x, y, cmd.button());
-                               bv->theLockingInset()->dispatch(cmd1);
-                               break;
-                       }
-                       bv->unlockInset(bv->theLockingInset());
-               }
-
-               if (!inset_hit)
-                       selection_possible = true;
+               selection_possible = true;
 
                // Clear the selection
-               bv->text->clearSelection();
-               bv->update();
-               bv->updateScrollbar();
-
-               // Single left click in math inset?
-               if (isHighlyEditableInset(inset_hit)) {
-                       // Highly editable inset, like math
-                       UpdatableInset * inset = static_cast<UpdatableInset *>(inset_hit);
-                       selection_possible = false;
-                       bv->owner()->message(inset->editMessage());
-                       // We just have to lock the inset before calling a PressEvent on it!
-                       if (!bv->lockInset(inset))
-                               lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
-                       FuncRequest cmd1(bv, LFUN_MOUSE_PRESS, x, y, cmd.button());
-                       inset->dispatch(cmd1);
-                       break;
-               }
-               // I'm not sure we should continue here if we hit an inset (Jug20020403)
+               cur.clearSelection();
 
                // Right click on a footnote flag opens float menu
                if (cmd.button() == mouse_button::button3) {
@@ -1337,11 +1233,13 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                        break;
                }
 
-               if (!inset_hit) // otherwise it was already set in checkInsetHit(...)
-                       bv->text->setCursorFromCoordinates(x, y + screen_first);
+               setCursorFromCoordinates(cur.current(), cmd.x, cmd.y);
+               cur.resetAnchor();
                finishUndo();
-               bv->text->selection.cursor = bv->text->cursor;
-               bv->text->cursor.x_fix(bv->text->cursor.x());
+               cur.x_target() = cursorX(cur.current());
+
+               // set cursor and anchor to this position
+               bv->cursor() = cur;
 
                if (bv->fitCursor())
                        selection_possible = false;
@@ -1359,33 +1257,14 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
        }
 
-       case LFUN_MOUSE_RELEASE:
-       {
-               // do nothing if we used the mouse wheel
+       case LFUN_MOUSE_RELEASE: {
                if (!bv->buffer())
                        break;
 
+               // do nothing if we used the mouse wheel
                if (cmd.button() == mouse_button::button4
                 || cmd.button() == mouse_button::button5)
-                       break;
-
-               // If we hit an inset, we have the inset coordinates in these
-               // and inset_hit points to the inset.  If we do not hit an
-               // inset, inset_hit is 0, and inset_x == x, inset_y == y.
-               int x = cmd.x;
-               int y = cmd.y;
-               InsetOld * inset_hit = bv->text->checkInsetHit(x, y);
-
-               if (bv->theLockingInset()) {
-                       // We are in inset locking mode.
-
-                       // LyX does a kind of work-area grabbing for insets.
-                       // Only a ButtonPress FuncRequest outside the inset will
-                       // force a insetUnlock.
-                       FuncRequest cmd1(bv, LFUN_MOUSE_RELEASE, x, y, cmd.button());
-                       bv->theLockingInset()->dispatch(cmd1);
-                       break;
-               }
+                       return DispatchResult(true, false);
 
                selection_possible = false;
 
@@ -1394,55 +1273,12 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
 
                // finish selection
                if (cmd.button() == mouse_button::button1)
-                       bv->haveSelection(selection.set());
+                       bv->haveSelection(cur.selection());
 
                bv->switchKeyMap();
                bv->owner()->view_state_changed();
                bv->owner()->updateMenubar();
                bv->owner()->updateToolbar();
-
-               // Did we hit an editable inset?
-               if (inset_hit) {
-                       selection_possible = false;
-
-                       // if we reach this point with a selection, it
-                       // must mean we are currently selecting.
-                       // But we don't want to open the inset
-                       // because that is annoying for the user.
-                       // So just pretend we didn't hit it.
-                       // this is OK because a "kosher" ButtonRelease
-                       // will follow a ButtonPress that clears
-                       // the selection.
-                       // Note this also fixes selection drawing
-                       // problems if we end up opening an inset
-                       if (selection.set())
-                               break;
-
-                       // CHECK fix this proper in 0.13
-                       // well, maybe 13.0 !!!!!!!!!
-
-                       // Following a ref shouldn't issue
-                       // a push on the undo-stack
-                       // anylonger, now that we have
-                       // keybindings for following
-                       // references and returning from
-                       // references.  IMHO though, it
-                       // should be the inset's own business
-                       // to push or not push on the undo
-                       // stack. They don't *have* to
-                       // alter the document...
-                       // (Joacim)
-                       // ...or maybe the recordUndo()
-                       // below isn't necessary at all anylonger?
-                       if (inset_hit->lyxCode() == InsetOld::REF_CODE)
-                               recUndo(cursor.par());
-
-                       bv->owner()->message(inset_hit->editMessage());
-
-                       FuncRequest cmd1(bv, LFUN_MOUSE_RELEASE, x, y, cmd.button());
-                       inset_hit->dispatch(cmd1);
-               }
-
                break;
        }
 
@@ -1457,12 +1293,12 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                // true (on).
 
                if (lyxrc.auto_region_delete) {
-                       if (selection.set())
+                       if (cur.selection())
                                cutSelection(false, false);
                        bv->haveSelection(false);
                }
 
-               bv->beforeChange(this);
+               cur.clearSelection();
                LyXFont const old_font = real_current_font;
 
                string::const_iterator cit = cmd.argument.begin();
@@ -1471,8 +1307,8 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                        bv->owner()->getIntl().getTransManager().
                                TranslateAndInsert(*cit, this);
 
-               selection.cursor = cursor;
-               moveCursorUpdate(bv, false);
+               cur.resetAnchor();
+               moveCursor(cur, false);
 
                // real_current_font.number can change so we need to
                // update the minibuffer
@@ -1482,20 +1318,27 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
                break;
        }
 
-       case LFUN_HTMLURL: {
-               InsetCommandParams p("htmlurl");
+       case LFUN_URL: {
+               InsetCommandParams p("url");
                string const data = InsetCommandMailer::params2string("url", p);
                bv->owner()->getDialogs().show("url", data, 0);
                break;
        }
 
-       case LFUN_URL: {
-               InsetCommandParams p("url");
+       case LFUN_HTMLURL: {
+               InsetCommandParams p("htmlurl");
                string const data = InsetCommandMailer::params2string("url", p);
                bv->owner()->getDialogs().show("url", data, 0);
                break;
        }
 
+       case LFUN_INSERT_LABEL: {
+               InsetCommandParams p("label");
+               string const data = InsetCommandMailer::params2string("label", p);
+               bv->owner()->getDialogs().show("label", data, 0);
+               break;
+       }
+
 
 #if 0
        case LFUN_INSET_LIST:
@@ -1503,6 +1346,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
        case LFUN_INSET_CAPTION:
 #endif
        case LFUN_INSERT_NOTE:
+       case LFUN_INSERT_CHARSTYLE:
        case LFUN_INSERT_BOX:
        case LFUN_INSERT_BRANCH:
        case LFUN_INSERT_BIBITEM:
@@ -1510,7 +1354,6 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
        case LFUN_INSET_FLOAT:
        case LFUN_INSET_FOOTNOTE:
        case LFUN_INSET_MARGINAL:
-       case LFUN_INSET_MINIPAGE:
        case LFUN_INSET_OPTARG:
        case LFUN_INSET_WIDE_FLOAT:
        case LFUN_INSET_WRAP:
@@ -1518,37 +1361,141 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd)
        case LFUN_ENVIRONMENT_INSERT:
                // Open the inset, and move the current selection
                // inside it.
-               doInsertInset(this, cmd, true, true);
+               doInsertInset(bv, cmd, true, true);
                break;
 
        case LFUN_INDEX_INSERT:
                // Just open the inset
-               doInsertInset(this, cmd, true, false);
+               doInsertInset(bv, cmd, true, false);
                break;
 
        case LFUN_INDEX_PRINT:
        case LFUN_TOC_INSERT:
        case LFUN_HFILL:
+       case LFUN_INSERT_LINE:
+       case LFUN_INSERT_PAGEBREAK:
                // do nothing fancy
-               doInsertInset(this, cmd, false, false);
+               doInsertInset(bv, cmd, false, false);
                break;
 
        case LFUN_DEPTH_MIN:
-               bv_funcs::changeDepth(bv, this, bv_funcs::DEC_DEPTH, false);
-               clearSelection();
+               bv_funcs::changeDepth(bv, this, bv_funcs::DEC_DEPTH);
                bv->update();
                break;
 
        case LFUN_DEPTH_PLUS:
-               clearSelection();
-               bv_funcs::changeDepth(bv, this, bv_funcs::INC_DEPTH, false);
-               clearSelection();
+               bv_funcs::changeDepth(bv, this, bv_funcs::INC_DEPTH);
                bv->update();
                break;
 
+       case LFUN_MATH_DELIM:
+       case LFUN_MATH_DISPLAY:
+       case LFUN_INSERT_MATH:
+       case LFUN_MATH_LIMITS:
+       case LFUN_MATH_MACRO:
+       case LFUN_MATH_MUTATE:
+       case LFUN_MATH_SPACE:
+       case LFUN_MATH_IMPORT_SELECTION:
+       case LFUN_MATH_MODE:
+       case LFUN_MATH_NONUMBER:
+       case LFUN_MATH_NUMBER:
+       case LFUN_MATH_EXTERN:
+       case LFUN_MATH_SIZE:
+               mathDispatch(cur, cmd);
+               break;
+
+       case LFUN_EMPH:
+               emph(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_BOLD:
+               bold(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_NOUN:
+               noun(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_CODE:
+               code(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_SANS:
+               sans(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_ROMAN:
+               roman(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_DEFAULT:
+               styleReset(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_UNDERLINE:
+               underline(bv, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_FONT_SIZE:
+               fontSize(bv, cmd.argument, this);
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_LANGUAGE:
+               lang(bv, cmd.argument, this);
+               bv->switchKeyMap();
+               bv->owner()->view_state_changed();
+               break;
+
+       case LFUN_FREEFONT_APPLY:
+               apply_freefont(bv, this);
+               break;
+
+       case LFUN_FREEFONT_UPDATE:
+               update_and_apply_freefont(bv, this, cmd.argument);
+               break;
+
+       case LFUN_FINISHED_LEFT:
+               lyxerr << "handle LFUN_FINISHED_LEFT" << endl;
+               cur.pop(cur.currentDepth());
+               cur.bv().cursor() = cur;
+               if (rtl())
+                       cursorLeft(true);
+               break;
+
+       case LFUN_FINISHED_RIGHT:
+               lyxerr << "handle LFUN_FINISHED_RIGHT" << endl;
+               cur.pop(cur.currentDepth());
+               cur.bv().cursor() = cur;
+               if (!rtl())
+                       cursorRight(true);
+               break;
+
+       case LFUN_FINISHED_UP:
+               lyxerr << "handle LFUN_FINISHED_UP" << endl;
+               cur.pop(cur.currentDepth());
+               cur.bv().cursor() = cur;
+               cursorUp(true);
+               break;
+
+       case LFUN_FINISHED_DOWN:
+               lyxerr << "handle LFUN_FINISHED_DOWN" << endl;
+               cur.pop(cur.currentDepth());
+               cur.bv().cursor() = cur;
+               cursorDown(true);
+               break;
+
        default:
-               return UNDISPATCHED;
+               return DispatchResult(false);
        }
 
-       return DISPATCHED;
+       return DispatchResult(true, true);
 }