]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
listerrors.lyx : Update a link.
[lyx.git] / src / Text3.cpp
index e5a1814b0e5cc8300698d59ad4ee605cec33ad95..4c1d07bf46720cc8141b32cc79ba8a6034e76647 100644 (file)
@@ -45,7 +45,6 @@
 #include "SpellChecker.h"
 #include "TextClass.h"
 #include "TextMetrics.h"
-#include "VSpace.h"
 #include "WordLangTuple.h"
 
 #include "frontends/Application.h"
@@ -68,6 +67,7 @@
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/gettext.h"
+#include "support/lassert.h"
 #include "support/lstrings.h"
 #include "support/lyxtime.h"
 #include "support/os.h"
@@ -93,6 +93,7 @@ using cap::pasteClipboardGraphics;
 using cap::replaceSelection;
 using cap::grabAndEraseSelection;
 using cap::selClearOrDel;
+using cap::pasteSimpleText;
 
 // globals...
 static Font freefont(ignore_font, ignore_language);
@@ -245,8 +246,11 @@ static bool doInsertInset(Cursor & cur, Text * text,
                if (edit)
                        inset->edit(cur, true);
                // Now put this into inset
-               cur.text()->insertStringAsLines(cur, ds, cur.current_font);
-               cur.leaveInset(*inset);
+               Font const f(inherit_font, cur.current_font.language());
+               if (!ds.empty()) {
+                       cur.text()->insertStringAsLines(cur, ds, f);
+                       cur.leaveInset(*inset);
+               }
                return true;
        }
 
@@ -268,10 +272,10 @@ static bool doInsertInset(Cursor & cur, Text * text,
        cur.buffer()->errors("Paste");
        cur.clearSelection(); // bug 393
        cur.finishUndo();
-       InsetText * insetText = dynamic_cast<InsetText *>(inset);
-       if (insetText) {
-               insetText->fixParagraphsFont();
-               if (!insetText->allowMultiPar() || cur.lastpit() == 0) {
+       InsetText * inset_text = inset->asInsetText();
+       if (inset_text) {
+               inset_text->fixParagraphsFont();
+               if (!inset_text->allowMultiPar() || cur.lastpit() == 0) {
                        // reset first par to default
                        cur.text()->paragraphs().begin()
                                ->setPlainOrDefaultLayout(bparams.documentClass());
@@ -464,12 +468,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // 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();
+       cur.noScreenUpdate();
 
        LASSERT(cur.text() == this, /**/);
-       CursorSlice oldTopSlice = cur.top();
-       bool oldBoundary = cur.boundary();
-       bool sel = cur.selection();
+       CursorSlice const oldTopSlice = cur.top();
+       bool const oldBoundary = cur.boundary();
+       bool const oldSelection = cur.selection();
        // Signals that, even if needsUpdate == false, an update of the
        // cursor paragraph is required
        bool singleParUpdate = lyxaction.funcHasFlag(cmd.action(),
@@ -477,7 +481,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // Signals that a full-screen update is required
        bool needsUpdate = !(lyxaction.funcHasFlag(cmd.action(),
                LyXAction::NoUpdate) || singleParUpdate);
-
+       bool const last_misspelled = lyxrc.spellcheck_continuously
+               && cur.paragraph().isMisspelled(cur.pos(), true);
+       
        FuncCode const act = cmd.action();
        switch (act) {
 
@@ -486,8 +492,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit, pit + 1);
                cur.finishUndo();
                pars_.swap(pit, pit + 1);
-               cur.buffer()->updateBuffer();
                needsUpdate = true;
+               cur.forceBufferUpdate();
                ++cur.pit();
                break;
        }
@@ -497,9 +503,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit - 1, pit);
                cur.finishUndo();
                pars_.swap(pit, pit - 1);
-               cur.buffer()->updateBuffer();
                --cur.pit();
                needsUpdate = true;
+               cur.forceBufferUpdate();
                break;
        }
 
@@ -523,7 +529,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                par.params().startOfAppendix(start);
 
                // we can set the refreshing parameters now
-               cur.buffer()->updateBuffer();
+               cur.forceBufferUpdate();
                break;
        }
 
@@ -558,7 +564,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cursorTop(cur);
                else
                        cur.undispatched();
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_BUFFER_END:
@@ -568,7 +574,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cursorBottom(cur);
                else
                        cur.undispatched();
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_INSET_BEGIN:
@@ -578,7 +584,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cursorTop(cur);
                else
                        cur.undispatched();
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_INSET_END:
@@ -588,7 +594,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cursorBottom(cur);
                else
                        cur.undispatched();
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_INSET_SELECT_ALL:
@@ -600,7 +606,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cursorBottom(cur);
                } else 
                        cur.undispatched();
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_CHAR_FORWARD:
@@ -624,7 +630,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                // provide it with two different cursors.
                                Cursor dummy = cur;
                                dummy.pos() = dummy.pit() = 0;
-                               cur.bv().checkDepm(dummy, cur);
+                               if (cur.bv().checkDepm(dummy, cur)) {
+                                       cur.forceBufferUpdate();
+                                       // DEPM may have requested a screen update
+                                       cur.screenUpdateFlags(
+                                               cur.screenUpdate() | dummy.screenUpdate());
+                               }
                        }
                }
                break;
@@ -650,7 +661,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                Cursor dummy = cur;
                                dummy.pos() = cur.lastpos();
                                dummy.pit() = cur.lastpit();
-                               cur.bv().checkDepm(dummy, cur);
+                               if (cur.bv().checkDepm(dummy, cur)) {
+                                       cur.forceBufferUpdate();
+                                       // DEPM may have requested a screen update
+                                       cur.screenUpdateFlags(
+                                               cur.screenUpdate() | dummy.screenUpdate());
+                               }
                        }
                }
                break;
@@ -817,6 +833,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_WORD_FORWARD_SELECT:
                needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_FORWARD_SELECT);
                needsUpdate |= cursorForwardOneWord(cur);
+
+               if (!needsUpdate && oldTopSlice == cur.top()
+                               && cur.boundary() == oldBoundary) {
+                       cur.undispatched();
+                       cmd = FuncRequest(LFUN_FINISHED_FORWARD);
+               
+                       // we will probably be moving out the inset, so we should execute
+                       // the depm-mechanism, but only when the cursor has a place to 
+                       // go outside this inset, i.e. in a slice above.
+                       if (cur.depth() > 1 && cur.pos() == cur.lastpos() 
+                                 && cur.pit() == cur.lastpit()) {
+                               // The cursor hasn't changed yet. To give the 
+                               // DEPM the possibility of doing something we must
+                               // provide it with two different cursors.
+                               Cursor dummy = cur;
+                               dummy.pos() = dummy.pit() = 0;
+                               if (cur.bv().checkDepm(dummy, cur)) {
+                                       cur.forceBufferUpdate();
+                                       // DEPM may have requested a screen update
+                                       cur.screenUpdateFlags(
+                                               cur.screenUpdate() | dummy.screenUpdate());
+                               }
+                       }
+               }
                break;
 
        case LFUN_WORD_LEFT:
@@ -846,6 +886,31 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_WORD_BACKWARD_SELECT:
                needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_BACKWARD_SELECT);
                needsUpdate |= cursorBackwardOneWord(cur);
+       
+               if (!needsUpdate && oldTopSlice == cur.top()
+                               && cur.boundary() == oldBoundary) {
+                       cur.undispatched();
+                       cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
+               
+                       // we will probably be moving out the inset, so we should execute
+                       // the depm-mechanism, but only when the cursor has a place to 
+                       // go outside this inset, i.e. in a slice above.
+                       if (cur.depth() > 1 && cur.pos() == 0 
+                                 && cur.pit() == 0) {
+                               // The cursor hasn't changed yet. To give the 
+                               // DEPM the possibility of doing something we must
+                               // provide it with two different cursors.
+                               Cursor dummy = cur;
+                               dummy.pos() = cur.lastpos();
+                               dummy.pit() = cur.lastpit();
+                               if (cur.bv().checkDepm(dummy, cur)) {
+                                       cur.forceBufferUpdate();
+                                       // DEPM may have requested a screen update
+                                       cur.screenUpdateFlags(
+                                               cur.screenUpdate() | dummy.screenUpdate());
+                               }
+                       }
+               }
                break;
 
        case LFUN_WORD_SELECT: {
@@ -909,24 +974,22 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        pit_type const pit_end = cur.selEnd().pit();
                        for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
                                Paragraph & par = paragraphs()[pit];
-                               if (par.getChar(0) == '\t') {
-                                       if (cur.pit() == pit)
-                                               cur.posBackward();
-                                       if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 )
-                                               cur.realAnchor().backwardPos();
-                                       
-                                       par.eraseChar(0, tc);
-                               } else 
-                                       // If no tab was present, try to remove up to four spaces.
-                                       for (int n_spaces = 0;
-                                            par.getChar(0) == ' ' && n_spaces < 4; ++n_spaces) {
+                               if (par.empty())
+                                       continue;
+                               char_type const c = par.getChar(0);
+                               if (c == '\t' || c == ' ') {
+                                       // remove either 1 tab or 4 spaces.
+                                       int const n = (c == ' ' ? 4 : 1);
+                                       for (int i = 0; i < n 
+                                                 && !par.empty() && par.getChar(0) == c; ++i) {
                                                if (cur.pit() == pit)
                                                        cur.posBackward();
-                                               if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 )
+                                               if (cur.realAnchor().pit() == pit 
+                                                         && cur.realAnchor().pos() > 0 )
                                                        cur.realAnchor().backwardPos();
-                                               
                                                par.eraseChar(0, tc);
                                        }
+                               }
                        }
                        cur.finishUndo();
                } else {
@@ -1032,7 +1095,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        if (cur.selection())
                                cutSelection(cur, true, false);
                        cur.insert(inset);
-                       cur.posForward();
+                       if (inset->editable() && inset->asInsetText())
+                               inset->edit(cur, true);
+                       else
+                               cur.posForward();
 
                        // trigger InstantPreview now
                        if (inset->lyxCode() == EXTERNAL_CODE) {
@@ -1046,8 +1112,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_INSET_DISSOLVE: {
-               if (dissolveInset(cur))
+               if (dissolveInset(cur)) {
                        needsUpdate = true;
+                       cur.forceBufferUpdate();
+               }
                break;
        }
 
@@ -1269,6 +1337,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bv->buffer().errors("Paste");
                break;
 
+       case LFUN_CLIPBOARD_PASTE_SIMPLE:
+               cur.clearSelection();
+               pasteSimpleText(cur, cmd.argument() == "paragraph");
+               break;
+
        case LFUN_PRIMARY_SELECTION_PASTE:
                pasteString(cur, theSelection().get(),
                            cmd.argument() == "paragraph");
@@ -1299,33 +1372,34 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_QUOTE_INSERT: {
-               Paragraph & par = cur.paragraph();
+               // this avoids a double undo
+               // FIXME: should not be needed, ideally
+               if (!cur.selection())
+                       cur.recordUndo();
+               cap::replaceSelection(cur);
+
+               Paragraph const & par = cur.paragraph();
                pos_type pos = cur.pos();
+
                BufferParams const & bufparams = bv->buffer().params();
-               Layout const & style = par.layout();
-               InsetLayout const & ilayout = cur.inset().getLayout();
-               if (!style.pass_thru && !ilayout.isPassThru()
-                   && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") {
-                       // this avoids a double undo
-                       // FIXME: should not be needed, ideally
-                       if (!cur.selection())
-                               cur.recordUndo();
-                       cap::replaceSelection(cur);
-                       pos = cur.pos();
-                       char_type c;
-                       if (pos == 0)
-                               c = ' ';
-                       else if (cur.prevInset() && cur.prevInset()->isSpace())
-                               c = ' ';
-                       else
+               bool const hebrew = 
+                       par.getFontSettings(bufparams, pos).language()->lang() == "hebrew";
+               bool const allow_inset_quote = !(par.isPassThru() || hebrew);
+               
+               if (allow_inset_quote) {
+                       char_type c = ' ';
+                       if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace()))
                                c = par.getChar(pos - 1);
-                       string arg = to_utf8(cmd.argument());
-                       cur.insert(new InsetQuotes(cur.buffer(), c, (arg == "single")
-                               ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes));
+                       string const arg = to_utf8(cmd.argument());
+                       InsetQuotes::QuoteTimes const quote_type = (arg == "single")
+                               ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes;
+                       cur.insert(new InsetQuotes(cur.buffer(), c, quote_type));
                        cur.posForward();
-               }
-               else
+               } else {
+                       // The cursor might have been invalidated by the replaceSelection.
+                       cur.buffer()->changed(true);
                        lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, "\""));
+               }                       
                break;
        }
 
@@ -1363,7 +1437,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                case mouse_button::button1:
                        // Set the cursor
                        if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select"))
-                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                               cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
                        if (bvcur.wordSelection())
                                selectWord(bvcur, WHOLE_WORD);
                        break;
@@ -1374,7 +1448,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        lyx::dispatch(
                                FuncRequest(LFUN_COMMAND_ALTERNATIVES,
                                            "selection-paste ; primary-selection-paste paragraph"));
-                       cur.noUpdate();
+                       cur.noScreenUpdate();
                        break;
 
                case mouse_button::button3: {
@@ -1382,11 +1456,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        // selection, a context menu will popup.
                        if (bvcur.selection() && cur >= bvcur.selectionBegin()
                            && cur < bvcur.selectionEnd()) {
-                               cur.noUpdate();
+                               cur.noScreenUpdate();
                                return;
                        }
                        if (!bv->mouseSetCursor(cur, false))
-                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                               cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
                        break;
                }
 
@@ -1398,7 +1472,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_MOUSE_MOTION: {
                // Mouse motion with right or middle mouse do nothing for now.
                if (cmd.button() != mouse_button::button1) {
-                       cur.noUpdate();
+                       cur.noScreenUpdate();
                        return;
                }
                // ignore motions deeper nested than the real anchor
@@ -1431,8 +1505,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                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);
-                       //cur.noUpdate();
+                       cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
+                       //cur.noScreenUpdate();
                        return;
                }
                break;
@@ -1453,23 +1527,23 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                cur.bv().cursor().setSelection();
                                // We might have removed an empty but drawn selection
                                // (probably a margin)
-                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                               cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
                        } else
-                               cur.noUpdate();
+                               cur.noScreenUpdate();
                        // FIXME: We could try to handle drag and drop of selection here.
                        return;
 
                case mouse_button::button2:
                        // Middle mouse pasting is handled at mouse press time,
                        // see LFUN_MOUSE_PRESS.
-                       cur.noUpdate();
+                       cur.noScreenUpdate();
                        return;
 
                case mouse_button::button3:
                        // Cursor was set at LFUN_MOUSE_PRESS time.
                        // FIXME: If there is a selection we could try to handle a special
                        // drag & drop context menu.
-                       cur.noUpdate();
+                       cur.noScreenUpdate();
                        return;
 
                case mouse_button::none:
@@ -1502,6 +1576,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
                cur.resetAnchor();
                moveCursor(cur, false);
+               cur.markNewWordPosition();
                bv->bookmarkEditPosition();
                break;
        }
@@ -1515,7 +1590,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                p["target"] = (cmd.argument().empty()) ?
                        content : cmd.argument();
-               string const data = InsetCommand::params2string("href", p);
+               string const data = InsetCommand::params2string(p);
                if (p["target"].empty()) {
                        bv->showDialog("href", data);
                } else {
@@ -1531,7 +1606,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                p["name"] = (cmd.argument().empty()) ?
                        cur.getPossibleLabel() :
                        cmd.argument();
-               string const data = InsetCommand::params2string("label", p);
+               string const data = InsetCommand::params2string(p);
 
                if (cmd.argument().empty()) {
                        bv->showDialog("label", data);
@@ -1573,13 +1648,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_ARGUMENT_INSERT:
        case LFUN_INDEX_INSERT:
        case LFUN_PREVIEW_INSERT:
+       case LFUN_SCRIPT_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.
-               bv->buffer().updateBuffer();
+               cur.forceBufferUpdate();
                break;
 
        case LFUN_TABULAR_INSERT:
@@ -1633,8 +1709,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // date metrics.
                FuncRequest cmd_caption(LFUN_CAPTION_INSERT);
                doInsertInset(cur, cur.text(), cmd_caption, true, false);
-               bv->buffer().updateBuffer();
-               cur.updateFlags(Update::Force);
+               cur.forceBufferUpdate();
+               cur.screenUpdateFlags(Update::Force);
                // FIXME: When leaving the Float (or Wrap) inset we should
                // delete any empty paragraph left above or below the
                // caption.
@@ -1647,7 +1723,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        p["symbol"] = bv->cursor().innerText()->getStringToIndex(bv->cursor());
                else
                        p["symbol"] = cmd.argument();
-               string const data = InsetCommand::params2string("nomenclature", p);
+               string const data = InsetCommand::params2string(p);
                bv->showDialog("nomenclature", data);
                break;
        }
@@ -1658,15 +1734,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        p["type"] = from_ascii("idx");
                else
                        p["type"] = cmd.argument();
-               string const data = InsetCommand::params2string("index_print", p);
+               string const data = InsetCommand::params2string(p);
                FuncRequest fr(LFUN_INSET_INSERT, data);
                dispatch(cur, fr);
                break;
        }
        
        case LFUN_NOMENCL_PRINT:
-       case LFUN_TOC_INSERT:
-       case LFUN_LINE_INSERT:
        case LFUN_NEWPAGE_INSERT:
                // do nothing fancy
                doInsertInset(cur, this, cmd, false, false);
@@ -1692,6 +1766,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_MATH_MODE:
                if (cmd.argument() == "on")
                        // don't pass "on" as argument
+                       // (it would appear literally in the first cell)
                        mathDispatch(cur, FuncRequest(LFUN_MATH_MODE), false);
                else
                        mathDispatch(cur, cmd, false);
@@ -1701,6 +1776,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (cmd.argument().empty())
                        cur.errorMessage(from_utf8(N_("Missing argument")));
                else {
+                       cur.recordUndo();
                        string s = to_utf8(cmd.argument());
                        string const s1 = token(s, ' ', 1);
                        int const nargs = s1.empty() ? 0 : convert<int>(s1);
@@ -1839,8 +1915,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                Language const * lang = languages.getLanguage(to_utf8(cmd.argument()));
                if (!lang)
                        break;
+               selectWordWhenUnderCursor(cur, WHOLE_WORD_STRICT);
                Font font(ignore_font, lang);
-               toggleAndShow(cur, this, font);
+               toggleAndShow(cur, this, font, false);
                break;
        }
 
@@ -1938,6 +2015,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (!cmd.argument().empty())
                        // FIXME: Are all these characters encoded in one byte in utf8?
                        bv->translateAndInsert(cmd.argument()[0], this, cur);
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_FLOAT_LIST_INSERT: {
@@ -2038,6 +2116,25 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_SPELLING_REMOVE: {
+               docstring word = from_utf8(cmd.getArg(0));
+               Language * lang;
+               if (word.empty()) {
+                       word = cur.selectionAsString(false);
+                       // FIXME
+                       if (word.size() > 100 || word.empty()) {
+                               // Get word or selection
+                               selectWordWhenUnderCursor(cur, WHOLE_WORD);
+                               word = cur.selectionAsString(false);
+                       }
+                       lang = const_cast<Language *>(cur.getFont().language());
+               } else
+                       lang = const_cast<Language *>(languages.getLanguage(cmd.getArg(1)));
+               WordLangTuple wl(word, lang);
+               theSpellChecker()->remove(wl);
+               break;
+       }
+
        case LFUN_PARAGRAPH_PARAMS_APPLY: {
                // Given data, an encoding of the ParagraphParameters
                // generated in the Paragraph dialog, this function sets
@@ -2074,26 +2171,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_OUTLINE_UP:
                outline(OutlineUp, cur);
                setCursor(cur, cur.pit(), 0);
-               cur.buffer()->updateBuffer();
+               cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_DOWN:
                outline(OutlineDown, cur);
                setCursor(cur, cur.pit(), 0);
-               cur.buffer()->updateBuffer();
+               cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_IN:
                outline(OutlineIn, cur);
-               cur.buffer()->updateBuffer();
+               cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_OUT:
                outline(OutlineOut, cur);
-               cur.buffer()->updateBuffer();
+               cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
@@ -2105,12 +2202,27 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection();
 
+       if (lyxrc.spellcheck_continuously && !needsUpdate) {
+               // Check for misspelled text
+               // The redraw is useful because of the painting of
+               // misspelled markers depends on the cursor position.
+               // Trigger a redraw for cursor moves inside misspelled text.
+               if (!cur.inTexted()) {
+                       // move from regular text to math
+                       needsUpdate = last_misspelled;
+               } else if (oldTopSlice != cur.top() || oldBoundary != cur.boundary()) {
+                       // move inside regular text
+                       needsUpdate = last_misspelled
+                               || cur.paragraph().isMisspelled(cur.pos(), true);
+               }
+       }
+
        // FIXME: The cursor flag is reset two lines below
        // so we need to check here if some of the LFUN did touch that.
        // for now only Text::erase() and Text::backspace() do that.
        // The plan is to verify all the LFUNs and then to remove this
        // singleParUpdate boolean altogether.
-       if (cur.result().update() & Update::Force) {
+       if (cur.result().screenUpdate() & Update::Force) {
                singleParUpdate = false;
                needsUpdate = true;
        }
@@ -2121,27 +2233,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // 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);
+               cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
                return;
        }
-
        if (!needsUpdate
            && &oldTopSlice.inset() == &cur.inset()
            && oldTopSlice.idx() == cur.idx()
-           && !sel // sel is a backup of cur.selection() at the beginning of the function.
+           && !oldSelection // oldSelection is a backup of cur.selection() at the beginning of the function.
            && !cur.selection())
                // FIXME: it would be better if we could just do this
                //
                //if (cur.result().update() != Update::FitCursor)
-               //      cur.noUpdate();
+               //      cur.noScreenUpdate();
                //
                // But some LFUNs do not set Update::FitCursor when needed, so we
                // do it for all. This is not very harmfull as FitCursor will provoke
                // a full redraw only if needed but still, a proper review of all LFUN
                // should be done and this needsUpdate boolean can then be removed.
-               cur.updateFlags(Update::FitCursor);
+               cur.screenUpdateFlags(Update::FitCursor);
        else
-               cur.updateFlags(Update::Force | Update::FitCursor);
+               cur.screenUpdateFlags(Update::Force | Update::FitCursor);
 }
 
 
@@ -2204,6 +2315,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        code = NOMENCL_PRINT_CODE;
                else if (cmd.argument() == "label")
                        code = LABEL_CODE;
+               else if (cmd.argument() == "line")
+                       code = LINE_CODE;
                else if (cmd.argument() == "note")
                        code = NOTE_CODE;
                else if (cmd.argument() == "phantom")
@@ -2287,7 +2400,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        // make sure we know about such floats
                        if (cit == floats.end() ||
                                        // and that we know how to generate a list of them
-                           (!cit->second.needsFloatPkg() && cit->second.listCommand().empty())) {
+                           (!cit->second.usesFloatPkg() && cit->second.listCommand().empty())) {
                                flag.setUnknown(true);
                                // probably not necessary, but...
                                enable = false;
@@ -2335,9 +2448,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_LABEL_INSERT:
                code = LABEL_CODE;
                break;
-       case LFUN_LINE_INSERT:
-               code = LINE_CODE;
-               break;
        case LFUN_INFO_INSERT:
                code = INFO_CODE;
                break;
@@ -2368,11 +2478,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                // not allowed in description items
                enable = !inDescriptionItem(cur);
                break;
-       case LFUN_TOC_INSERT:
-               code = TOC_CODE;
-               // not allowed in description items
-               enable = !inDescriptionItem(cur);
-               break;
        case LFUN_HYPERLINK_INSERT:
                if (cur.selIsMultiCell() || cur.selIsMultiLine()) {
                        enable = false;
@@ -2395,6 +2500,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_PREVIEW_INSERT:
                code = PREVIEW_CODE;
                break;
+       case LFUN_SCRIPT_INSERT:
+               code = SCRIPT_CODE;
+               break;
 
        case LFUN_MATH_INSERT:
        case LFUN_MATH_AMS_MATRIX:
@@ -2424,38 +2532,38 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_FONT_EMPH:
                flag.setOnOff(fontinfo.emph() == FONT_ON);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_ITAL:
                flag.setOnOff(fontinfo.shape() == ITALIC_SHAPE);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_NOUN:
                flag.setOnOff(fontinfo.noun() == FONT_ON);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_BOLD:
        case LFUN_FONT_BOLDSYMBOL:
                flag.setOnOff(fontinfo.series() == BOLD_SERIES);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_SANS:
                flag.setOnOff(fontinfo.family() == SANS_FAMILY);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_ROMAN:
                flag.setOnOff(fontinfo.family() == ROMAN_FAMILY);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_FONT_TYPEWRITER:
                flag.setOnOff(fontinfo.family() == TYPEWRITER_FAMILY);
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_CUT:
@@ -2499,6 +2607,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
         }
 
        case LFUN_CLIPBOARD_PASTE:
+       case LFUN_CLIPBOARD_PASTE_SIMPLE:
                enable = !theClipboard().empty();
                break;
 
@@ -2549,7 +2658,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_TAB_INSERT:
        case LFUN_TAB_DELETE:
-               enable = cur.inset().getLayout().isPassThru();
+               enable = cur.paragraph().isPassThru();
                break;
 
        case LFUN_SET_GRAPHICS_GROUP: {
@@ -2575,7 +2684,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        }
 
        case LFUN_LANGUAGE:
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                flag.setOnOff(to_utf8(cmd.argument()) == cur.real_current_font.language()->lang());
                break;
 
@@ -2585,6 +2694,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        
        case LFUN_SPELLING_ADD:
        case LFUN_SPELLING_IGNORE:
+       case LFUN_SPELLING_REMOVE:
                enable = theSpellChecker();
                break;
 
@@ -2626,7 +2736,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_FONT_UWAVE:
        case LFUN_TEXTSTYLE_APPLY:
        case LFUN_TEXTSTYLE_UPDATE:
-               enable = !cur.inset().getLayout().isPassThru();
+               enable = !cur.paragraph().isPassThru();
                break;
 
        case LFUN_WORD_DELETE_FORWARD:
@@ -2673,7 +2783,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_LINE_END:
        case LFUN_CHAR_DELETE_FORWARD:
        case LFUN_CHAR_DELETE_BACKWARD:
-       case LFUN_INSET_INSERT:
        case LFUN_WORD_UPCASE:
        case LFUN_WORD_LOWCASE:
        case LFUN_WORD_CAPITALIZE:
@@ -2689,6 +2798,19 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = true;
                break;
 
+       case LFUN_INSET_INSERT: {
+               string const type = cmd.getArg(0);
+               if (type == "toc") {
+                       code = TOC_CODE;
+                       // not allowed in description items
+                       //FIXME: couldn't this be merged in Inset::insetAllowed()?
+                       enable = !inDescriptionItem(cur);
+               } else {
+                       enable = true;
+               }
+               break;
+       }
+
        default:
                return false;
        }