]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
Add commented-out code that might prove useful one day
[lyx.git] / src / Text3.cpp
index 5c623fec9e54fabf053004ba0d9b2fc80bba528f..148b1d4f8bb53ded73420b51af2ecc37e19ebcde 100644 (file)
@@ -58,6 +58,7 @@
 #include "insets/InsetGraphics.h"
 #include "insets/InsetGraphicsParams.h"
 #include "insets/InsetInfo.h"
+#include "insets/InsetIndexMacro.h"
 #include "insets/InsetIPAMacro.h"
 #include "insets/InsetNewline.h"
 #include "insets/InsetQuotes.h"
@@ -118,6 +119,11 @@ static void toggleAndShow(Cursor & cur, Text * text,
                                                       cur.real_current_font))
                        text->setCursor(cur, cur.pit(), cur.pos(),
                                        false, !cur.boundary());
+               if (font.language() != ignore_language)
+                       // We need a buffer update if we change the language
+                       // (e.g., with info insets or if the selection contains
+                       // a par label)
+                       cur.forceBufferUpdate();
        }
 }
 
@@ -238,7 +244,8 @@ static void ipaChar(Cursor & cur, InsetIPAChar::Kind kind)
 
 
 static bool doInsertInset(Cursor & cur, Text * text,
-       FuncRequest const & cmd, bool edit, bool pastesel)
+                         FuncRequest const & cmd, bool edit,
+                         bool pastesel, bool resetfont = false)
 {
        Buffer & buffer = cur.bv().buffer();
        BufferParams const & bparams = buffer.params();
@@ -252,7 +259,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
        cur.recordUndo();
        if (cmd.action() == LFUN_ARGUMENT_INSERT) {
                bool cotextinsert = false;
-               InsetArgument const * const ia = static_cast<InsetArgument const *>(inset);
+               InsetArgument * const ia = static_cast<InsetArgument *>(inset);
                Layout const & lay = cur.paragraph().layout();
                Layout::LaTeXArgMap args = lay.args();
                Layout::LaTeXArgMap::const_iterator const lait = args.find(ia->name());
@@ -275,6 +282,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
                        else
                                ds = cur.paragraph().asString();
                        text->insertInset(cur, inset);
+                       ia->init(cur.paragraph());
                        if (edit)
                                inset->edit(cur, true);
                        // Now put co-text into inset
@@ -298,8 +306,11 @@ static bool doInsertInset(Cursor & cur, Text * text,
                         * paragraph and the inset allows setting layout
                         * FIXME: this does not work as expected when change tracking is on
                         *   However, we do not really know what to do in this case.
+                        * FIXME: figure out a good test in the environment case (see #12251).
                         */
-                       if (cur.paragraph().empty() && !inset->forcePlainLayout()) {
+                       if (cur.paragraph().layout().isCommand()
+                            && cur.paragraph().empty()
+                            && !inset->forcePlainLayout()) {
                                cur.paragraph().setPlainOrDefaultLayout(bparams.documentClass());
                                move_layout = true;
                        }
@@ -313,6 +324,19 @@ static bool doInsertInset(Cursor & cur, Text * text,
        }
        text->insertInset(cur, inset);
 
+       InsetText * inset_text = inset->asInsetText();
+       if (inset_text) {
+               Font const & font = inset->inheritFont()
+                       ? cur.bv().textMetrics(text).displayFont(cur.pit(), cur.pos())
+                       : bparams.getFont();
+               inset_text->setOuterFont(cur.bv(), font.fontInfo());
+       }
+
+       if (cmd.action() == LFUN_ARGUMENT_INSERT) {
+               InsetArgument * const ia = static_cast<InsetArgument *>(inset);
+               ia->init(cur.paragraph());
+       }
+
        if (edit)
                inset->edit(cur, true);
 
@@ -323,8 +347,14 @@ static bool doInsertInset(Cursor & cur, Text * text,
        cur.buffer()->errors("Paste");
        cur.clearSelection(); // bug 393
        cur.finishUndo();
-       InsetText * inset_text = inset->asInsetText();
        if (inset_text) {
+               if (resetfont) {
+                       // Reset of font (not language) is requested.
+                       // Used by InsetIndex (#11961).
+                       Language const * lang = cur.getFont().language();
+                       Font font(bparams.getFont().fontInfo(), lang);
+                       cur.paragraph().resetFonts(font);
+               }
                inset_text->fixParagraphsFont();
                cur.pos() = 0;
                cur.pit() = 0;
@@ -720,7 +750,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selection())
                        cutSelection(cur, false);
                else
-                       deleteWordForward(cur, cmd.getArg(0) == "force");
+                       deleteWordForward(cur, cmd.getArg(0) != "confirm");
                finishChange(cur, false);
                break;
 
@@ -728,7 +758,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selection())
                        cutSelection(cur, false);
                else
-                       deleteWordBackward(cur, cmd.getArg(0) == "force");
+                       deleteWordBackward(cur, cmd.getArg(0) != "confirm");
                finishChange(cur, false);
                break;
 
@@ -787,24 +817,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool const cur_moved = cursorForward(cur);
                needsUpdate |= cur_moved;
 
-               if (!cur_moved && oldTopSlice == cur.top()
-                              && cur.boundary() == oldBoundary) {
+               if (!cur_moved && cur.depth() > 1
+                    && 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();
-                       }
+                       // we will be moving out the inset, so we should execute
+                       // the depm-mechanism.
+                       // 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();
                }
                break;
        }
@@ -816,24 +842,21 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool const cur_moved = cursorBackward(cur);
                needsUpdate |= cur_moved;
 
-               if (!cur_moved && oldTopSlice == cur.top()
-                              && cur.boundary() == oldBoundary) {
+               if (!cur_moved && cur.depth() > 1
+                    && 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();
-                       }
+                       // we will be moving out the inset, so we should execute
+                       // the depm-mechanism.
+                       // 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();
                }
                break;
        }
@@ -844,8 +867,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cur.selHandle(act == LFUN_CHAR_LEFT_SELECT);
                        bool const cur_moved = cursorVisLeft(cur);
                        needsUpdate |= cur_moved;
-                       if (!cur_moved && oldTopSlice == cur.top()
-                                      && cur.boundary() == oldBoundary) {
+                       if (!cur_moved && cur.depth() > 1
+                            && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) {
                                cur.undispatched();
                                cmd = FuncRequest(LFUN_FINISHED_LEFT);
                        }
@@ -868,8 +891,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cur.selHandle(cmd.action() == LFUN_CHAR_RIGHT_SELECT);
                        bool const cur_moved = cursorVisRight(cur);
                        needsUpdate |= cur_moved;
-                       if (!cur_moved && oldTopSlice == cur.top()
-                                      && cur.boundary() == oldBoundary) {
+                       if (!cur_moved && cur.depth() > 1
+                            && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) {
                                cur.undispatched();
                                cmd = FuncRequest(LFUN_FINISHED_RIGHT);
                        }
@@ -1002,8 +1025,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_RIGHT_SELECT);
                        bool const cur_moved = cursorVisRightOneWord(cur);
                        needsUpdate |= cur_moved;
-                       if (!cur_moved && oldTopSlice == cur.top()
-                                      && cur.boundary() == oldBoundary) {
+                       if (!cur_moved && cur.depth() > 1
+                            && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) {
                                cur.undispatched();
                                cmd = FuncRequest(LFUN_FINISHED_RIGHT);
                        }
@@ -1026,24 +1049,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool const cur_moved = cursorForwardOneWord(cur);
                needsUpdate |= cur_moved;
 
-               if (!cur_moved && oldTopSlice == cur.top()
-                              && cur.boundary() == oldBoundary) {
+               if (!cur_moved && cur.depth() > 1
+                    && 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();
-                       }
+                       // we will be moving out the inset, so we should execute
+                       // the depm-mechanism.
+                       // 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();
                }
                break;
        }
@@ -1054,8 +1073,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_LEFT_SELECT);
                        bool const cur_moved = cursorVisLeftOneWord(cur);
                        needsUpdate |= cur_moved;
-                       if (!cur_moved && oldTopSlice == cur.top()
-                                      && cur.boundary() == oldBoundary) {
+                       if (!cur_moved && cur.depth() > 1
+                            && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) {
                                cur.undispatched();
                                cmd = FuncRequest(LFUN_FINISHED_LEFT);
                        }
@@ -1078,25 +1097,21 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool const cur_moved = cursorBackwardOneWord(cur);
                needsUpdate |= cur_moved;
 
-               if (!cur_moved && oldTopSlice == cur.top()
-                              && cur.boundary() == oldBoundary) {
+               if (!cur_moved && cur.depth() > 1
+                    && 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();
-                       }
+                       // we will be moving out the inset, so we should execute
+                       // the depm-mechanism.
+                       // 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();
                }
                break;
        }
@@ -1210,7 +1225,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        if (cur.pos() == cur.paragraph().size())
                                // Par boundary, force full-screen update
                                singleParUpdate = false;
-                       else if (cmd.getArg(0) != "force" && cur.confirmDeletion()) {
+                       else if (cmd.getArg(0) == "confirm" && cur.confirmDeletion()) {
                                cur.resetAnchor();
                                cur.selection(true);
                                cur.posForward();
@@ -1235,7 +1250,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                // Par boundary, full-screen update
                                if (par_boundary)
                                        singleParUpdate = false;
-                               else if (cmd.getArg(0) != "force" && cur.confirmDeletion(true)) {
+                               else if (cmd.getArg(0) == "confirm" && cur.confirmDeletion(true)) {
                                        cur.resetAnchor();
                                        cur.selection(true);
                                        cur.posBackward();
@@ -1503,7 +1518,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                pasteFromStack(cur, bv->buffer().errorList("Paste"), 0);
                        else if (theClipboard().hasTextContents()) {
                                if (pasteClipboardText(cur, bv->buffer().errorList("Paste"),
-                                                      true, Clipboard::AnyTextType))
+                                                      !cur.paragraph().parbreakIsNewline(),
+                                                          Clipboard::AnyTextType))
                                        tryGraphics = false;
                        }
                        if (tryGraphics && theClipboard().hasGraphicsContents())
@@ -1839,8 +1855,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                bvcur.resetAnchor();
                        if (!bv->mouseSetCursor(cur, cmd.modifier() == ShiftModifier))
                                cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
-                       if (bvcur.wordSelection())
-                               selectWord(bvcur, WHOLE_WORD);
+                       // FIXME: move this to mouseSetCursor?
+                       if (bvcur.wordSelection() && bvcur.inTexted())
+                               expandWordSel(bvcur);
                        break;
 
                case mouse_button::button2:
@@ -1908,6 +1925,8 @@ 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);
+               if (bvcur.wordSelection() && bvcur.inTexted())
+                       expandWordSel(bvcur);
                bvcur.selection(true);
                bvcur.setCurrentFont();
                if (cur.top() == old) {
@@ -2072,28 +2091,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_BRANCH_INSERT:
        case LFUN_PHANTOM_INSERT:
        case LFUN_ERT_INSERT:
+       case LFUN_INDEXMACRO_INSERT:
        case LFUN_LISTING_INSERT:
        case LFUN_MARGINALNOTE_INSERT:
        case LFUN_ARGUMENT_INSERT:
        case LFUN_INDEX_INSERT:
        case LFUN_PREVIEW_INSERT:
        case LFUN_SCRIPT_INSERT:
-       case LFUN_IPA_INSERT:
+       case LFUN_IPA_INSERT: {
+               // Indexes reset font formatting (#11961)
+               bool const resetfont = cmd.action() == LFUN_INDEX_INSERT;
                // Open the inset, and move the current selection
                // inside it.
-               doInsertInset(cur, this, cmd, true, true);
+               doInsertInset(cur, this, cmd, true, true, resetfont);
                cur.posForward();
-               /* The font of the inset is computed in metrics(), and this is
-                * used to compute the height of the caret (because the font
-                * is stored in TextMetrics::font_). When we insert, we have
-                * to make sure that metrics are computed so that the caret
-                * height is correct. Arguably, this is hackish.*/
-               bv->processUpdateFlags(Update::SinglePar);
                cur.setCurrentFont();
                // Some insets are numbered, others are shown in the outline pane so
                // let's update the labels and the toc backend.
                cur.forceBufferUpdate();
                break;
+       }
 
        case LFUN_FLEX_INSERT: {
                // Open the inset, and move the current selection
@@ -2116,6 +2133,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                // leave this now in order to insert the next one.
                                if (inautoarg) {
                                        cur.leaveInset(cur.inset());
+                                       cur.setCurrentFont();
                                        cur.posForward();
                                        if (arg.insertonnewline && cur.pos() > 0) {
                                                FuncRequest cmd2(LFUN_PARAGRAPH_BREAK);
@@ -2493,7 +2511,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                string const lang_arg = cmd.getArg(0);
                bool const reset = (lang_arg.empty() || lang_arg == "reset");
                Language const * lang =
-                       reset ? reset_language
+                       reset ? cur.bv().buffer().params().language
                              : languages.getLanguage(lang_arg);
                // we allow reset_language, which is 0, but only if it
                // was requested via empty or "reset" arg.
@@ -2503,10 +2521,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                selectWordWhenUnderCursor(cur, WHOLE_WORD_STRICT);
                Font font(ignore_font, lang);
                toggleAndShow(cur, this, font, toggle);
-               // We need a buffer update if we change the language
-               // of an info inset
-               if (cur.insetInSelection(INFO_CODE))
-                       cur.forceBufferUpdate();
                break;
        }
 
@@ -2541,10 +2555,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        freeFonts.push(make_pair(props, font));
                        toggleall = toggle;
                        toggleAndShow(cur, this, font, toggleall);
-                       // We need a buffer update if we change the language
-                       // of an info inset
-                       if (cur.insetInSelection(INFO_CODE))
-                               cur.forceBufferUpdate();
                        cur.message(bformat(_("Text properties applied: %1$s"), props));
                } else
                        LYXERR0("Invalid argument of textstyle-update");
@@ -2732,6 +2742,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_SPELLING_ADD_LOCAL: {
+               Language const * language = getLanguage(cur, cmd.getArg(1));
+               docstring word = from_utf8(cmd.getArg(0));
+               if (word.empty()) {
+                       word = cur.selectionAsString(false);
+                       if (word.size() > 100)
+                               break;
+                       if (word.empty()) {
+                               // Get word or selection
+                               selectWordWhenUnderCursor(cur, WHOLE_WORD);
+                               word = cur.selectionAsString(false);
+                       }
+               }
+               WordLangTuple wl(word, language);
+               if (!bv->buffer().params().spellignored(wl)) {
+                       cur.recordUndoBufferParams();
+                       bv->buffer().params().spellignore().push_back(wl);
+                       cur.recordUndo();
+                       // trigger re-check of whole buffer
+                       bv->buffer().requestSpellcheck();
+               }
+               break;
+       }
+
+       case LFUN_SPELLING_REMOVE_LOCAL: {
                Language const * language = getLanguage(cur, cmd.getArg(1));
                docstring word = from_utf8(cmd.getArg(0));
                if (word.empty()) {
@@ -2746,9 +2780,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                WordLangTuple wl(word, language);
                bool has_item = false;
-               vector<WordLangTuple> il = bv->buffer().params().spellignore();
-               vector<WordLangTuple>::const_iterator it = il.begin();
-               for (; it != il.end(); ++it) {
+               vector<WordLangTuple>::const_iterator it = bv->buffer().params().spellignore().begin();
+               for (; it != bv->buffer().params().spellignore().end(); ++it) {
                        if (it->lang()->code() != wl.lang()->code())
                                continue;
                        if (it->word() == wl.word()) {
@@ -2756,21 +2789,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                break;
                        }
                }
-               if (!has_item) {
+               if (has_item) {
                        cur.recordUndoBufferParams();
-                       bv->buffer().params().spellignore().push_back(wl);
+                       bv->buffer().params().spellignore().erase(it);
                        cur.recordUndo();
-                       // trigger re-check
-                       WordLangTuple wl;
-                       docstring_list suggestions;
-                       Paragraph const & par = cur.paragraph();
-                       pos_type from = cur.pos();
-                       pos_type to = from;
-                       par.spellCheck(from, to, wl, suggestions, true, true);
+                       // trigger re-check of whole buffer
+                       bv->buffer().requestSpellcheck();
                }
                break;
        }
-       
+
 
        case LFUN_SPELLING_IGNORE: {
                Language const * language = getLanguage(cur, cmd.getArg(1));
@@ -2998,6 +3026,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        code = BRANCH_CODE;
                else if (cmd.argument() == "citation")
                        code = CITE_CODE;
+               else if (cmd.argument() == "counter")
+                       code = COUNTER_CODE;
                else if (cmd.argument() == "ert")
                        code = ERT_CODE;
                else if (cmd.argument() == "external")
@@ -3134,15 +3164,22 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                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() != InsetLyXType::CHARSTYLE &&
-                   il.lyxtype() != InsetLyXType::CUSTOM &&
-                   il.lyxtype ()!= InsetLyXType::STANDARD)
+               docstring s = from_utf8(cmd.getArg(0));
+               // Prepend "Flex:" prefix if not there
+               if (!prefixIs(s, from_ascii("Flex:")))
+                       s = from_ascii("Flex:") + s;
+               if (!cur.buffer()->params().documentClass().hasInsetLayout(s))
                        enable = false;
-               break;
+               else {
+                       InsetLyXType ilt =
+                               cur.buffer()->params().documentClass().insetLayout(s).lyxtype();
+                       if (ilt != InsetLyXType::CHARSTYLE
+                           && ilt != InsetLyXType::CUSTOM
+                           && ilt != InsetLyXType::STANDARD)
+                               enable = false;
                }
+               break;
+       }
        case LFUN_BOX_INSERT:
                code = BOX_CODE;
                break;
@@ -3240,6 +3277,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                }
                code = HYPERLINK_CODE;
                break;
+       case LFUN_INDEXMACRO_INSERT: {
+               string const arg = cmd.getArg(0);
+               if (arg == "sortkey")
+                       code = INDEXMACRO_SORTKEY_CODE;
+               else
+                       code = INDEXMACRO_CODE;
+               break;
+       }
        case LFUN_IPAMACRO_INSERT: {
                string const arg = cmd.getArg(0);
                if (arg == "deco")
@@ -3397,6 +3442,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
 
        case LFUN_PRIMARY_SELECTION_PASTE:
+               status.setUnknown(!theSelection().supported());
                enable = cur.selection() || !theSelection().empty();
                break;
 
@@ -3502,6 +3548,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_SPELLING_ADD:
        case LFUN_SPELLING_ADD_LOCAL:
+       case LFUN_SPELLING_REMOVE_LOCAL:
        case LFUN_SPELLING_IGNORE:
        case LFUN_SPELLING_REMOVE:
                enable = theSpellChecker() != nullptr;
@@ -3518,8 +3565,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                docstring const req_layout = ignoreautonests ? from_utf8(cmd.getArg(0)) : cmd.argument();
                docstring const layout = resolveLayout(req_layout, cur);
 
-               enable = !owner_->forcePlainLayout() && !layout.empty();
-               status.setOnOff(isAlreadyLayout(layout, cur));
+               // FIXME: make this work in multicell selection case
+               enable = !owner_->forcePlainLayout() && !layout.empty() && !cur.selIsMultiCell();
+               status.setOnOff(!owner_->forcePlainLayout() && !cur.selIsMultiCell()
+                               && isAlreadyLayout(layout, cur));
                break;
        }