]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
Move handling of LFUN_INSET_SETTINGS to Inset.cpp
[lyx.git] / src / Text3.cpp
index c6674850cfb460b69ba3eaadcca43b8fc13fd5b3..3ac094d033c994f3ad2cfa5fe0cb121626ac14e3 100644 (file)
@@ -1,14 +1,14 @@
 /**
- * \file text3.cpp
+ * \file Text3.cpp
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
  * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author Alfredo Braunstein
  * \author Angus Leeming
  * \author John Levon
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
 #include "TextMetrics.h"
 #include "VSpace.h"
 
+#include "frontends/Application.h"
 #include "frontends/Clipboard.h"
+#include "frontends/LyXView.h"
 #include "frontends/Selection.h"
+#include "frontends/WorkArea.h"
 
 #include "insets/InsetCollapsable.h"
 #include "insets/InsetCommand.h"
+#include "insets/InsetExternal.h"
 #include "insets/InsetFloatList.h"
+#include "insets/InsetGraphics.h"
+#include "insets/InsetGraphicsParams.h"
 #include "insets/InsetNewline.h"
 #include "insets/InsetQuotes.h"
 #include "insets/InsetSpecialChar.h"
 #include "insets/InsetText.h"
-#include "insets/InsetInfo.h"
 
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
 #include "support/lyxtime.h"
+#include "support/os.h"
 
 #include "mathed/InsetMathHull.h"
 #include "mathed/MathMacroTemplate.h"
@@ -83,6 +89,8 @@ using cap::pasteFromStack;
 using cap::pasteClipboardText;
 using cap::pasteClipboardGraphics;
 using cap::replaceSelection;
+using cap::grabAndEraseSelection;
+using cap::selClearOrDel;
 
 // globals...
 static Font freefont(ignore_font, ignore_language);
@@ -126,6 +134,9 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
        // It may happen that sel is empty but there is a selection
        replaceSelection(cur);
 
+       // Is this a valid formula?
+       bool valid = true;
+
        if (sel.empty()) {
 #ifdef ENABLE_ASSERTIONS
                const int old_pos = cur.pos();
@@ -155,20 +166,51 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
                                && sel.find(from_ascii("\\def")) == string::npos)
                {
                        InsetMathHull * formula = new InsetMathHull;
-                       istringstream is(to_utf8(sel));
+                       string const selstr = to_utf8(sel);
+                       istringstream is(selstr);
                        Lexer lex;
                        lex.setStream(is);
-                       formula->read(lex);
-                       if (formula->getType() == hullNone)
-                               // Don't create pseudo formulas if
-                               // delimiters are left out
-                               formula->mutate(hullSimple);
-                       cur.insert(formula);
+                       if (!formula->readQuiet(lex)) {
+                               // No valid formula, let's try with delims
+                               is.str("$" + selstr + "$");
+                               lex.setStream(is);
+                               if (!formula->readQuiet(lex)) {
+                                       // Still not valid, leave it as is
+                                       valid = false;
+                                       delete formula;
+                                       cur.insert(sel);
+                               } else
+                                       cur.insert(formula);
+                       } else
+                               cur.insert(formula);
                } else {
                        cur.insert(new MathMacroTemplate(sel));
                }
        }
-       cur.message(from_utf8(N_("Math editor mode")));
+       if (valid)
+               cur.message(from_utf8(N_("Math editor mode")));
+       else
+               cur.message(from_utf8(N_("No valid math formula")));
+}
+
+
+void regexpDispatch(Cursor & cur, FuncRequest const & cmd)
+{
+       BOOST_ASSERT(cmd.action == LFUN_REGEXP_MODE);
+       if (cur.inRegexped()) {
+               cur.message(_("Already in regexp mode"));
+               return;
+       }
+       cur.recordUndo();
+       docstring const save_selection = grabAndEraseSelection(cur);
+       selClearOrDel(cur);
+       // replaceSelection(cur);
+
+       cur.insert(new InsetMathHull(hullRegexp));
+       cur.nextInset()->edit(cur, true);
+       cur.niceInsert(save_selection);
+
+       cur.message(_("Regexp editor mode"));
 }
 
 
@@ -200,13 +242,15 @@ static bool doInsertInset(Cursor & cur, Text * text,
                if (edit)
                        inset->edit(cur, true);
                // Now put this into inset
-               static_cast<InsetCollapsable *>(inset)->text_.insertStringAsParagraphs(cur, ds);
+               static_cast<InsetCollapsable *>(inset)->
+                               text().insertStringAsParagraphs(cur, ds);
                return true;
        }
 
        bool gotsel = false;
        if (cur.selection()) {
-               lyx::dispatch(FuncRequest(LFUN_CUT));
+               cutSelection(cur, false, pastesel);
+               cur.clearSelection();
                gotsel = true;
        }
        text->insertInset(cur, inset);
@@ -217,23 +261,28 @@ static bool doInsertInset(Cursor & cur, Text * text,
        if (!gotsel || !pastesel)
                return true;
 
-       lyx::dispatch(FuncRequest(LFUN_PASTE, "0"));
+       pasteFromStack(cur, cur.buffer()->errorList("Paste"), 0);
+       cur.buffer()->errors("Paste");
+       cur.clearSelection(); // bug 393
+       cur.finishUndo();
        InsetText * insetText = dynamic_cast<InsetText *>(inset);
-       if (insetText && !insetText->allowMultiPar() || cur.lastpit() == 0) {
+       if (insetText && (!insetText->allowMultiPar() || cur.lastpit() == 0)) {
                // reset first par to default
                cur.text()->paragraphs().begin()
-                       ->setEmptyOrDefaultLayout(bparams.documentClass());
+                       ->setPlainOrDefaultLayout(bparams.documentClass());
                cur.pos() = 0;
                cur.pit() = 0;
                // Merge multiple paragraphs -- hack
                while (cur.lastpit() > 0)
                        mergeParagraph(bparams, cur.text()->paragraphs(), 0);
+               cur.leaveInset(*inset);
        } else {
-               // reset surrounding par to default
-               docstring const layoutname = insetText->useEmptyLayout()
-                       ? bparams.documentClass().emptyLayoutName()
-                       : bparams.documentClass().defaultLayoutName();
                cur.leaveInset(*inset);
+               // reset surrounding par to default
+               DocumentClass const & dc = bparams.documentClass();
+               docstring const layoutname = inset->usePlainLayout()
+                       ? dc.plainLayoutName()
+                       : dc.defaultLayoutName();
                text->setLayout(cur, layoutname);
        }
 
@@ -258,7 +307,7 @@ enum OutlineOp {
 
 static void outline(OutlineOp mode, Cursor & cur)
 {
-       Buffer & buf = cur.buffer();
+       Buffer & buf = *cur.buffer();
        pit_type & pit = cur.pit();
        ParagraphList & pars = buf.text().paragraphs();
        ParagraphList::iterator bgn = pars.begin();
@@ -399,8 +448,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        BufferView * bv = &cur.bv();
        TextMetrics & tm = bv->textMetrics(this);
-       if (!tm.contains(cur.pit()))
-               lyx::dispatch(FuncRequest(LFUN_SCREEN_RECENTER));
+       if (!tm.contains(cur.pit())) {
+               lyx::dispatch(FuncRequest(LFUN_SCREEN_SHOW_CURSOR));
+               tm = bv->textMetrics(this);
+       }
 
        // FIXME: We use the update flag to indicates wether a singlePar or a
        // full screen update is needed. We reset it here but shall we restore it
@@ -426,7 +477,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit, pit + 1);
                cur.finishUndo();
                swap(pars_[pit], pars_[pit + 1]);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                ++cur.pit();
                break;
@@ -437,7 +488,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit - 1, pit);
                cur.finishUndo();
                swap(pars_[pit], pars_[pit - 1]);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                --cur.pit();
                needsUpdate = true;
                break;
@@ -463,30 +514,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                par.params().startOfAppendix(start);
 
                // we can set the refreshing parameters now
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                break;
        }
 
        case LFUN_WORD_DELETE_FORWARD:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        deleteWordForward(cur);
                finishChange(cur, false);
                break;
 
        case LFUN_WORD_DELETE_BACKWARD:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        deleteWordBackward(cur);
                finishChange(cur, false);
                break;
 
        case LFUN_LINE_DELETE:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        tm.deleteLineForward(cur);
                finishChange(cur, false);
                break;
@@ -494,22 +545,40 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_BUFFER_BEGIN:
        case LFUN_BUFFER_BEGIN_SELECT:
                needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_BEGIN_SELECT);
-               if (cur.depth() == 1) {
+               if (cur.depth() == 1)
                        needsUpdate |= cursorTop(cur);
-               } else {
+               else
                        cur.undispatched();
-               }
                cur.updateFlags(Update::FitCursor);
                break;
 
        case LFUN_BUFFER_END:
        case LFUN_BUFFER_END_SELECT:
                needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_END_SELECT);
-               if (cur.depth() == 1) {
+               if (cur.depth() == 1)
                        needsUpdate |= cursorBottom(cur);
-               } else {
+               else
+                       cur.undispatched();
+               cur.updateFlags(Update::FitCursor);
+               break;
+
+       case LFUN_INSET_BEGIN:
+       case LFUN_INSET_BEGIN_SELECT:
+               needsUpdate |= cur.selHandle(cmd.action == LFUN_INSET_BEGIN_SELECT);
+               if (cur.depth() == 1 || cur.pos() > 0)
+                       needsUpdate |= cursorTop(cur);
+               else
+                       cur.undispatched();
+               cur.updateFlags(Update::FitCursor);
+               break;
+
+       case LFUN_INSET_END:
+       case LFUN_INSET_END_SELECT:
+               needsUpdate |= cur.selHandle(cmd.action == LFUN_INSET_END_SELECT);
+               if (cur.depth() == 1 || cur.pos() < cur.lastpos())
+                       needsUpdate |= cursorBottom(cur);
+               else
                        cur.undispatched();
-               }
                cur.updateFlags(Update::FitCursor);
                break;
 
@@ -551,10 +620,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        }
                } else {
                        if (reverseDirectionNeeded(cur)) {
-                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ?
                                        LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
                        } else {
-                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ?
                                        LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
                        }
                        dispatch(cur, cmd);
@@ -574,17 +643,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        }
                } else {
                        if (reverseDirectionNeeded(cur)) {
-                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ?
                                        LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
                        } else {
-                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ?
                                        LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
                        }
                        dispatch(cur, cmd);
                        return;
                }
                break;
-               
+
 
        case LFUN_UP_SELECT:
        case LFUN_DOWN_SELECT:
@@ -593,17 +662,25 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // stop/start the selection
                bool select = cmd.action == LFUN_DOWN_SELECT ||
                        cmd.action == LFUN_UP_SELECT;
-               cur.selHandle(select);
-               
+
                // move cursor up/down
                bool up = cmd.action == LFUN_UP_SELECT || cmd.action == LFUN_UP;
-               bool const successful = cur.upDownInText(up, needsUpdate);
-               if (successful) {
-                       // redraw if you leave mathed (for the decorations)
+               bool const atFirstOrLastRow = cur.atFirstOrLastRow(up);
+
+               if (!atFirstOrLastRow) {
+                       needsUpdate |= cur.selHandle(select);   
+                       cur.selHandle(select);
+                       cur.upDownInText(up, needsUpdate);
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
-               } else
+               } else {
+                       // if the cursor cannot be moved up or down do not remove
+                       // the selection right now, but wait for the next dispatch.
+                       if (select)
+                               needsUpdate |= cur.selHandle(select);   
+                       cur.upDownInText(up, needsUpdate);
                        cur.undispatched();
-               
+               }
+
                break;
        }
 
@@ -633,16 +710,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 +739,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:
@@ -692,7 +789,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                moveCursor(cur, false);
                break;
        }
-       
+
        case LFUN_CHAR_DELETE_FORWARD:
                if (!cur.selection()) {
                        if (cur.pos() == cur.paragraph().size())
@@ -709,21 +806,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                moveCursor(cur, false);
                break;
 
-       case LFUN_DELETE_FORWARD_SKIP:
-               // Reverse the effect of LFUN_BREAK_PARAGRAPH_SKIP.
-               if (!cur.selection()) {
-                       if (cur.pos() == cur.lastpos()) {
-                               cursorForward(cur);
-                               cursorBackward(cur);
-                       }
-                       erase(cur);
-                       cur.resetAnchor();
-               } else {
-                       cutSelection(cur, true, false);
-               }
-               break;
-
-
        case LFUN_CHAR_DELETE_BACKWARD:
                if (!cur.selection()) {
                        if (bv->getIntl().getTransManager().backspace()) {
@@ -741,36 +823,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                break;
 
-       case LFUN_DELETE_BACKWARD_SKIP:
-               // Reverse the effect of LFUN_BREAK_PARAGRAPH_SKIP.
-               if (!cur.selection()) {
-                       // FIXME: look here
-                       //CursorSlice cur = cursor();
-                       backspace(cur);
-                       //anchor() = cur;
-               } else {
-                       cutSelection(cur, true, false);
-               }
-               break;
-
        case LFUN_BREAK_PARAGRAPH:
                cap::replaceSelection(cur);
                breakParagraph(cur, cmd.argument() == "inverse");
                cur.resetAnchor();
                break;
 
-       case LFUN_BREAK_PARAGRAPH_SKIP: {
-               // When at the beginning of a paragraph, remove
-               // indentation.  Otherwise, do the same as LFUN_BREAK_PARAGRAPH.
-               cap::replaceSelection(cur);
-               if (cur.pos() == 0)
-                       cur.paragraph().params().labelWidthString(docstring());
-               else
-                       breakParagraph(cur, false);
-               cur.resetAnchor();
-               break;
-       }
-
        // TODO
        // With the creation of LFUN_PARAGRAPH_PARAMS, this is now redundant,
        // as its duties can be performed there. Should it be removed??
@@ -816,7 +874,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_INSET_INSERT: {
                cur.recordUndo();
+
+               // We have to avoid triggering InstantPreview loading
+               // before inserting into the document. See bug #5626.
+               bool loaded = bv->buffer().isFullyLoaded();
+               bv->buffer().setFullyLoaded(false);
                Inset * inset = createInset(bv->buffer(), cmd);
+               bv->buffer().setFullyLoaded(loaded);
+
                if (inset) {
                        // FIXME (Abdel 01/02/2006):
                        // What follows would be a partial fix for bug 2154:
@@ -844,26 +909,64 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                cutSelection(cur, true, false);
                        cur.insert(inset);
                        cur.posForward();
+
+                       // trigger InstantPreview now
+                       if (inset->lyxCode() == EXTERNAL_CODE) {
+                               InsetExternal & ins =
+                                       static_cast<InsetExternal &>(*inset);
+                               ins.updatePreview();
+                       }
                }
-               break;
-       }
 
-       case LFUN_INSET_DISSOLVE:
-               needsUpdate |= dissolveInset(cur);
                break;
+       }
 
-       case LFUN_INSET_SETTINGS: {
-               // if there is an inset at cursor, access this
+       case LFUN_INSET_DISSOLVE: {
+               // first, try if there's an inset at cursor
+               // FIXME: this first part should be moved to
+               // a LFUN_NEXT_INSET_DISSOLVE, or be called via
+               // some generic "next-inset inset-dissolve"
                Inset * inset = cur.nextInset();
-               if (inset) {
-                       inset->showInsetDialog(bv);
+               if (inset && inset->isActive()) {
+                       Cursor tmpcur = cur;
+                       tmpcur.pushBackward(*inset);
+                       inset->dispatch(tmpcur, cmd);
+                       if (tmpcur.result().dispatched()) {
+                               cur.dispatched();
+                               break;
+                       }
+               }
+               // if it did not work, try the underlying inset
+               if (dissolveInset(cur)) {
+                       needsUpdate = true;
                        break;
                }
-               // if not work, access the underlying inset.
-               cur.inset().showInsetDialog(bv);
+               // if it did not work, do nothing.
                break;
        }
 
+       case LFUN_SET_GRAPHICS_GROUP: {
+               InsetGraphics * ins = graphics::getCurrentGraphicsInset(cur);
+               if (!ins)
+                       break;
+
+               cur.recordUndo();
+
+               string id = to_utf8(cmd.argument());
+               string grp = graphics::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)
                        insertChar(cur, ' ');
@@ -915,6 +1018,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_PASTE: {
                cur.message(_("Paste"));
+               LASSERT(cur.selBegin().idx() == cur.selEnd().idx(), /**/);
                cap::replaceSelection(cur);
 
                // without argument?
@@ -922,7 +1026,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (arg.empty()) {
                        if (theClipboard().isInternal())
                                pasteFromStack(cur, bv->buffer().errorList("Paste"), 0);
-                       else if (theClipboard().hasGraphicsContents())
+                       else if (theClipboard().hasGraphicsContents() 
+                                    && !theClipboard().hasTextContents())
                                pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"));
                        else
                                pasteClipboardText(cur, bv->buffer().errorList("Paste"));
@@ -981,15 +1086,6 @@ 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());
                break;
@@ -1005,16 +1101,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (layout.empty())
                        layout = tclass.defaultLayoutName();
 
-               if (para.forceEmptyLayout()) 
+               if (para.forcePlainLayout())
                        // in this case only the empty layout is allowed
-                       layout = tclass.emptyLayoutName();
-               else if (para.useEmptyLayout()) {
-                       // in this case, default layout maps to empty layout 
+                       layout = tclass.plainLayoutName();
+               else if (para.usePlainLayout()) {
+                       // in this case, default layout maps to empty layout
                        if (layout == tclass.defaultLayoutName())
-                               layout = tclass.emptyLayoutName();
-               } else { 
+                               layout = tclass.plainLayoutName();
+               } else {
                        // otherwise, the empty layout maps to the default
-                       if (layout == tclass.emptyLayoutName())
+                       if (layout == tclass.plainLayoutName())
                                layout = tclass.defaultLayoutName();
                }
 
@@ -1067,6 +1163,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                            cmd.argument() == "paragraph");
                break;
 
+       case LFUN_SELECTION_PASTE:
+               // 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");
+               break;
+
        case LFUN_UNICODE_INSERT: {
                if (cmd.argument().empty())
                        break;
@@ -1087,7 +1192,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                pos_type pos = cur.pos();
                BufferParams const & bufparams = bv->buffer().params();
                Layout const & style = par.layout();
-               if (!style.pass_thru
+               InsetLayout const & ilayout = cur.inset().getLayout(bufparams);
+               if (!style.pass_thru && !ilayout.isPassThru()
                    && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") {
                        // this avoids a double undo
                        // FIXME: should not be needed, ideally
@@ -1103,9 +1209,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        else
                                c = par.getChar(pos - 1);
                        string arg = to_utf8(cmd.argument());
-                       cur.insert(new InsetQuotes(c, bufparams.quotes_language,
-                               (arg == "single") ? InsetQuotes::SingleQuotes
-                                       : InsetQuotes::DoubleQuotes));
+                       cur.insert(new InsetQuotes(bv->buffer(), c, (arg == "single")
+                               ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes));
                        cur.posForward();
                }
                else
@@ -1141,52 +1246,37 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // Single-click on work area
        case LFUN_MOUSE_PRESS:
                // We are not marking a selection with the keyboard in any case.
-               cur.bv().cursor().mark() = false;
+               cur.bv().cursor().setMark(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;                  
+                       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.
+                       bv->mouseSetCursor(cur);
+                       lyx::dispatch(
+                               FuncRequest(LFUN_COMMAND_ALTERNATIVES,
+                                           "selection-paste ; primary-selection-paste paragraph"));
+                       cur.noUpdate();
+                       break;
+
+               case mouse_button::button3: {
+                       Cursor const & bvcur = cur.bv().cursor();
+                       // Don't do anything if we right-click a
+                       // selection, a context menu will popup.
+                       if (bvcur.selection() && cur >= bvcur.selectionBegin()
+                           && cur < bvcur.selectionEnd()) {
                                cur.noUpdate();
                                return;
                        }
-                       // 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();
+                       if (!bv->mouseSetCursor(cur, false))
+                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
                        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())
@@ -1225,7 +1315,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // We continue with our existing selection or start a new one, so don't
                // reset the anchor.
                bvcur.setCursor(cur);
-               bvcur.selection() = true;
+               bvcur.setSelection(true);
                if (cur.top() == old) {
                        // We didn't move one iota, so no need to update the screen.
                        cur.updateFlags(Update::SinglePar | Update::FitCursor);
@@ -1243,13 +1333,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        // 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.
-                               cur.bv().cursor().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().setSelection();
+                               // We might have removed an empty but drawn selection
+                               // (probably a margin)
+                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       } else
+                               cur.noUpdate();
                        // FIXME: We could try to handle drag and drop of selection here.
-                       cur.noUpdate();
                        return;
 
                case mouse_button::button2:
@@ -1265,6 +1359,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        cur.noUpdate();
                        return;
 
+               case mouse_button::none:
+               case mouse_button::button4:
+               case mouse_button::button5:
+                       break;
                } // switch (cmd.button())
 
                break;
@@ -1283,15 +1381,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        cutSelection(cur, false, false);
 
                cur.clearSelection();
-               Font const old_font = cur.real_current_font;
 
                docstring::const_iterator cit = cmd.argument().begin();
-               docstring::const_iterator end = cmd.argument().end();
+               docstring::const_iterator const end = cmd.argument().end();
                for (; cit != end; ++cit)
                        bv->translateAndInsert(*cit, this, cur);
 
                cur.resetAnchor();
                moveCursor(cur, false);
+               bv->bookmarkEditPosition();
                break;
        }
 
@@ -1332,37 +1430,33 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_INFO_INSERT: {
-               Inset * inset = createInset(cur.bv().buffer(), cmd);
-               if (!inset)
-                       break;
-               // if an empty inset is created (cmd.argument() is empty)
-               // use current selection as parameter.
+               Inset * inset;
                if (cmd.argument().empty() && cur.selection()) {
-                       // use selected text as info to avoid a separate UI
+                       // if command argument is empty use current selection as parameter.
                        docstring ds = cur.selectionAsString(false);
                        cutSelection(cur, true, false);
-                       static_cast<InsetInfo *>(inset)->setInfo(to_utf8(ds));
-                       static_cast<InsetInfo *>(inset)->updateInfo();
+                       FuncRequest cmd0(cmd, ds);
+                       inset = createInset(cur.bv().buffer(), cmd0);
+               } else {
+                       inset = createInset(cur.bv().buffer(), cmd);
                }
+               if (!inset)
+                       break;
                insertInset(cur, inset);
                cur.posForward();
                break;
        }
-#if 0
-       case LFUN_LIST_INSERT:
-#endif
        case LFUN_CAPTION_INSERT:
        case LFUN_FOOTNOTE_INSERT:
        case LFUN_NOTE_INSERT:
        case LFUN_FLEX_INSERT:
        case LFUN_BOX_INSERT:
        case LFUN_BRANCH_INSERT:
-       case LFUN_BIBITEM_INSERT:
+       case LFUN_PHANTOM_INSERT:
        case LFUN_ERT_INSERT:
        case LFUN_LISTING_INSERT:
        case LFUN_MARGINALNOTE_INSERT:
        case LFUN_OPTIONAL_INSERT:
-       case LFUN_ENVIRONMENT_INSERT:
        case LFUN_INDEX_INSERT:
                // Open the inset, and move the current selection
                // inside it.
@@ -1370,7 +1464,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                cur.posForward();
                // Some insets are numbered, others are shown in the outline pane so
                // let's update the labels and the toc backend.
-               updateLabels(bv->buffer());
+               bv->buffer().updateLabels();
                break;
 
        case LFUN_TABULAR_INSERT:
@@ -1385,18 +1479,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_FLOAT_INSERT:
        case LFUN_FLOAT_WIDE_INSERT:
        case LFUN_WRAP_INSERT: {
-               bool content = cur.selection();  // will some text be moved into the inset?
+               // will some text be moved into the inset?
+               bool content = cur.selection();
 
                doInsertInset(cur, this, cmd, true, true);
                cur.posForward();
+
+               // If some text is moved into the inset, doInsertInset 
+               // puts the cursor outside the inset. To insert the
+               // caption we put it back into the inset.
+               if (content)
+                       cur.backwardPos();
+
                ParagraphList & pars = cur.text()->paragraphs();
 
                DocumentClass const & tclass = bv->buffer().params().documentClass();
 
                // add a separate paragraph for the caption inset
                pars.push_back(Paragraph());
-               pars.back().setInsetOwner(pars[0].inInset());
-               pars.back().setEmptyOrDefaultLayout(tclass);
+               pars.back().setInsetOwner(&pars[0].inInset());
+               pars.back().setPlainOrDefaultLayout(tclass);
                int cap_pit = pars.size() - 1;
 
                // if an empty inset was created, we create an additional empty
@@ -1404,8 +1506,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // the graphics (or table).
                if (!content) {
                        pars.push_back(Paragraph());
-                       pars.back().setInsetOwner(pars[0].inInset());
-                       pars.back().setEmptyOrDefaultLayout(tclass);
+                       pars.back().setInsetOwner(&pars[0].inInset());
+                       pars.back().setPlainOrDefaultLayout(tclass);
                }
 
                // reposition the cursor to the caption
@@ -1415,7 +1517,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // We cannot use Cursor::dispatch here it needs access to up to
                // date metrics.
                FuncRequest cmd_caption(LFUN_CAPTION_INSERT);
-               cur.text()->dispatch(cur, cmd_caption);
+               doInsertInset(cur, cur.text(), cmd_caption, true, false);
+               bv->buffer().updateLabels();
                cur.updateFlags(Update::Force);
                // FIXME: When leaving the Float (or Wrap) inset we should
                // delete any empty paragraph left above or below the
@@ -1424,21 +1527,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_NOMENCL_INSERT: {
-               FuncRequest cmd1 = cmd;
+               InsetCommandParams p(NOMENCL_CODE);
                if (cmd.argument().empty())
-                       cmd1 = FuncRequest(cmd,
-                               bv->cursor().innerText()->getStringToIndex(bv->cursor()));
-               Inset * inset = createInset(cur.bv().buffer(), cmd1);
-               if (!inset)
-                       break;
-               cur.recordUndo();
-               cur.clearSelection();
-               insertInset(cur, inset);
-               // Show the dialog for the nomenclature entry, since the
-               // description entry still needs to be filled in.
-               if (cmd.action == LFUN_NOMENCL_INSERT)
-                       inset->edit(cur, true);
-               cur.posForward();
+                       p["symbol"] = bv->cursor().innerText()->getStringToIndex(bv->cursor());
+               else
+                       p["symbol"] = cmd.argument();
+               string const data = InsetCommand::params2string("nomenclature", p);
+               bv->showDialog("nomenclature", data);
                break;
        }
 
@@ -1464,7 +1559,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                mathDispatch(cur, cmd, true);
                break;
 
-       case LFUN_MATH_IMPORT_SELECTION:
+       case LFUN_REGEXP_MODE:
+               regexpDispatch(cur, cmd);
+               break;
+
        case LFUN_MATH_MODE:
                if (cmd.argument() == "on")
                        // don't pass "on" as argument
@@ -1484,8 +1582,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        MacroType type = MacroTypeNewcommand;
                        if (s2 == "def")
                                type = MacroTypeDef;
-                       cur.insert(new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, type));
-                       //cur.nextInset()->edit(cur, true);
+                       MathMacroTemplate * inset = new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, type);
+                       inset->setBuffer(bv->buffer());
+                       insertInset(cur, inset);
+
+                       // enter macro inset and select the name
+                       cur.push(*inset);
+                       cur.top().pos() = cur.top().lastpos();
+                       cur.resetAnchor();
+                       cur.setSelection(true);
+                       cur.top().pos() = 0;
                }
                break;
 
@@ -1501,6 +1607,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_MATH_MATRIX:
        case LFUN_MATH_DELIM:
        case LFUN_MATH_BIGDELIM: {
+               cur.recordUndo();
                cap::replaceSelection(cur);
                cur.insert(new InsetMathHull(hullSimple));
                checkAndActivateInset(cur, true);
@@ -1516,7 +1623,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_FONT_BOLD: {
+       case LFUN_FONT_ITAL: {
+               Font font(ignore_font, ignore_language);
+               font.fontInfo().setShape(ITALIC_SHAPE);
+               toggleAndShow(cur, this, font);
+               break;
+       }
+
+       case LFUN_FONT_BOLD:
+       case LFUN_FONT_BOLDSYMBOL: {
                Font font(ignore_font, ignore_language);
                font.fontInfo().setSeries(BOLD_SERIES);
                toggleAndShow(cur, this, font);
@@ -1580,14 +1695,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_FONT_FREE_APPLY:
+       case LFUN_TEXTSTYLE_APPLY:
                toggleAndShow(cur, this, freefont, toggleall);
                cur.message(_("Character set"));
                break;
 
        // Set the freefont using the contents of \param data dispatched from
        // the frontends and apply it at the current cursor location.
-       case LFUN_FONT_FREE_UPDATE: {
+       case LFUN_TEXTSTYLE_UPDATE: {
                Font font;
                bool toggle;
                if (font.fromString(to_utf8(cmd.argument()), toggle)) {
@@ -1603,9 +1718,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_LEFT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_LEFT:\n" << cur);
-               // We're leaving an inset, going left. If the inset is LTR, we're 
+               // We're leaving an inset, going left. If the inset is LTR, we're
                // leaving from the front, so we should not move (remain at --- but
-               // not in --- the inset). If the inset is RTL, move left, without 
+               // not in --- the inset). If the inset is RTL, move left, without
                // entering the inset itself; i.e., move to after the inset.
                if (cur.paragraph().getFontSettings(
                                cur.bv().buffer().params(), cur.pos()).isRightToLeft())
@@ -1614,9 +1729,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_RIGHT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_RIGHT:\n" << cur);
-               // We're leaving an inset, going right. If the inset is RTL, we're 
+               // We're leaving an inset, going right. If the inset is RTL, we're
                // leaving from the front, so we should not move (remain at --- but
-               // not in --- the inset). If the inset is LTR, move right, without 
+               // not in --- the inset). If the inset is LTR, move right, without
                // entering the inset itself; i.e., move to after the inset.
                if (!cur.paragraph().getFontSettings(
                                cur.bv().buffer().params(), cur.pos()).isRightToLeft())
@@ -1646,7 +1761,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                params2string(cur.paragraph(), data);
 
                // Will the paragraph accept changes from the dialog?
-               bool const accept = 
+               bool const accept =
                        cur.inset().allowParagraphCustomization(cur.idx());
 
                data = "update " + convert<string>(accept) + '\n' + data;
@@ -1665,7 +1780,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_ACCENT_UNDERDOT:
        case LFUN_ACCENT_UNDERBAR:
        case LFUN_ACCENT_CARON:
-       case LFUN_ACCENT_SPECIAL_CARON:
        case LFUN_ACCENT_BREVE:
        case LFUN_ACCENT_TIE:
        case LFUN_ACCENT_HUNGARIAN_UMLAUT:
@@ -1677,7 +1791,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        bv->translateAndInsert(cmd.argument()[0], this, cur);
                break;
 
-       case LFUN_FLOAT_LIST: {
+       case LFUN_FLOAT_LIST_INSERT: {
                DocumentClass const & tclass = bv->buffer().params().documentClass();
                if (tclass.floats().typeExist(to_utf8(cmd.argument()))) {
                        cur.recordUndo();
@@ -1690,13 +1804,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                breakParagraph(cur);
                        }
 
-                       docstring const laystr = cur.inset().useEmptyLayout() ?
-                               tclass.emptyLayoutName() :
+                       docstring const laystr = cur.inset().usePlainLayout() ?
+                               tclass.plainLayoutName() :
                                tclass.defaultLayoutName();
                        setLayout(cur, laystr);
                        ParagraphParameters p;
+                       // FIXME If this call were replaced with one to clearParagraphParams(),
+                       // then we could get rid of this method altogether.
                        setParagraphs(cur, p);
-                       // FIXME This should be simplified when InsetFloatList takes a 
+                       // 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());
@@ -1728,6 +1844,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                // Get word or selection
                                selectWordWhenUnderCursor(cur, WHOLE_WORD);
                                arg = cur.selectionAsString(false);
+                               arg += " lang=" + from_ascii(cur.getFont().language()->lang());
                        }
                }
                bv->showDialog("thesaurus", to_utf8(arg));
@@ -1738,17 +1855,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // Given data, an encoding of the ParagraphParameters
                // generated in the Paragraph dialog, this function sets
                // the current paragraph, or currently selected paragraphs,
-               // appropriately. 
+               // appropriately.
                // NOTE: This function overrides all existing settings.
                setParagraphs(cur, cmd.argument());
                cur.message(_("Paragraph layout set"));
                break;
        }
-       
+
        case LFUN_PARAGRAPH_PARAMS: {
                // Given data, an encoding of the ParagraphParameters as we'd
-               // find them in a LyX file, this function modifies the current paragraph, 
-               // or currently selected paragraphs. 
+               // find them in a LyX file, this function modifies the current paragraph,
+               // or currently selected paragraphs.
                // NOTE: This function only modifies, and does not override, existing
                // settings.
                setParagraphs(cur, cmd.argument(), true);
@@ -1758,7 +1875,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_ESCAPE:
                if (cur.selection()) {
-                       cur.selection() = false;
+                       cur.setSelection(false);
                } else {
                        cur.undispatched();
                        // This used to be LFUN_FINISHED_RIGHT, I think FORWARD is more
@@ -1770,26 +1887,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_OUTLINE_UP:
                outline(OutlineUp, cur);
                setCursor(cur, cur.pit(), 0);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_DOWN:
                outline(OutlineDown, cur);
                setCursor(cur, cur.pit(), 0);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_IN:
                outline(OutlineIn, cur);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_OUT:
                outline(OutlineOut, cur);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
@@ -1846,8 +1963,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 {
        LASSERT(cur.text() == this, /**/);
 
-       Font const & font = cur.real_current_font;
-       FontInfo const & fontinfo = font.fontInfo();
+       FontInfo const & fontinfo = cur.real_current_font.fontInfo();
        bool enable = true;
        InsetCode code = NO_CODE;
 
@@ -1863,11 +1979,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_APPENDIX:
                flag.setOnOff(cur.paragraph().params().startOfAppendix());
-               return true;
-
-       case LFUN_BIBITEM_INSERT:
-               enable = (cur.paragraph().layout().labeltype == LABEL_BIBLIO
-                         && cur.pos() == 0);
                break;
 
        case LFUN_DIALOG_SHOW_NEW_INSET:
@@ -1901,6 +2012,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        code = LABEL_CODE;
                else if (cmd.argument() == "note")
                        code = NOTE_CODE;
+               else if (cmd.argument() == "phantom")
+                       code = PHANTOM_CODE;
                else if (cmd.argument() == "ref")
                        code = REF_CODE;
                else if (cmd.argument() == "space")
@@ -1920,6 +2033,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
        case LFUN_LISTING_INSERT:
                code = LISTINGS_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_FOOTNOTE_INSERT:
                code = FOOT_CODE;
@@ -1933,36 +2048,39 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_FLOAT_INSERT:
        case LFUN_FLOAT_WIDE_INSERT:
                code = FLOAT_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_WRAP_INSERT:
                code = WRAP_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
-       case LFUN_FLOAT_LIST:
+       case LFUN_FLOAT_LIST_INSERT:
                code = FLOAT_LIST_CODE;
                break;
-#if 0
-       case LFUN_LIST_INSERT:
-               code = LIST_CODE;
-               break;
-#endif
        case LFUN_CAPTION_INSERT:
                code = CAPTION_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_NOTE_INSERT:
                code = NOTE_CODE;
-               // in commands (sections etc., only Notes are allowed)
+               // in commands (sections etc.) and description items,
+               // only Notes are allowed
                enable = (cmd.argument().empty() || cmd.getArg(0) == "Note" ||
-                         !cur.paragraph().layout().isCommand());
+                         (!cur.paragraph().layout().isCommand()
+                          && !inDescriptionItem(cur)));
                break;
        case LFUN_FLEX_INSERT: {
                code = FLEX_CODE;
                string s = cmd.getArg(0);
-               InsetLayout il = 
-                       cur.buffer().params().documentClass().insetLayout(from_utf8(s));
-               if (il.lyxtype() != "charstyle" &&
-                   il.lyxtype() != "custom" &&
-                   il.lyxtype() != "element" &&
-                   il.lyxtype ()!= "standard")
+               InsetLayout il =
+                       cur.buffer()->params().documentClass().insetLayout(from_utf8(s));
+               if (il.lyxtype() != InsetLayout::CHARSTYLE &&
+                   il.lyxtype() != InsetLayout::CUSTOM &&
+                   il.lyxtype() != InsetLayout::ELEMENT &&
+                   il.lyxtype ()!= InsetLayout::STANDARD)
                        enable = false;
                break;
                }
@@ -1971,9 +2089,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
        case LFUN_BRANCH_INSERT:
                code = BRANCH_CODE;
-               if (cur.buffer().masterBuffer()->params().branchlist().empty())
+               if (cur.buffer()->masterBuffer()->params().branchlist().empty())
                        enable = false;
                break;
+       case LFUN_PHANTOM_INSERT:
+               code = PHANTOM_CODE;
+               break;
        case LFUN_LABEL_INSERT:
                code = LABEL_CODE;
                break;
@@ -1985,9 +2106,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = cur.paragraph().insetList().count(OPTARG_CODE)
                        < cur.paragraph().layout().optionalargs;
                break;
-       case LFUN_ENVIRONMENT_INSERT:
-               code = BOX_CODE;
-               break;
        case LFUN_INDEX_INSERT:
                code = INDEX_CODE;
                break;
@@ -1995,6 +2113,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = INDEX_PRINT_CODE;
                break;
        case LFUN_NOMENCL_INSERT:
+               if (cur.selIsMultiCell() || cur.selIsMultiLine()) {
+                       enable = false;
+                       break;
+               }
                code = NOMENCL_CODE;
                break;
        case LFUN_NOMENCL_PRINT:
@@ -2004,6 +2126,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = TOC_CODE;
                break;
        case LFUN_HYPERLINK_INSERT:
+               if (cur.selIsMultiCell() || cur.selIsMultiLine()) {
+                       enable = false;
+                       break;
+               }
                code = HYPERLINK_CODE;
                break;
        case LFUN_QUOTE_INSERT:
@@ -2029,27 +2155,32 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_FONT_EMPH:
                flag.setOnOff(fontinfo.emph() == FONT_ON);
-               return true;
+               break;
+
+       case LFUN_FONT_ITAL:
+               flag.setOnOff(fontinfo.shape() == ITALIC_SHAPE);
+               break;
 
        case LFUN_FONT_NOUN:
                flag.setOnOff(fontinfo.noun() == FONT_ON);
-               return true;
+               break;
 
        case LFUN_FONT_BOLD:
+       case LFUN_FONT_BOLDSYMBOL:
                flag.setOnOff(fontinfo.series() == BOLD_SERIES);
-               return true;
+               break;
 
        case LFUN_FONT_SANS:
                flag.setOnOff(fontinfo.family() == SANS_FAMILY);
-               return true;
+               break;
 
        case LFUN_FONT_ROMAN:
                flag.setOnOff(fontinfo.family() == ROMAN_FAMILY);
-               return true;
+               break;
 
        case LFUN_FONT_TYPEWRITER:
                flag.setOnOff(fontinfo.family() == TYPEWRITER_FAMILY);
-               return true;
+               break;
 
        case LFUN_CUT:
        case LFUN_COPY:
@@ -2064,7 +2195,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                                enable = !theClipboard().empty();
                        break;
                }
-               
+
                // we have an argument
                string const arg = to_utf8(cmd.argument());
                if (isStrUnsignedInt(arg)) {
@@ -2073,7 +2204,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        enable = cap::numberOfSelections() > n;
                        break;
                }
-               
+
                // explicit graphics type?
                if ((arg == "pdf" && theClipboard().hasGraphicsContents(Clipboard::PdfGraphicsType))
                    || (arg == "png" && theClipboard().hasGraphicsContents(Clipboard::PngGraphicsType))
@@ -2082,7 +2213,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        enable = true;
                        break;
                }
-               
+
                // unknown argument
                enable = false;
                break;
@@ -2096,6 +2227,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = cur.selection() || !theSelection().empty();
                break;
 
+       case LFUN_SELECTION_PASTE:
+               enable = cap::selection();
+               break;
+
        case LFUN_PARAGRAPH_MOVE_UP:
                enable = cur.pit() > 0 && !cur.selection();
                break;
@@ -2106,12 +2241,16 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_INSET_DISSOLVE:
                if (!cmd.argument().empty()) {
-                       InsetLayout il = cur.inset().getLayout(cur.buffer().params());
+                       InsetLayout const & il = cur.inset().getLayout(cur.buffer()->params());
+                       InsetLayout::InsetLyXType const type = 
+                                       translateLyXType(to_utf8(cmd.argument()));
                        enable = cur.inset().lyxCode() == FLEX_CODE
-                                && il.lyxtype() == to_utf8(cmd.argument());
+                                && il.lyxtype() == type;
                } else {
-                       enable = !isMainText(cur.bv().buffer()) 
-                                && cur.inset().nargs() == 1;
+                       enable = ((!isMainText(cur.bv().buffer())
+                                     && cur.inset().nargs() == 1)
+                                 || (cur.nextInset()
+                                     && cur.nextInset()->nargs() == 1));
                }
                break;
 
@@ -2130,7 +2269,9 @@ 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);
+               // FIXME: LyX is not ready for outlining within inset.
+               enable = isMainText(cur.bv().buffer())
+                       && cur.paragraph().layout().toclevel != Layout::NOT_IN_TOC;
                break;
 
        case LFUN_NEWLINE_INSERT:
@@ -2138,6 +2279,35 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = (cur.pos() > cur.paragraph().beginOfBody());
                break;
 
+       case LFUN_SET_GRAPHICS_GROUP: {
+               InsetGraphics * ins = graphics::getCurrentGraphicsInset(cur);
+               if (!ins)
+                       enable = false;
+               else
+                       flag.setOnOff(to_utf8(cmd.argument()) == ins->getParams().groupId);
+               break;
+       }
+
+       case LFUN_NEWPAGE_INSERT:
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
+               break;
+
+       case LFUN_MATH_INSERT:
+       case LFUN_MATH_MATRIX:
+       case LFUN_MATH_DELIM:
+       case LFUN_MATH_BIGDELIM:
+               // not allowed in ERT, for example.
+               enable = cur.inset().insetAllowed(MATH_CODE);
+               break;
+
+       case LFUN_DATE_INSERT: {
+               string const format = cmd.argument().empty()
+                       ? lyxrc.date_insert_format : to_utf8(cmd.argument());
+               enable = support::os::is_valid_strftime(format);
+               break;
+       }
+
        case LFUN_WORD_DELETE_FORWARD:
        case LFUN_WORD_DELETE_BACKWARD:
        case LFUN_LINE_DELETE:
@@ -2171,11 +2341,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_LINE_BEGIN:
        case LFUN_LINE_END:
        case LFUN_CHAR_DELETE_FORWARD:
-       case LFUN_DELETE_FORWARD_SKIP:
        case LFUN_CHAR_DELETE_BACKWARD:
-       case LFUN_DELETE_BACKWARD_SKIP:
        case LFUN_BREAK_PARAGRAPH:
-       case LFUN_BREAK_PARAGRAPH_SKIP:
        case LFUN_PARAGRAPH_SPACING:
        case LFUN_INSET_INSERT:
        case LFUN_WORD_UPCASE:
@@ -2184,29 +2351,21 @@ 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_MATH_DISPLAY:
-       case LFUN_MATH_IMPORT_SELECTION:
        case LFUN_MATH_MODE:
        case LFUN_MATH_MACRO:
-       case LFUN_MATH_MATRIX:
-       case LFUN_MATH_DELIM:
-       case LFUN_MATH_BIGDELIM:
-       case LFUN_MATH_INSERT:
        case LFUN_MATH_SUBSCRIPT:
        case LFUN_MATH_SUPERSCRIPT:
        case LFUN_FONT_DEFAULT:
        case LFUN_FONT_UNDERLINE:
        case LFUN_FONT_SIZE:
        case LFUN_LANGUAGE:
-       case LFUN_FONT_FREE_APPLY:
-       case LFUN_FONT_FREE_UPDATE:
+       case LFUN_TEXTSTYLE_APPLY:
+       case LFUN_TEXTSTYLE_UPDATE:
        case LFUN_LAYOUT_PARAGRAPH:
        case LFUN_PARAGRAPH_UPDATE:
        case LFUN_ACCENT_UMLAUT:
@@ -2220,7 +2379,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_ACCENT_UNDERDOT:
        case LFUN_ACCENT_UNDERBAR:
        case LFUN_ACCENT_CARON:
-       case LFUN_ACCENT_SPECIAL_CARON:
        case LFUN_ACCENT_BREVE:
        case LFUN_ACCENT_TIE:
        case LFUN_ACCENT_HUNGARIAN_UMLAUT:
@@ -2230,10 +2388,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_PARAGRAPH_PARAMS_APPLY:
        case LFUN_PARAGRAPH_PARAMS:
        case LFUN_ESCAPE:
-       case LFUN_BUFFER_END:
        case LFUN_BUFFER_BEGIN:
+       case LFUN_BUFFER_END:
        case LFUN_BUFFER_BEGIN_SELECT:
        case LFUN_BUFFER_END_SELECT:
+       case LFUN_INSET_BEGIN:
+       case LFUN_INSET_END:
+       case LFUN_INSET_BEGIN_SELECT:
+       case LFUN_INSET_END_SELECT:
        case LFUN_UNICODE_INSERT:
                // these are handled in our dispatch()
                enable = true;
@@ -2247,7 +2409,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
            && (cur.empty() || !cur.inset().insetAllowed(code)))
                enable = false;
 
-       flag.enabled(enable);
+       flag.setEnabled(enable);
        return true;
 }
 
@@ -2265,4 +2427,22 @@ void Text::pasteString(Cursor & cur, docstring const & clip,
        }
 }
 
+
+// FIXME: an item inset would make things much easier.
+bool Text::inDescriptionItem(Cursor & cur) const
+{
+       Paragraph & par = cur.paragraph();
+       pos_type const pos = cur.pos();
+       pos_type const body_pos = par.beginOfBody();
+
+       if (par.layout().latextype != LATEX_LIST_ENVIRONMENT
+           && (par.layout().latextype != LATEX_ITEM_ENVIRONMENT
+               || par.layout().margintype != MARGIN_FIRST_DYNAMIC))
+               return false;
+
+       return (pos < body_pos
+               || (pos == body_pos
+                   && (pos == 0 || par.getChar(pos - 1) != ' ')));
+}
+
 } // namespace lyx