]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
even example code should follow the style conventions
[lyx.git] / src / Text3.cpp
index 5e7bf51c7f9eb63584f914304b1de7ec2204c15c..80f782d8057101f000534312a2ac6f9c3c7deb9b 100644 (file)
 #include "BufferView.h"
 #include "Cursor.h"
 #include "CutAndPaste.h"
-#include "support/debug.h"
 #include "DispatchResult.h"
 #include "ErrorList.h"
 #include "factory.h"
 #include "FuncRequest.h"
-#include "support/gettext.h"
 #include "InsetList.h"
 #include "Intl.h"
 #include "Language.h"
@@ -44,7 +42,6 @@
 #include "Paragraph.h"
 #include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
-#include "ParIterator.h"
 #include "TextClass.h"
 #include "TextMetrics.h"
 #include "VSpace.h"
 #include "insets/InsetText.h"
 #include "insets/InsetInfo.h"
 
-#include "support/lstrings.h"
 #include "support/convert.h"
+#include "support/debug.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
 #include "support/lyxtime.h"
 
 #include "mathed/InsetMathHull.h"
@@ -81,7 +80,8 @@ namespace lyx {
 using cap::copySelection;
 using cap::cutSelection;
 using cap::pasteFromStack;
-using cap::pasteClipboard;
+using cap::pasteClipboardText;
+using cap::pasteClipboardGraphics;
 using cap::replaceSelection;
 
 // globals...
@@ -149,13 +149,14 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
                // somewhere, and an ordinary formula
                // otherwise
                if (sel.find(from_ascii("\\newcommand")) == string::npos
+                               && sel.find(from_ascii("\\newlyxcommand")) == string::npos
                                && sel.find(from_ascii("\\def")) == string::npos)
                {
                        InsetMathHull * formula = new InsetMathHull;
                        istringstream is(to_utf8(sel));
                        Lexer lex(0, 0);
                        lex.setStream(is);
-                       formula->read(cur.buffer(), lex);
+                       formula->read(lex);
                        if (formula->getType() == hullNone)
                                // Don't create pseudo formulas if
                                // delimiters are left out
@@ -181,12 +182,14 @@ static void specialChar(Cursor & cur, InsetSpecialChar::Kind kind)
 static bool doInsertInset(Cursor & cur, Text * text,
        FuncRequest const & cmd, bool edit, bool pastesel)
 {
-       Inset * inset = createInset(cur.bv().buffer(), cmd);
+       Buffer & buffer = cur.bv().buffer();
+       BufferParams const & bparams = buffer.params();
+       Inset * inset = createInset(buffer, cmd);
        if (!inset)
                return false;
 
        if (InsetCollapsable * ci = inset->asInsetCollapsable())
-               ci->setLayout(cur.bv().buffer().params());
+               ci->setLayout(bparams);
 
        cur.recordUndo();
        if (cmd.action == LFUN_INDEX_INSERT) {
@@ -196,42 +199,42 @@ static bool doInsertInset(Cursor & cur, Text * text,
                        inset->edit(cur, true);
                // Now put this into inset
                static_cast<InsetCollapsable *>(inset)->text_.insertStringAsParagraphs(cur, ds);
-       } else {
-               bool gotsel = false;
-               if (cur.selection()) {
-                       lyx::dispatch(FuncRequest(LFUN_CUT));
-                       gotsel = true;
-               }
-               text->insertInset(cur, inset);
+               return true;
+       }
 
-               if (edit)
-                       inset->edit(cur, true);
+       bool gotsel = false;
+       if (cur.selection()) {
+               lyx::dispatch(FuncRequest(LFUN_CUT));
+               gotsel = true;
+       }
+       text->insertInset(cur, inset);
 
-               if (gotsel && pastesel) {
-                       lyx::dispatch(FuncRequest(LFUN_PASTE, "0"));
-                       InsetText * insetText = dynamic_cast<InsetText *>(inset);
-                       if (insetText && !insetText->allowMultiPar() 
-                           || cur.lastpit() == 0) {
-                               // reset first par to default
-                               LayoutPtr const layout =
-                                       cur.buffer().params().getTextClass().defaultLayout();
-                               cur.text()->paragraphs().begin()->layout(layout);
-                               cur.pos() = 0;
-                               cur.pit() = 0;
-                               // Merge multiple paragraphs -- hack
-                               while (cur.lastpit() > 0) {
-                                       mergeParagraph(cur.buffer().params(),
-                                               cur.text()->paragraphs(), 0);
-                               }
-                       } else {
-                               // reset surrounding par to default
-                               docstring const layoutname = 
-                                       cur.buffer().params().getTextClass().defaultLayoutName();
-                               cur.leaveInset(*inset);
-                               text->setLayout(cur, layoutname);
-                       }
-               }
+       if (edit)
+               inset->edit(cur, true);
+
+       if (!gotsel || !pastesel)
+               return true;
+
+       lyx::dispatch(FuncRequest(LFUN_PASTE, "0"));
+       InsetText * insetText = dynamic_cast<InsetText *>(inset);
+       if (insetText && !insetText->allowMultiPar() || cur.lastpit() == 0) {
+               // reset first par to default
+               cur.text()->paragraphs().begin()
+                       ->setEmptyOrDefaultLayout(bparams.documentClass());
+               cur.pos() = 0;
+               cur.pit() = 0;
+               // Merge multiple paragraphs -- hack
+               while (cur.lastpit() > 0)
+                       mergeParagraph(bparams, cur.text()->paragraphs(), 0);
+       } else {
+               // reset surrounding par to default
+               docstring const layoutname = insetText->useEmptyLayout()
+                       ? bparams.documentClass().emptyLayoutName()
+                       : bparams.documentClass().defaultLayoutName();
+               cur.leaveInset(*inset);
+               text->setLayout(cur, layoutname);
        }
+
        return true;
 }
 
@@ -263,40 +266,38 @@ static void outline(OutlineOp mode, Cursor & cur)
        ParagraphList::iterator finish = start;
        ParagraphList::iterator end = pars.end();
 
-       TextClass::const_iterator lit =
-               buf.params().getTextClass().begin();
-       TextClass::const_iterator const lend =
-               buf.params().getTextClass().end();
+       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
+       if (finish != end)
+               ++finish;
+       // Seek the one (on same level) below
+       for (; finish != end; ++finish) {
+               toclevel = finish->layout().toclevel;
+               if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel) {
+                       break;
+               }
+       }
+
        switch (mode) {
                case OutlineUp: {
-                       // Move out (down) from this section header
-                       if (finish != end)
-                               ++finish;
-                       // Seek the one (on same level) below
-                       for (; finish != end; ++finish) {
-                               toclevel = finish->layout()->toclevel;
-                               if (toclevel != Layout::NOT_IN_TOC
-                                   && toclevel <= thistoclevel) {
-                                       break;
-                               }
-                       }
                        ParagraphList::iterator dest = start;
                        // Move out (up) from this header
                        if (dest == bgn)
-                               break;
+                               return;
                        // 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));
                        // Not found; do nothing
                        if (toclevel == Layout::NOT_IN_TOC || toclevel > thistoclevel)
-                               break;
+                               return;
                        pit_type const newpit = distance(bgn, dest);
                        pit_type const len = distance(start, finish);
                        pit_type const deletepit = pit + len;
@@ -305,30 +306,10 @@ static void outline(OutlineOp mode, Cursor & cur)
                        start = boost::next(pars.begin(), deletepit);
                        pit = newpit;
                        pars.erase(start, finish);
-                       break;
+                       return;
                }
                case OutlineDown: {
-                       // Go down out of current header:
-                       if (finish != end)
-                               ++finish;
-                       // Find next same-level header:
-                       for (; finish != end; ++finish) {
-                               toclevel = finish->layout()->toclevel;
-                               if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel)
-                                       break;
-                       }
                        ParagraphList::iterator dest = finish;
-                       // Go one down from *this* header:
-                       if (dest != end)
-                               ++dest;
-                       else
-                               break;
-                       // 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);
@@ -337,30 +318,46 @@ static void outline(OutlineOp mode, Cursor & cur)
                        start = boost::next(bgn, pit);
                        pit = newpit - len;
                        pars.erase(start, finish);
-                       break;
+                       return;
                }
-               case OutlineIn:
-                       buf.undo().recordUndo(cur);
-                       for (; lit != lend; ++lit) {
-                               if ((*lit)->toclevel == thistoclevel + 1 &&
-                                   start->layout()->labeltype == (*lit)->labeltype) {
-                                       start->layout((*lit));
-                                       break;
+               case OutlineIn: {
+                       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;
+                               if (toclevel == Layout::NOT_IN_TOC)
+                                       continue;
+                               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;
+                                       }
                                }
                        }
-                       break;
-               case OutlineOut:
-                       buf.undo().recordUndo(cur);
-                       for (; lit != lend; ++lit) {
-                               if ((*lit)->toclevel == thistoclevel - 1 &&
-                                   start->layout()->labeltype == (*lit)->labeltype) {
-                                       start->layout((*lit));
-                                       break;
+                       return;
+               }
+               case OutlineOut: {
+                       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;
+                               if (toclevel == Layout::NOT_IN_TOC)
+                                       continue;
+                               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;
+                                       }
                                }
                        }
-                       break;
-               default:
-                       break;
+                       return;
+               }
        }
 }
 
@@ -369,7 +366,7 @@ void Text::number(Cursor & cur)
 {
        FontInfo font = ignore_font;
        font.setNumber(FONT_TOGGLE);
-       toggleAndShow(cur, this, Font(font));
+       toggleAndShow(cur, this, Font(font, ignore_language));
 }
 
 
@@ -383,14 +380,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 {
        LYXERR(Debug::ACTION, "Text::dispatch: cmd: " << cmd);
 
+       BufferView * bv = &cur.bv();
+       TextMetrics & tm = bv->textMetrics(this);
+       if (!tm.contains(cur.pit()))
+               lyx::dispatch(FuncRequest(LFUN_SCREEN_RECENTER));
+
        // 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
        // at the end?
        cur.noUpdate();
 
        BOOST_ASSERT(cur.text() == this);
-       BufferView * bv = &cur.bv();
-       TextMetrics & tm = cur.bv().textMetrics(this);
        CursorSlice oldTopSlice = cur.top();
        bool oldBoundary = cur.boundary();
        bool sel = cur.selection();
@@ -401,10 +401,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // Signals that a full-screen update is required
        bool needsUpdate = !(lyxaction.funcHasFlag(cmd.action,
                LyXAction::NoUpdate) || singleParUpdate);
-       // Remember the old paragraph metric (_outer_ paragraph!)
-       ParagraphMetrics const & pm = cur.bv().parMetrics(
-               cur.bottom().text(), cur.bottom().pit());
-       Dimension olddim = pm.dim();
 
        switch (cmd.action) {
 
@@ -486,6 +482,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                } else {
                        cur.undispatched();
                }
+               cur.updateFlags(Update::FitCursor);
                break;
 
        case LFUN_BUFFER_END:
@@ -496,6 +493,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                } else {
                        cur.undispatched();
                }
+               cur.updateFlags(Update::FitCursor);
                break;
 
        case LFUN_CHAR_FORWARD:
@@ -526,29 +524,50 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CHAR_LEFT:
        case LFUN_CHAR_LEFT_SELECT:
-               //FIXME: for visual cursor, really move left
-               if (reverseDirectionNeeded(cur)) {
-                       cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
-                                       LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
+               if (lyxrc.visual_cursor) {
+                       needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_LEFT_SELECT);
+                       needsUpdate |= cursorVisLeft(cur);
+                       if (!needsUpdate && oldTopSlice == cur.top()
+                                       && cur.boundary() == oldBoundary) {
+                               cur.undispatched();
+                               cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       }
                } else {
-                       cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                       if (reverseDirectionNeeded(cur)) {
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                                       LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
+                       } else {
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
                                        LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
+                       }
+                       dispatch(cur, cmd);
+                       return;
                }
-               dispatch(cur, cmd);
-               return;
+               break;
 
        case LFUN_CHAR_RIGHT:
        case LFUN_CHAR_RIGHT_SELECT:
-               //FIXME: for visual cursor, really move right
-               if (reverseDirectionNeeded(cur)) {
-                       cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
-                                       LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
+               if (lyxrc.visual_cursor) {
+                       needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_RIGHT_SELECT);
+                       needsUpdate |= cursorVisRight(cur);
+                       if (!needsUpdate && oldTopSlice == cur.top()
+                                       && cur.boundary() == oldBoundary) {
+                               cur.undispatched();
+                               cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       }
                } else {
-                       cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                       if (reverseDirectionNeeded(cur)) {
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                                       LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
+                       } else {
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
                                        LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
+                       }
+                       dispatch(cur, cmd);
+                       return;
                }
-               dispatch(cur, cmd);
-               return;
+               break;
+               
 
        case LFUN_UP_SELECT:
        case LFUN_DOWN_SELECT:
@@ -563,10 +582,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool up = cmd.action == LFUN_UP_SELECT || cmd.action == LFUN_UP;
                bool const successful = cur.upDownInText(up, needsUpdate);
                if (successful) {
-                       // notify insets which were left and get their update flags 
-                       notifyCursorLeaves(cur.beforeDispatchCursor(), cur);
-                       cur.fixIfBroken();
-                       
                        // redraw if you leave mathed (for the decorations)
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
                } else
@@ -587,25 +602,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);
@@ -829,7 +825,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':
@@ -841,7 +837,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        */
                        if (cur.selection())
                                cutSelection(cur, true, false);
-                       insertInset(cur, inset);
+                       cur.insert(inset);
                        cur.posForward();
                }
                break;
@@ -856,7 +852,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
        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);
@@ -904,22 +900,44 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                charsTranspose(cur);
                break;
 
-       case LFUN_PASTE:
+       case LFUN_PASTE: {
                cur.message(_("Paste"));
                cap::replaceSelection(cur);
-               if (cmd.argument().empty() && !theClipboard().isInternal())
-                       pasteClipboard(cur, bv->buffer().errorList("Paste"));
-               else {
-                       string const arg(to_utf8(cmd.argument()));
+
+               // without argument?
+               string const arg = to_utf8(cmd.argument());
+               if (arg.empty()) {
+                       if (theClipboard().isInternal())
+                               pasteFromStack(cur, bv->buffer().errorList("Paste"), 0);
+                       else if (theClipboard().hasGraphicsContents())
+                               pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"));
+                       else
+                               pasteClipboardText(cur, bv->buffer().errorList("Paste"));
+               } else if (isStrUnsignedInt(arg)) {
+                       // we have a numerical argument
                        pasteFromStack(cur, bv->buffer().errorList("Paste"),
-                                       isStrUnsignedInt(arg) ?
-                                               convert<unsigned int>(arg) :
-                                               0);
+                                      convert<unsigned int>(arg));
+               } else {
+                       Clipboard::GraphicsType type = Clipboard::AnyGraphicsType;
+                       if (arg == "pdf")
+                               type = Clipboard::PdfGraphicsType;
+                       else if (arg == "png")
+                               type = Clipboard::PngGraphicsType;
+                       else if (arg == "jpeg")
+                               type = Clipboard::JpegGraphicsType;
+                       else if (arg == "linkback")
+                               type = Clipboard::LinkBackGraphicsType;
+                       else
+                               BOOST_ASSERT(false);
+
+                       pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"), type);
                }
+
                bv->buffer().errors("Paste");
                cur.clearSelection(); // bug 393
                cur.finishUndo();
                break;
+       }
 
        case LFUN_CUT:
                cutSelection(cur, true, true);
@@ -960,25 +978,38 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
        case LFUN_SERVER_GET_LAYOUT:
-               cur.message(cur.paragraph().layout()->name());
+               cur.message(cur.paragraph().layout().name());
                break;
 
        case LFUN_LAYOUT: {
                docstring layout = cmd.argument();
                LYXERR(Debug::INFO, "LFUN_LAYOUT: (arg) " << to_utf8(layout));
 
-               docstring const old_layout = cur.paragraph().layout()->name();
+               Paragraph const & para = cur.paragraph();
+               docstring const old_layout = para.layout().name();
+               DocumentClass const & tclass = bv->buffer().params().documentClass();
 
-               // Derive layout number from given argument (string)
-               // and current buffer's textclass (number)
-               TextClass const & tclass = bv->buffer().params().getTextClass();
                if (layout.empty())
                        layout = tclass.defaultLayoutName();
+
+               if (para.forceEmptyLayout()) 
+                       // 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 
+                       if (layout == tclass.defaultLayoutName())
+                               layout = tclass.emptyLayoutName();
+               } else { 
+                       // otherwise, the empty layout maps to the default
+                       if (layout == tclass.emptyLayoutName())
+                               layout = tclass.defaultLayoutName();
+               }
+
                bool hasLayout = tclass.hasLayout(layout);
 
                // 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;
                }
@@ -997,7 +1028,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;
                                }
@@ -1013,7 +1044,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CLIPBOARD_PASTE:
                cur.clearSelection();
-               pasteClipboard(cur, bv->buffer().errorList("Paste"),
+               pasteClipboardText(cur, bv->buffer().errorList("Paste"),
                               cmd.argument() == "paragraph");
                bv->buffer().errors("Paste");
                break;
@@ -1042,8 +1073,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
@@ -1059,14 +1090,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
@@ -1279,7 +1305,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        docstring ds = cur.selectionAsString(false);
                        cutSelection(cur, true, false);
                        static_cast<InsetInfo *>(inset)->setInfo(to_utf8(ds));
-                       static_cast<InsetInfo *>(inset)->updateInfo(cur.bv().buffer());
+                       static_cast<InsetInfo *>(inset)->updateInfo();
                }
                insertInset(cur, inset);
                cur.posForward();
@@ -1287,17 +1313,9 @@ 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:
-               // Open the inset, and move the current selection
-               // inside it.
-               doInsertInset(cur, this, cmd, true, true);
-               cur.posForward();
-               // These insets are numbered.
-               updateLabels(bv->buffer());
-               break;
        case LFUN_NOTE_INSERT:
        case LFUN_FLEX_INSERT:
        case LFUN_BOX_INSERT:
@@ -1308,10 +1326,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        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.
                doInsertInset(cur, this, cmd, true, true);
                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());
                break;
 
        case LFUN_TABULAR_INSERT:
@@ -1332,13 +1354,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                cur.posForward();
                ParagraphList & pars = cur.text()->paragraphs();
 
-               TextClass const & tclass = bv->buffer().params().getTextClass();
+               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().layout(tclass.defaultLayout());
-
+               pars.back().setEmptyOrDefaultLayout(tclass);
                int cap_pit = pars.size() - 1;
 
                // if an empty inset was created, we create an additional empty
@@ -1347,8 +1368,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (!content) {
                        pars.push_back(Paragraph());
                        pars.back().setInsetOwner(pars[0].inInset());
-                       pars.back().layout(tclass.defaultLayout());
-
+                       pars.back().setEmptyOrDefaultLayout(tclass);
                }
 
                // reposition the cursor to the caption
@@ -1366,11 +1386,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_INDEX_INSERT:
-               doInsertInset(cur, this, cmd, true, true);
-               cur.posForward();
-               break;
-
        case LFUN_NOMENCL_INSERT: {
                FuncRequest cmd1 = cmd;
                if (cmd.argument().empty())
@@ -1393,7 +1408,6 @@ 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:
@@ -1433,8 +1447,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        string const s1 = token(s, ' ', 1);
                        int const nargs = s1.empty() ? 0 : convert<int>(s1);
                        string const s2 = token(s, ' ', 2);
-                       string const type = s2.empty() ? "newcommand" : s2;
-                       cur.insert(new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, from_utf8(type)));
+                       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);
                }
                break;
@@ -1553,18 +1569,24 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_LEFT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_LEFT:\n" << cur);
-               if (reverseDirectionNeeded(cur)) {
-                       ++cur.pos();
-                       cur.setCurrentFont();
-               }
+               // 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 
+               // entering the inset itself; i.e., move to after the inset.
+               if (cur.paragraph().getFontSettings(
+                               cur.bv().buffer().params(), cur.pos()).isRightToLeft())
+                       cursorVisLeft(cur, true);
                break;
 
        case LFUN_FINISHED_RIGHT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_RIGHT:\n" << cur);
-               if (!reverseDirectionNeeded(cur)) {
-                       ++cur.pos();
-                       cur.setCurrentFont();
-               }
+               // 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 
+               // entering the inset itself; i.e., move to after the inset.
+               if (!cur.paragraph().getFontSettings(
+                               cur.bv().buffer().params(), cur.pos()).isRightToLeft())
+                       cursorVisRight(cur, true);
                break;
 
        case LFUN_FINISHED_BACKWARD:
@@ -1590,7 +1612,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                params2string(cur.paragraph(), data);
 
                // Will the paragraph accept changes from the dialog?
-               bool const accept = !cur.inset().forceDefaultParagraphs(cur.idx());
+               bool const accept = 
+                       cur.inset().allowParagraphCustomization(cur.idx());
 
                data = "update " + convert<string>(accept) + '\n' + data;
                bv->updateDialog("paragraph", data);
@@ -1621,7 +1644,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
        case LFUN_FLOAT_LIST: {
-               TextClass const & tclass = bv->buffer().params().getTextClass();
+               DocumentClass const & tclass = bv->buffer().params().documentClass();
                if (tclass.floats().typeExist(to_utf8(cmd.argument()))) {
                        cur.recordUndo();
                        if (cur.selection())
@@ -1633,6 +1656,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                breakParagraph(cur);
                        }
 
+                       //FIXME Check if this should be emptyLayout()
                        setLayout(cur, tclass.defaultLayoutName());
                        ParagraphParameters p;
                        setParagraphs(cur, p);
@@ -1750,16 +1774,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // FIXME: the following code should go in favor of fine grained
        // update flag treatment.
        if (singleParUpdate) {
-               // Inserting characters does not change par height
-               ParagraphMetrics const & pms
-                       = cur.bv().parMetrics(cur.bottom().text(), cur.bottom().pit());
-               if (pms.dim().height() == olddim.height()) {
-                       // if so, update _only_ this paragraph
-                       cur.updateFlags(Update::SinglePar |
-                               Update::FitCursor);
-                       return;
-               }
-               needsUpdate = true;
+               // Inserting characters does not change par height in general. So, try
+               // to update _only_ this paragraph. BufferView will detect if a full
+               // metrics update is needed anyway.
+               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+               return;
        }
 
        if (!needsUpdate
@@ -1807,7 +1826,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;
 
@@ -1844,6 +1863,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")
@@ -1883,9 +1904,6 @@ 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;
@@ -1896,11 +1914,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_FLEX_INSERT: {
                code = FLEX_CODE;
                string s = cmd.getArg(0);
-               InsetLayout il =  cur.buffer().params().getTextClass().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() != "charstyle" &&
+                   il.lyxtype() != "custom" &&
+                   il.lyxtype() != "element" &&
+                   il.lyxtype ()!= "standard")
                        enable = false;
                break;
                }
@@ -1921,7 +1940,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;
@@ -1948,7 +1967,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;
@@ -1995,22 +2013,37 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = cur.selection();
                break;
 
-       case LFUN_PASTE:
+       case LFUN_PASTE: {
                if (cmd.argument().empty()) {
                        if (theClipboard().isInternal())
                                enable = cap::numberOfSelections() > 0;
                        else
                                enable = !theClipboard().empty();
-               } else {
-                       string const arg = to_utf8(cmd.argument());
-                       if (isStrUnsignedInt(arg)) {
-                               unsigned int n = convert<unsigned int>(arg);
-                               enable = cap::numberOfSelections() > n;
-                       } else
-                               // unknown argument
-                               enable = false;
+                       break;
                }
+               
+               // we have an argument
+               string const arg = to_utf8(cmd.argument());
+               if (isStrUnsignedInt(arg)) {
+                       // it's a number and therefore means the internal stack
+                       unsigned int n = convert<unsigned int>(arg);
+                       enable = cap::numberOfSelections() > n;
+                       break;
+               }
+               
+               // explicit graphics type?
+               if ((arg == "pdf" && theClipboard().hasGraphicsContents(Clipboard::PdfGraphicsType))
+                   || (arg == "png" && theClipboard().hasGraphicsContents(Clipboard::PngGraphicsType))
+                   || (arg == "jpeg" && theClipboard().hasGraphicsContents(Clipboard::JpegGraphicsType))
+                   || (arg == "linkback" && theClipboard().hasGraphicsContents(Clipboard::LinkBackGraphicsType))) {
+                       enable = true;
+                       break;
+               }
+               
+               // unknown argument
+               enable = false;
                break;
+        }
 
        case LFUN_CLIPBOARD_PASTE:
                enable = !theClipboard().empty();
@@ -2032,7 +2065,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                if (!cmd.argument().empty()) {
                        InsetLayout il = cur.inset().getLayout(cur.buffer().params());
                        enable = cur.inset().lyxCode() == FLEX_CODE
-                                && il.lyxtype == to_utf8(cmd.argument());
+                                && il.lyxtype() == to_utf8(cmd.argument());
                } else {
                        enable = !isMainText(cur.bv().buffer()) 
                                 && cur.inset().nargs() == 1;
@@ -2054,7 +2087,7 @@ 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_WORD_DELETE_FORWARD:
@@ -2078,8 +2111,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: