]> git.lyx.org Git - features.git/blobdiff - src/Text3.cpp
Do not allow pasting backslashes in macro names
[features.git] / src / Text3.cpp
index 1623996ec665aa052bc49ec173e349a3bb079438..8bbac0eee23d72130b13b5e8ce6e143c98c623bb 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();
@@ -299,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;
                        }
@@ -318,7 +328,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
        if (inset_text) {
                Font const & font = inset->inheritFont()
                        ? cur.bv().textMetrics(text).displayFont(cur.pit(), cur.pos())
-                       : buffer.params().getFont();
+                       : bparams.getFont();
                inset_text->setOuterFont(cur.bv(), font.fontInfo());
        }
 
@@ -338,6 +348,13 @@ static bool doInsertInset(Cursor & cur, Text * text,
        cur.clearSelection(); // bug 393
        cur.finishUndo();
        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;
@@ -898,12 +915,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_UP:
        case LFUN_DOWN: {
                // stop/start the selection
-               bool const select = cmd.action() == LFUN_DOWN_SELECT
-                                       || cmd.action() == LFUN_UP_SELECT;
+               bool select = cmd.action() == LFUN_DOWN_SELECT ||
+                       cmd.action() == LFUN_UP_SELECT;
+
                // move cursor up/down
-               bool const up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP;
+               bool up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP;
+               bool const atFirstOrLastRow = cur.atFirstOrLastRow(up);
 
-               if (!cur.atFirstOrLastRow(up)) {
+               if (!atFirstOrLastRow) {
                        needsUpdate |= cur.selHandle(select);
                        cur.upDownInText(up, needsUpdate);
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
@@ -919,35 +938,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                        cur.forceBufferUpdate();
                                break;
                        }
-                       needsUpdate |= cur.selHandle(select);
-                       bool const can_move = cur.upDownInText(up, needsUpdate);
-                       // if the cursor can be moved up or down at an upper level,
-                       // delegate the dispatch to next level. Otherwise, we are
-                       // done.
-                       if (can_move) {
-                               cmd = FuncRequest(up ? LFUN_FINISHED_UP : LFUN_FINISHED_DOWN);
-                               cur.undispatched();
-                       }
-               }
 
-               break;
-       }
-
-       case LFUN_FINISHED_UP:
-       case LFUN_FINISHED_DOWN: {
-               // move cursor up/down
-               bool const up = cmd.action() == LFUN_FINISHED_UP;
-
-               if (!cur.atFirstOrLastRow(up)) {
+                       // if the cursor cannot be moved up or down do not remove
+                       // the selection right now, but wait for the next dispatch.
+                       if (select)
+                               needsUpdate |= cur.selHandle(select);
                        cur.upDownInText(up, needsUpdate);
-                       needsUpdate |= cur.beforeDispatchCursor().inMathed();
-               } else {
-                       bool const can_move = cur.upDownInText(up, needsUpdate);
-                       // if the cursor can be moved up or down and we are not
-                       // moving cusor at top level, wait for the next dispatch.
-                       // Otherwise, we are done.
-                       if (can_move)
-                               cur.undispatched();
+                       cur.undispatched();
                }
 
                break;
@@ -1521,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())
@@ -1857,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:
@@ -1926,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) {
@@ -2090,22 +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();
                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
@@ -2128,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);
@@ -2515,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;
        }
 
@@ -2553,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");
@@ -3166,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;
@@ -3272,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")
@@ -3552,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(!owner_->forcePlainLayout() && 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;
        }