]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
english_language was not used at all.
[lyx.git] / src / Text3.cpp
index d978e3f6e72e58189422641eb0b552b0c7cceea5..3dd736b9dd698d399466b69d843bb7d5568cb530 100644 (file)
@@ -57,6 +57,8 @@
 #include "insets/InsetSpecialChar.h"
 #include "insets/InsetText.h"
 #include "insets/InsetInfo.h"
+#include "insets/InsetGraphics.h"
+#include "insets/InsetGraphicsParams.h"
 
 #include "support/convert.h"
 #include "support/debug.h"
@@ -131,7 +133,9 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
                const int old_pos = cur.pos();
 #endif
                cur.insert(new InsetMathHull(hullSimple));
-               BOOST_ASSERT(old_pos == cur.pos());
+#ifdef ENABLE_ASSERTIONS
+               LASSERT(old_pos == cur.pos(), /**/);
+#endif
                cur.nextInset()->edit(cur, true);
                // don't do that also for LFUN_MATH_MODE
                // unless you want end up with always changing
@@ -154,7 +158,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
                {
                        InsetMathHull * formula = new InsetMathHull;
                        istringstream is(to_utf8(sel));
-                       Lexer lex(0, 0);
+                       Lexer lex;
                        lex.setStream(is);
                        formula->read(lex);
                        if (formula->getType() == hullNone)
@@ -268,7 +272,7 @@ static void outline(OutlineOp mode, Cursor & cur)
 
        DocumentClass const & tc = buf.params().documentClass();
 
-       int const thistoclevel = start->layout()->toclevel;
+       int const thistoclevel = start->layout().toclevel;
        int toclevel;
 
        // Move out (down) from this section header
@@ -276,7 +280,7 @@ static void outline(OutlineOp mode, Cursor & cur)
                ++finish;
        // Seek the one (on same level) below
        for (; finish != end; ++finish) {
-               toclevel = finish->layout()->toclevel;
+               toclevel = finish->layout().toclevel;
                if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel) {
                        break;
                }
@@ -284,6 +288,9 @@ static void outline(OutlineOp mode, Cursor & cur)
 
        switch (mode) {
                case OutlineUp: {
+                       if (start == pars.begin())
+                               // Nothing to move.
+                               return;
                        ParagraphList::iterator dest = start;
                        // Move out (up) from this header
                        if (dest == bgn)
@@ -291,7 +298,7 @@ static void outline(OutlineOp mode, Cursor & cur)
                        // Search previous same-level header above
                        do {
                                --dest;
-                               toclevel = dest->layout()->toclevel;
+                               toclevel = dest->layout().toclevel;
                        } while(dest != bgn
                                && (toclevel == Layout::NOT_IN_TOC
                                    || toclevel > thistoclevel));
@@ -309,7 +316,19 @@ static void outline(OutlineOp mode, Cursor & cur)
                        return;
                }
                case OutlineDown: {
-                       ParagraphList::iterator dest = finish;
+                       if (finish == end)
+                               // Nothing to move.
+                               return;
+                       // Go one down from *this* header:
+                       ParagraphList::iterator dest = boost::next(finish, 1);
+                       // Go further down to find header to insert in front of:
+                       for (; dest != end; ++dest) {
+                               toclevel = dest->layout().toclevel;
+                               if (toclevel != Layout::NOT_IN_TOC
+                                   && toclevel <= thistoclevel) {
+                                       break;
+                               }
+                       }
                        // One such was found:
                        pit_type newpit = distance(bgn, dest);
                        pit_type const len = distance(start, finish);
@@ -324,14 +343,15 @@ static void outline(OutlineOp mode, Cursor & cur)
                        pit_type const len = distance(start, finish);
                        buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, pit + len - 1);
                        for (; start != finish; ++start) {
-                               toclevel = start->layout()->toclevel;
+                               toclevel = start->layout().toclevel;
                                if (toclevel == Layout::NOT_IN_TOC)
                                        continue;
-                               for (size_t i = 0; i != tc.layoutCount(); ++i) {
-                                       LayoutPtr const & lt = tc.layout(i);
-                                       if (lt->toclevel == toclevel + 1 &&
-                                           start->layout()->labeltype == lt->labeltype) {
-                                               start->setLayout(lt);
+                               DocumentClass::const_iterator lit = tc.begin();
+                               DocumentClass::const_iterator len = tc.end();
+                               for (; lit != len; ++lit) {
+                                       if (lit->toclevel == toclevel + 1 &&
+                                           start->layout().labeltype == lit->labeltype) {
+                                               start->setLayout(*lit);
                                                break;
                                        }
                                }
@@ -342,14 +362,15 @@ static void outline(OutlineOp mode, Cursor & cur)
                        pit_type const len = distance(start, finish);
                        buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, pit + len - 1);
                        for (; start != finish; ++start) {
-                               toclevel = start->layout()->toclevel;
+                               toclevel = start->layout().toclevel;
                                if (toclevel == Layout::NOT_IN_TOC)
                                        continue;
-                               for (size_t i = 0; i != tc.layoutCount(); ++i) {
-                                       LayoutPtr const & lt = tc.layout(i);
-                                       if (lt->toclevel == toclevel - 1 &&
-                                               start->layout()->labeltype == lt->labeltype) {
-                                                       start->setLayout(lt);
+                               DocumentClass::const_iterator lit = tc.begin();
+                               DocumentClass::const_iterator len = tc.end();
+                               for (; lit != len; ++lit) {
+                                       if (lit->toclevel == toclevel - 1 &&
+                                               start->layout().labeltype == lit->labeltype) {
+                                                       start->setLayout(*lit);
                                                        break;
                                        }
                                }
@@ -388,7 +409,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // at the end?
        cur.noUpdate();
 
-       BOOST_ASSERT(cur.text() == this);
+       LASSERT(cur.text() == this, /**/);
        CursorSlice oldTopSlice = cur.top();
        bool oldBoundary = cur.boundary();
        bool sel = cur.selection();
@@ -600,25 +621,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                needsUpdate |= cursorDownParagraph(cur);
                break;
 
-       case LFUN_SCREEN_UP_SELECT:
-               needsUpdate |= cur.selHandle(true);
-               if (cur.pit() == 0 && cur.textRow().pos() == 0)
-                       cur.undispatched();
-               else {
-                       tm.cursorPrevious(cur);
-               }
-               break;
-
-       case LFUN_SCREEN_DOWN_SELECT:
-               needsUpdate |= cur.selHandle(true);
-               if (cur.pit() == cur.lastpit()
-                         && cur.textRow().endpos() == cur.lastpos())
-                       cur.undispatched();
-               else {
-                       tm.cursorNext(cur);
-               }
-               break;
-
        case LFUN_LINE_BEGIN:
        case LFUN_LINE_BEGIN_SELECT:
                needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_BEGIN_SELECT);
@@ -633,16 +635,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_WORD_RIGHT:
        case LFUN_WORD_RIGHT_SELECT:
-               //FIXME: for visual cursor mode, really move right
-               if (reverseDirectionNeeded(cur)) {
-                       cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ?
-                                       LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD;
+               if (lyxrc.visual_cursor) {
+                       needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_RIGHT_SELECT);
+                       needsUpdate |= cursorVisRightOneWord(cur);
+                       if (!needsUpdate && oldTopSlice == cur.top()
+                                       && cur.boundary() == oldBoundary) {
+                               cur.undispatched();
+                               cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       }
                } else {
-                       cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ?
-                                       LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD;
+                       if (reverseDirectionNeeded(cur)) {
+                               cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ?
+                                               LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD;
+                       } else {
+                               cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ?
+                                               LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD;
+                       }
+                       dispatch(cur, cmd);
+                       return;
                }
-               dispatch(cur, cmd);
-               return;
+               break;
 
        case LFUN_WORD_FORWARD:
        case LFUN_WORD_FORWARD_SELECT:
@@ -652,16 +664,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_WORD_LEFT:
        case LFUN_WORD_LEFT_SELECT:
-               //FIXME: for visual cursor mode, really move left
-               if (reverseDirectionNeeded(cur)) {
-                       cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ?
-                                       LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD;
+               if (lyxrc.visual_cursor) {
+                       needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_LEFT_SELECT);
+                       needsUpdate |= cursorVisLeftOneWord(cur);
+                       if (!needsUpdate && oldTopSlice == cur.top()
+                                       && cur.boundary() == oldBoundary) {
+                               cur.undispatched();
+                               cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       }
                } else {
-                       cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ?
-                                       LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD;
+                       if (reverseDirectionNeeded(cur)) {
+                               cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ?
+                                               LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD;
+                       } else {
+                               cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ?
+                                               LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD;
+                       }
+                       dispatch(cur, cmd);
+                       return;
                }
-               dispatch(cur, cmd);
-               return;
+               break;
 
        case LFUN_WORD_BACKWARD:
        case LFUN_WORD_BACKWARD_SELECT:
@@ -675,36 +697,24 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_NEW_LINE: {
-               // Not allowed by LaTeX (labels or empty par)
-               if (cur.pos() > cur.paragraph().beginOfBody()) {
-                       // this avoids a double undo
-                       // FIXME: should not be needed, ideally
-                       if (!cur.selection())
-                               cur.recordUndo();
-                       cap::replaceSelection(cur);
-                       cur.insert(new InsetNewline);
-                       cur.posForward();
-                       moveCursor(cur, false);
-               }
+       case LFUN_NEWLINE_INSERT: {
+               InsetNewlineParams inp;
+               docstring arg = cmd.argument();
+               // this avoids a double undo
+               // FIXME: should not be needed, ideally
+               if (!cur.selection())
+                       cur.recordUndo();
+               cap::replaceSelection(cur);
+               if (arg == "linebreak")
+                       inp.kind = InsetNewlineParams::LINEBREAK;
+               else
+                       inp.kind = InsetNewlineParams::NEWLINE;
+               cur.insert(new InsetNewline(inp));
+               cur.posForward();
+               moveCursor(cur, false);
                break;
        }
        
-       case LFUN_LINE_BREAK: {
-               // Not allowed by LaTeX (labels or empty par)
-               if (cur.pos() > cur.paragraph().beginOfBody()) {
-                       // this avoids a double undo
-                       // FIXME: should not be needed, ideally
-                       if (!cur.selection())
-                               cur.recordUndo();
-                       cap::replaceSelection(cur);
-                       cur.insert(new InsetLinebreak);
-                       cur.posForward();
-                       moveCursor(cur, false);
-               }
-               break;
-       }
-
        case LFUN_CHAR_DELETE_FORWARD:
                if (!cur.selection()) {
                        if (cur.pos() == cur.paragraph().size())
@@ -842,7 +852,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        /*
                        Paragraph & par = pars_[cur.pit()];
                        if (inset->lyxCode() == LABEL_CODE
-                               && par.layout()->labeltype == LABEL_COUNTER) {
+                               && par.layout().labeltype == LABEL_COUNTER) {
                                // Go to the end of the paragraph
                                // Warning: Because of Change-Tracking, the last
                                // position is 'size()' and not 'size()-1':
@@ -864,12 +874,50 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                needsUpdate |= dissolveInset(cur);
                break;
 
-       case LFUN_INSET_SETTINGS:
-               cur.inset().showInsetDialog(bv);
+       case LFUN_INSET_SETTINGS: {
+               Inset & inset = cur.inset();
+               if (cmd.getArg(0) == insetName(inset.lyxCode())) {
+                       // This inset dialog has been explicitely requested.
+                       inset.showInsetDialog(bv);
+                       break;
+               }
+               // else, if there is an inset at the cursor, access this
+               Inset * next_inset = cur.nextInset();
+               if (next_inset) {
+                       next_inset->showInsetDialog(bv);
+                       break;
+               }
+               // if not then access the underlying inset.
+               inset.showInsetDialog(bv);
                break;
+       }
+
+       case LFUN_SET_GRAPHICS_GROUP: {
+               Inset * instmp = &cur.inset();
+               if (instmp->lyxCode() != GRAPHICS_CODE) instmp = cur.nextInset();
+               if (!instmp || instmp->lyxCode() != GRAPHICS_CODE) break;
+
+               cur.recordUndoFullDocument();
+               Inset & inset = *instmp;
+               InsetGraphics & ins = static_cast<InsetGraphics &>(inset);
+
+               string id = to_utf8(cmd.argument());
+               string grp = InsetGraphics::getGroupParams(bv->buffer(), id);
+               InsetGraphicsParams tmp, inspar = ins.getParams();
+
+               if (id.empty())
+                       inspar.groupId = to_utf8(cmd.argument());
+               else {
+                       InsetGraphics::string2params(grp, bv->buffer(), tmp);
+                       tmp.filename = inspar.filename;
+                       inspar = tmp;
+               }
+
+               ins.setParams(inspar);
+       }
 
        case LFUN_SPACE_INSERT:
-               if (cur.paragraph().layout()->free_spacing)
+               if (cur.paragraph().layout().free_spacing)
                        insertChar(cur, ' ');
                else {
                        doInsertInset(cur, this, cmd, false, false);
@@ -945,7 +993,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        else if (arg == "linkback")
                                type = Clipboard::LinkBackGraphicsType;
                        else
-                               BOOST_ASSERT(false);
+                               LASSERT(false, /**/);
 
                        pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"), type);
                }
@@ -985,17 +1033,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_SERVER_GET_FONT:
-               if (cur.current_font.fontInfo().shape() == ITALIC_SHAPE)
-                       cur.message(from_ascii("E"));
-               else if (cur.current_font.fontInfo().shape() == SMALLCAPS_SHAPE)
-                       cur.message(from_ascii("N"));
-               else
-                       cur.message(from_ascii("0"));
-               break;
-
        case LFUN_SERVER_GET_LAYOUT:
-               cur.message(cur.paragraph().layout()->name());
+               cur.message(cur.paragraph().layout().name());
                break;
 
        case LFUN_LAYOUT: {
@@ -1003,7 +1042,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                LYXERR(Debug::INFO, "LFUN_LAYOUT: (arg) " << to_utf8(layout));
 
                Paragraph const & para = cur.paragraph();
-               docstring const old_layout = para.layout()->name();
+               docstring const old_layout = para.layout().name();
                DocumentClass const & tclass = bv->buffer().params().documentClass();
 
                if (layout.empty())
@@ -1026,7 +1065,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
                // If the entry is obsolete, use the new one instead.
                if (hasLayout) {
-                       docstring const & obs = tclass[layout]->obsoleted_by();
+                       docstring const & obs = tclass[layout].obsoleted_by();
                        if (!obs.empty())
                                layout = obs;
                }
@@ -1045,7 +1084,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        pit_type spit = cur.selBegin().pit();
                        pit_type epit = cur.selEnd().pit() + 1;
                        while (spit != epit) {
-                               if (pars_[spit].layout()->name() != old_layout) {
+                               if (pars_[spit].layout().name() != old_layout) {
                                        change_layout = true;
                                        break;
                                }
@@ -1090,8 +1129,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                Paragraph & par = cur.paragraph();
                pos_type pos = cur.pos();
                BufferParams const & bufparams = bv->buffer().params();
-               LayoutPtr const & style = par.layout();
-               if (!style->pass_thru
+               Layout const & style = par.layout();
+               if (!style.pass_thru
                    && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") {
                        // this avoids a double undo
                        // FIXME: should not be needed, ideally
@@ -1107,14 +1146,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        else
                                c = par.getChar(pos - 1);
                        string arg = to_utf8(cmd.argument());
-                       if (arg == "single")
-                               cur.insert(new InsetQuotes(c,
-                                   bufparams.quotes_language,
-                                   InsetQuotes::SingleQ));
-                       else
-                               cur.insert(new InsetQuotes(c,
-                                   bufparams.quotes_language,
-                                   InsetQuotes::DoubleQ));
+                       cur.insert(new InsetQuotes(c, bufparams.quotes_language,
+                               (arg == "single") ? InsetQuotes::SingleQuotes
+                                       : InsetQuotes::DoubleQuotes));
                        cur.posForward();
                }
                else
@@ -1148,51 +1182,65 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
        // Single-click on work area
-       case LFUN_MOUSE_PRESS: {
-               // Right click on a footnote flag opens float menu
-               // FIXME: Why should we clear the selection in this case?
-               if (cmd.button() == mouse_button::button3)
-                       cur.clearSelection();
-
-               bool do_selection = cmd.button() == mouse_button::button1
-                       && cmd.argument() == "region-select";
-               // Set the cursor
-               bool update = bv->mouseSetCursor(cur, do_selection);
-
-               // Insert primary selection with middle mouse
-               // if there is a local selection in the current buffer,
-               // insert this
-               if (cmd.button() == mouse_button::button2) {
-                       if (cap::selection()) {
-                               // Copy the selection buffer to the clipboard
-                               // stack, because we want it to appear in the
-                               // "Edit->Paste recent" menu.
-                               cap::copySelectionToStack();
-
-                               cap::pasteSelection(bv->cursor(), 
-                                                   bv->buffer().errorList("Paste"));
-                               bv->buffer().errors("Paste");
-                               bv->buffer().markDirty();
-                               bv->cursor().finishUndo();
-                       } else {
-                               lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"));
+       case LFUN_MOUSE_PRESS:
+               // We are not marking a selection with the keyboard in any case.
+               cur.bv().cursor().mark() = false;
+               switch (cmd.button()) {
+               case mouse_button::button1:
+                       // Set the cursor
+                       if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select"))
+                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       break;                  
+
+               case mouse_button::button2:
+                       // Middle mouse pasting.
+                       if (!cap::selection()) {                        
+                               // There is no local selection in the current buffer, so try to
+                               // paste primary selection instead.
+                               lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE,
+                                       "paragraph"));
+                               // Nothing else to do.
+                               cur.noUpdate();
+                               return;
                        }
-               }
-
-               // we have to update after dEPM triggered
-               if (!update && cmd.button() == mouse_button::button1) {
-                       needsUpdate = false;
-                       cur.noUpdate();
-               }
+                       // Copy the selection buffer to the clipboard stack, because we want it
+                       // to appear in the "Edit->Paste recent" menu.
+                       cap::copySelectionToStack();
+                       cap::pasteSelection(bv->cursor(), bv->buffer().errorList("Paste"));
+                       cur.updateFlags(Update::Force | Update::FitCursor);
+                       bv->buffer().errors("Paste");
+                       bv->buffer().markDirty();
+                       bv->cursor().finishUndo();
+                       break;
 
+               case mouse_button::button3:
+                       if (cur.selection()) {
+                               DocIterator const selbeg = cur.selectionBegin();
+                               DocIterator const selend = cur.selectionEnd();
+                               Cursor tmpcur = cur;
+                               tm.setCursorFromCoordinates(tmpcur, cmd.x, cmd.y);
+                               // Don't do anything if we right-click a selection, a selection
+                               // context menu should popup instead.
+                               if (tmpcur < selbeg || tmpcur >= selend) {
+                                       cur.noUpdate();
+                                       return;
+                               }
+                       }
+                       if (!bv->mouseSetCursor(cur, false)) {
+                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                               break;                  
+                       }
+               default:
+                       break;
+               } // switch (cmd.button())
                break;
-       }
 
        case LFUN_MOUSE_MOTION: {
-               // Only use motion with button 1
-               //if (cmd.button() != mouse_button::button1)
-               //      return false;
-
+               // Mouse motion with right or middle mouse do nothing for now.
+               if (cmd.button() != mouse_button::button1) {
+                       cur.noUpdate();
+                       return;
+               }
                // ignore motions deeper nested than the real anchor
                Cursor & bvcur = cur.bv().cursor();
                if (!bvcur.anchor_.hasPart(cur)) {
@@ -1217,42 +1265,52 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        else if (cmd.y < 0)
                                lyx::dispatch(FuncRequest(LFUN_UP_SELECT));
                }
-
-               if (cur.top() == old)
-                       cur.noUpdate();
-               else {
-                       // FIXME: This is brute force! But without it the selected
-                       // area is not corrected updated while moving the mouse.
-                       cur.updateFlags(Update::Force | Update::FitCursor);
-                       // don't set anchor_
-                       bvcur.setCursor(cur);
-                       bvcur.selection() = true;
-                       //lyxerr << "MOTION: " << bv->cursor() << endl;
+               // We continue with our existing selection or start a new one, so don't
+               // reset the anchor.
+               bvcur.setCursor(cur);
+               bvcur.selection() = true;
+               if (cur.top() == old) {
+                       // We didn't move one iota, so no need to update the screen.
+                       cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       //cur.noUpdate();
+                       return;
                }
                break;
        }
 
-       case LFUN_MOUSE_RELEASE: {
-               if (cmd.button() == mouse_button::button2)
-                       break;
-
-               if (cmd.button() == mouse_button::button1) {
-                       // if there is new selection, update persistent
-                       // selection, otherwise, single click does not
-                       // clear persistent selection buffer
+       case LFUN_MOUSE_RELEASE:
+               switch (cmd.button()) {
+               case mouse_button::button1:
+                       // Cursor was set at LFUN_MOUSE_PRESS or LFUN_MOUSE_MOTION time.
+                       // If there is a new selection, update persistent selection;
+                       // otherwise, single click does not clear persistent selection
+                       // buffer.
                        if (cur.selection()) {
-                               // finish selection
-                               // if double click, cur is moved to the end of word by selectWord
-                               // but bvcur is current mouse position
-                               Cursor & bvcur = cur.bv().cursor();
-                               bvcur.selection() = true;
+                               // Finish selection.
+                               // If double click, cur is moved to the end of word by selectWord
+                               // but bvcur is current mouse position.
+                               cur.bv().cursor().selection() = true;
                        }
-                       needsUpdate = false;
+                       // FIXME: We could try to handle drag and drop of selection here.
                        cur.noUpdate();
-               }
+                       return;
+
+               case mouse_button::button2:
+                       // Middle mouse pasting is handled at mouse press time,
+                       // see LFUN_MOUSE_PRESS.
+                       cur.noUpdate();
+                       return;
+
+               case mouse_button::button3:
+                       // Cursor was set at LFUN_MOUSE_PRESS time.
+                       // FIXME: If there is a selection we could try to handle a special
+                       // drag & drop context menu.
+                       cur.noUpdate();
+                       return;
+
+               } // switch (cmd.button())
 
                break;
-       }
 
        case LFUN_SELF_INSERT: {
                if (cmd.argument().empty())
@@ -1289,7 +1347,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                p["target"] = (cmd.argument().empty()) ?
                        content : cmd.argument();
-               string const data = InsetCommandMailer::params2string("href", p);
+               string const data = InsetCommand::params2string("href", p);
                if (p["target"].empty()) {
                        bv->showDialog("href", data);
                } else {
@@ -1305,7 +1363,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                p["name"] = (cmd.argument().empty()) ?
                        cur.getPossibleLabel() :
                        cmd.argument();
-               string const data = InsetCommandMailer::params2string("label", p);
+               string const data = InsetCommand::params2string("label", p);
 
                if (cmd.argument().empty()) {
                        bv->showDialog("label", data);
@@ -1335,7 +1393,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 #if 0
        case LFUN_LIST_INSERT:
-       case LFUN_THEOREM_INSERT:
 #endif
        case LFUN_CAPTION_INSERT:
        case LFUN_FOOTNOTE_INSERT:
@@ -1431,12 +1488,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_INDEX_PRINT:
        case LFUN_NOMENCL_PRINT:
        case LFUN_TOC_INSERT:
-       case LFUN_HFILL_INSERT:
        case LFUN_LINE_INSERT:
        case LFUN_NEWPAGE_INSERT:
-       case LFUN_PAGEBREAK_INSERT:
-       case LFUN_CLEARPAGE_INSERT:
-       case LFUN_CLEARDOUBLEPAGE_INSERT:
                // do nothing fancy
                doInsertInset(cur, this, cmd, false, false);
                cur.posForward();
@@ -1494,7 +1547,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                cap::replaceSelection(cur);
                cur.insert(new InsetMathHull(hullSimple));
                checkAndActivateInset(cur, true);
-               BOOST_ASSERT(cur.inMathed());
+               LASSERT(cur.inMathed(), /**/);
                cur.dispatch(cmd);
                break;
        }
@@ -1680,11 +1733,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                breakParagraph(cur);
                        }
 
-                       //FIXME Check if this should be emptyLayout()
-                       setLayout(cur, tclass.defaultLayoutName());
+                       docstring const laystr = cur.inset().useEmptyLayout() ?
+                               tclass.emptyLayoutName() :
+                               tclass.defaultLayoutName();
+                       setLayout(cur, laystr);
                        ParagraphParameters p;
                        setParagraphs(cur, p);
-                       insertInset(cur, new InsetFloatList(to_utf8(cmd.argument())));
+                       // FIXME This should be simplified when InsetFloatList takes a 
+                       // Buffer in its constructor.
+                       InsetFloatList * ifl = new InsetFloatList(to_utf8(cmd.argument()));
+                       ifl->setBuffer(bv->buffer());
+                       insertInset(cur, ifl);
                        cur.posForward();
                } else {
                        lyxerr << "Non-existent float type: "
@@ -1828,7 +1887,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        FuncStatus & flag) const
 {
-       BOOST_ASSERT(cur.text() == this);
+       LASSERT(cur.text() == this, /**/);
 
        Font const & font = cur.real_current_font;
        FontInfo const & fontinfo = font.fontInfo();
@@ -1850,7 +1909,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                return true;
 
        case LFUN_BIBITEM_INSERT:
-               enable = (cur.paragraph().layout()->labeltype == LABEL_BIBLIO
+               enable = (cur.paragraph().layout().labeltype == LABEL_BIBLIO
                          && cur.pos() == 0);
                break;
 
@@ -1887,6 +1946,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        code = NOTE_CODE;
                else if (cmd.argument() == "ref")
                        code = REF_CODE;
+               else if (cmd.argument() == "space")
+                       code = SPACE_CODE;
                else if (cmd.argument() == "toc")
                        code = TOC_CODE;
                else if (cmd.argument() == "vspace")
@@ -1901,7 +1962,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = ERT_CODE;
                break;
        case LFUN_LISTING_INSERT:
-           code = LISTINGS_CODE;
+               code = LISTINGS_CODE;
                break;
        case LFUN_FOOTNOTE_INSERT:
                code = FOOT_CODE;
@@ -1926,15 +1987,15 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_LIST_INSERT:
                code = LIST_CODE;
                break;
-       case LFUN_THEOREM_INSERT:
-               code = THEOREM_CODE;
-               break;
 #endif
        case LFUN_CAPTION_INSERT:
                code = CAPTION_CODE;
                break;
        case LFUN_NOTE_INSERT:
                code = NOTE_CODE;
+               // in commands (sections etc., only Notes are allowed)
+               enable = (cmd.argument().empty() || cmd.getArg(0) == "Note" ||
+                         !cur.paragraph().layout().isCommand());
                break;
        case LFUN_FLEX_INSERT: {
                code = FLEX_CODE;
@@ -1965,7 +2026,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_OPTIONAL_INSERT:
                code = OPTARG_CODE;
                enable = cur.paragraph().insetList().count(OPTARG_CODE)
-                       < cur.paragraph().layout()->optionalargs;
+                       < cur.paragraph().layout().optionalargs;
                break;
        case LFUN_ENVIRONMENT_INSERT:
                code = BOX_CODE;
@@ -1992,7 +2053,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                // always allow this, since we will inset a raw quote
                // if an inset is not allowed.
                break;
-       case LFUN_HFILL_INSERT:
        case LFUN_SPECIALCHAR_INSERT:
                code = SPECIALCHAR_CODE;
                break;
@@ -2113,7 +2173,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_OUTLINE_DOWN:
        case LFUN_OUTLINE_IN:
        case LFUN_OUTLINE_OUT:
-               enable = (cur.paragraph().layout()->toclevel != Layout::NOT_IN_TOC);
+               enable = (cur.paragraph().layout().toclevel != Layout::NOT_IN_TOC);
+               break;
+
+       case LFUN_NEWLINE_INSERT:
+               // LaTeX restrictions (labels or empty par)
+               enable = (cur.pos() > cur.paragraph().beginOfBody());
                break;
 
        case LFUN_WORD_DELETE_FORWARD:
@@ -2137,8 +2202,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_DOWN_SELECT:
        case LFUN_PARAGRAPH_UP_SELECT:
        case LFUN_PARAGRAPH_DOWN_SELECT:
-       case LFUN_SCREEN_UP_SELECT:
-       case LFUN_SCREEN_DOWN_SELECT:
        case LFUN_LINE_BEGIN_SELECT:
        case LFUN_LINE_END_SELECT:
        case LFUN_WORD_FORWARD_SELECT:
@@ -2149,9 +2212,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_PARAGRAPH_UP:
        case LFUN_PARAGRAPH_DOWN:
        case LFUN_LINE_BEGIN:
-       case LFUN_LINE_BREAK:
        case LFUN_LINE_END:
-       case LFUN_NEW_LINE:
        case LFUN_CHAR_DELETE_FORWARD:
        case LFUN_DELETE_FORWARD_SKIP:
        case LFUN_CHAR_DELETE_BACKWARD:
@@ -2166,16 +2227,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_CHARS_TRANSPOSE:
        case LFUN_SERVER_GET_XY:
        case LFUN_SERVER_SET_XY:
-       case LFUN_SERVER_GET_FONT:
        case LFUN_SERVER_GET_LAYOUT:
        case LFUN_LAYOUT:
        case LFUN_DATE_INSERT:
        case LFUN_SELF_INSERT:
        case LFUN_LINE_INSERT:
        case LFUN_NEWPAGE_INSERT:
-       case LFUN_PAGEBREAK_INSERT:
-       case LFUN_CLEARPAGE_INSERT:
-       case LFUN_CLEARDOUBLEPAGE_INSERT:
        case LFUN_MATH_DISPLAY:
        case LFUN_MATH_IMPORT_SELECTION:
        case LFUN_MATH_MODE:
@@ -2220,6 +2277,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_BUFFER_BEGIN_SELECT:
        case LFUN_BUFFER_END_SELECT:
        case LFUN_UNICODE_INSERT:
+       case LFUN_SET_GRAPHICS_GROUP:
                // these are handled in our dispatch()
                enable = true;
                break;