]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
Account for old versions of Pygments
[lyx.git] / src / Text3.cpp
index 9edda1b65267f02126d01bafbb82103ed736845d..71293f80301152055633644007ce08bab5740db3 100644 (file)
@@ -90,13 +90,16 @@ namespace lyx {
 
 using cap::copySelection;
 using cap::cutSelection;
+using cap::cutSelectionToTemp;
 using cap::pasteFromStack;
+using cap::pasteFromTemp;
 using cap::pasteClipboardText;
 using cap::pasteClipboardGraphics;
 using cap::replaceSelection;
 using cap::grabAndEraseSelection;
 using cap::selClearOrDel;
 using cap::pasteSimpleText;
+using frontend::Clipboard;
 
 // globals...
 static Font freefont(ignore_font, ignore_language);
@@ -178,7 +181,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd)
                        LASSERT(cur.inMathed(), return);
                        cur.pos() = 0;
                        cur.resetAnchor();
-                       cur.setSelection(true);
+                       cur.selection(true);
                        cur.pos() = cur.lastpos();
                        if (cmd.action() != LFUN_MATH_MODE)
                                // LFUN_MATH_MODE has a different meaning in math mode
@@ -298,7 +301,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
 
        bool gotsel = false;
        if (cur.selection()) {
-               cutSelection(cur, false, pastesel);
+               cutSelectionToTemp(cur, false, pastesel);
                cur.clearSelection();
                gotsel = true;
        }
@@ -310,7 +313,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
        if (!gotsel || !pastesel)
                return true;
 
-       pasteFromStack(cur, cur.buffer()->errorList("Paste"), 0);
+       pasteFromTemp(cur, cur.buffer()->errorList("Paste"));
        cur.buffer()->errors("Paste");
        cur.clearSelection(); // bug 393
        cur.finishUndo();
@@ -370,7 +373,7 @@ static void outline(OutlineOp mode, Cursor & cur)
        ParagraphList & pars = buf.text().paragraphs();
        ParagraphList::iterator const bgn = pars.begin();
        // The first paragraph of the area to be copied:
-       ParagraphList::iterator start = next(bgn, pit);
+       ParagraphList::iterator start = lyx::next(bgn, pit);
        // The final paragraph of area to be copied:
        ParagraphList::iterator finish = start;
        ParagraphList::iterator const end = pars.end();
@@ -583,7 +586,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selection())
                        cutSelection(cur, true, false);
                else
-                       deleteWordForward(cur);
+                       deleteWordForward(cur, cmd.getArg(0) == "force");
                finishChange(cur, false);
                break;
 
@@ -591,7 +594,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selection())
                        cutSelection(cur, true, false);
                else
-                       deleteWordBackward(cur);
+                       deleteWordBackward(cur, cmd.getArg(0) == "force");
                finishChange(cur, false);
                break;
 
@@ -808,7 +811,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                ParagraphList & pars = buf.text().paragraphs();
                ParagraphList::iterator bgn = pars.begin();
                // The first paragraph of the area to be selected:
-               ParagraphList::iterator start = next(bgn, pit);
+               ParagraphList::iterator start = lyx::next(bgn, pit);
                // The final paragraph of area to be selected:
                ParagraphList::iterator finish = start;
                ParagraphList::iterator end = pars.end();
@@ -1048,22 +1051,18 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CHAR_DELETE_FORWARD:
                if (!cur.selection()) {
-                       bool was_separator = cur.paragraph().isEnvSeparator(cur.pos());
                        if (cur.pos() == cur.paragraph().size())
                                // Par boundary, force full-screen update
                                singleParUpdate = false;
-                       needsUpdate |= erase(cur);
-                       cur.resetAnchor();
-                       if (was_separator && cur.pos() == cur.paragraph().size()
-                           && (!cur.paragraph().layout().isEnvironment()
-                               || cur.paragraph().size() > 0)) {
-                               // Force full-screen update
-                               singleParUpdate = false;
-                               needsUpdate |= erase(cur);
+                       else if (cmd.getArg(0) != "force" && cur.confirmDeletion()) {
                                cur.resetAnchor();
+                               cur.selection(true);
+                               cur.posForward();
+                               cur.setSelection();
+                               break;
                        }
-                       // It is possible to make it a lot faster still
-                       // just comment out the line below...
+                       needsUpdate |= erase(cur);
+                       cur.resetAnchor();
                } else {
                        cutSelection(cur, true, false);
                        singleParUpdate = false;
@@ -1079,6 +1078,13 @@ 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)) {
+                                       cur.resetAnchor();
+                                       cur.selection(true);
+                                       cur.posBackward();
+                                       cur.setSelection();
+                                       break;
+                               }
                                needsUpdate |= backspace(cur);
                                cur.resetAnchor();
                                if (par_boundary && !first_par && cur.pos() > 0
@@ -1097,33 +1103,32 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                cap::replaceSelection(cur);
                pit_type pit = cur.pit();
                Paragraph const & par = pars_[pit];
-               pit_type prev = pit;
-               if (pit > 0) {
-                       if (!pars_[pit - 1].layout().isEnvironment())
-                               prev = depthHook(pit, par.getDepth());
-                       else if (pars_[pit - 1].getDepth() >= par.getDepth())
-                               prev = pit - 1;
-               }
+               bool lastpar = (pit == pit_type(pars_.size() - 1));
+               Paragraph const & nextpar = lastpar ? par : pars_[pit + 1];
+               pit_type prev = pit > 0 ? depthHook(pit, par.getDepth()) : pit;
                if (prev < pit && cur.pos() == par.beginOfBody()
-                   && !par.isEnvSeparator(cur.pos())
+                   && !par.size() && !par.isEnvSeparator(cur.pos())
                    && !par.layout().isCommand()
                    && pars_[prev].layout() != par.layout()
-                   && pars_[prev].layout().isEnvironment()) {
+                   && pars_[prev].layout().isEnvironment()
+                   && !nextpar.isEnvSeparator(nextpar.beginOfBody())) {
                        if (par.layout().isEnvironment()
                            && pars_[prev].getDepth() == par.getDepth()) {
                                docstring const layout = par.layout().name();
                                DocumentClass const & tc = bv->buffer().params().documentClass();
                                lyx::dispatch(FuncRequest(LFUN_LAYOUT, tc.plainLayout().name()));
-                               lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "parbreak"));
+                               lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
                                lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK, "inverse"));
                                lyx::dispatch(FuncRequest(LFUN_LAYOUT, layout));
                        } else {
-                               lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "parbreak"));
+                               lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
                                breakParagraph(cur);
                        }
                        Font const f(inherit_font, cur.current_font.language());
                        pars_[cur.pit() - 1].resetFonts(f);
                } else {
+                       if (par.isEnvSeparator(cur.pos()))
+                               cur.posForward();
                        breakParagraph(cur, cmd.argument() == "inverse");
                }
                cur.resetAnchor();
@@ -1238,6 +1243,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                string const name = to_utf8(cmd.argument());
                if (name == "hyphenation")
                        specialChar(cur, InsetSpecialChar::HYPHENATION);
+               else if (name == "allowbreak")
+                       specialChar(cur, InsetSpecialChar::ALLOWBREAK);
                else if (name == "ligature-break")
                        specialChar(cur, InsetSpecialChar::LIGATURE_BREAK);
                else if (name == "slash")
@@ -1557,26 +1564,44 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                while (pos > 0 && par.isDeleted(pos - 1))
                        --pos;
 
-               BufferParams const & bufparams = bv->buffer().params();
-               bool const hebrew =
-                       par.getFontSettings(bufparams, pos).language()->lang() == "hebrew";
-               bool const allow_inset_quote = !(par.isPassThru() || hebrew);
-
-               string const arg = to_utf8(cmd.argument());
-               if (allow_inset_quote) {
-                       char_type c = ' ';
-                       if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace()))
+               bool const inner = (cmd.getArg(0) == "single" || cmd.getArg(0) == "inner");
+
+               // Guess quote side.
+               // A space triggers an opening quote. This is passed if the preceding
+               // char/inset is a space or at paragraph start.
+               char_type c = ' ';
+               if (pos > 0 && !par.isSpace(pos - 1)) {
+                       if (cur.prevInset() && cur.prevInset()->lyxCode() == QUOTE_CODE) {
+                               // If an opening double quotation mark precedes, and this
+                               // is a single quote, make it opening as well
+                               InsetQuotes & ins =
+                                       static_cast<InsetQuotes &>(*cur.prevInset());
+                               string const type = ins.getType();
+                               if (!suffixIs(type, "ld") || !inner)
+                                       c = par.getChar(pos - 1);
+                       }
+                       else if (!cur.prevInset()
+                           || (cur.prevInset() && cur.prevInset()->isChar()))
+                               // If a char precedes, pass that and let InsetQuote decide
                                c = par.getChar(pos - 1);
-                       InsetQuotes::QuoteTimes const quote_type = (arg == "single")
-                               ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes;
-                       cur.insert(new InsetQuotes(cur.buffer(), c, quote_type));
-                       cur.posForward();
-               } else {
-                       // The cursor might have been invalidated by the replaceSelection.
-                       cur.buffer()->changed(true);
-                       string const quote_string = (arg == "single") ? "'" : "\"";
-                       lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, quote_string));
+                       else {
+                               while (pos > 0) {
+                                       if (par.getInset(pos - 1)
+                                           && !par.getInset(pos - 1)->isPartOfTextSequence()) {
+                                               // skip "invisible" insets
+                                               --pos;
+                                               continue;
+                                       }
+                                       c = par.getChar(pos - 1);
+                                       break;
+                               }
+                       }
                }
+               InsetQuotesParams::QuoteLevel const quote_level = inner
+                               ? InsetQuotesParams::SecondaryQuotes : InsetQuotesParams::PrimaryQuotes;
+               cur.insert(new InsetQuotes(cur.buffer(), c, quote_level, cmd.getArg(1), cmd.getArg(2)));
+               cur.buffer()->updateBuffer();
+               cur.posForward();
                break;
        }
 
@@ -1612,9 +1637,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bvcur.setMark(false);
                switch (cmd.button()) {
                case mouse_button::button1:
-                       // Set the cursor
-                       if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select"))
-                               cur.screenUpdateFlags(Update::FitCursor);
+                       if (!bvcur.selection())
+                               // Set the cursor
+                               bvcur.resetAnchor();
+                       if (!bv->mouseSetCursor(cur, cmd.modifier() == ShiftModifier))
+                               cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
                        if (bvcur.wordSelection())
                                selectWord(bvcur, WHOLE_WORD);
                        break;
@@ -1667,6 +1694,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
                tm->setCursorFromCoordinates(cur, cmd.x(), y);
                cur.setTargetX(cmd.x());
+               // Don't allow selecting a separator inset
+               if (cur.pos() && cur.paragraph().isEnvSeparator(cur.pos() - 1))
+                       cur.posBackward();
                if (cmd.y() >= wh)
                        lyx::dispatch(FuncRequest(LFUN_DOWN_SELECT));
                else if (cmd.y() < 0)
@@ -1681,7 +1711,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // We continue with our existing selection or start a new one, so don't
                // reset the anchor.
                bvcur.setCursor(cur);
-               bvcur.setSelection(true);
+               bvcur.selection(true);
                if (cur.top() == old) {
                        // We didn't move one iota, so no need to update the screen.
                        cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
@@ -1761,13 +1791,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_HREF_INSERT: {
-               // FIXME If we're actually given an argument, shouldn't
-               // we use it, whether or not we have a selection?
                docstring content = cmd.argument();
-               if (cur.selection()) {
+               if (content.empty() && cur.selection())
                        content = cur.selectionAsString(false);
-                       cutSelection(cur, true, false);
-               }
 
                InsetCommandParams p(HYPERLINK_CODE);
                if (!content.empty()){
@@ -2063,7 +2089,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        cur.push(*inset);
                        cur.top().pos() = cur.top().lastpos();
                        cur.resetAnchor();
-                       cur.setSelection(true);
+                       cur.selection(true);
                        cur.top().pos() = 0;
                }
                break;
@@ -2142,6 +2168,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_FONT_CROSSOUT: {
+               Font font(ignore_font, ignore_language);
+               font.fontInfo().setXout(FONT_TOGGLE);
+               toggleAndShow(cur, this, font);
+               break;
+       }
+
        case LFUN_FONT_UNDERUNDERLINE: {
                Font font(ignore_font, ignore_language);
                font.fontInfo().setUuline(FONT_TOGGLE);
@@ -2439,7 +2472,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_ESCAPE:
                if (cur.selection()) {
-                       cur.setSelection(false);
+                       cur.selection(false);
                } else {
                        cur.undispatched();
                        // This used to be LFUN_FINISHED_RIGHT, I think FORWARD is more
@@ -2724,7 +2757,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_CAPTION_INSERT: {
                code = CAPTION_CODE;
                string arg = cmd.getArg(0);
-               bool varia = arg != "LongTableNoNumber"
+               bool varia = arg != "Unnumbered"
                        && cur.inset().allowsCaptionVariation(arg);
                // not allowed in description items,
                // and in specific insets
@@ -2808,19 +2841,13 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        for (; pit <= lastpit; ++pit) {
                                if (pars_[pit].layout() != lay)
                                        break;
-                               InsetList::const_iterator it = pars_[pit].insetList().begin();
-                               InsetList::const_iterator end = pars_[pit].insetList().end();
-                               for (; it != end; ++it) {
-                                       if (it->inset->lyxCode() == ARG_CODE) {
-                                               InsetArgument const * ins =
-                                                       static_cast<InsetArgument const *>(it->inset);
+                               for (auto const & table : pars_[pit].insetList())
+                                       if (InsetArgument const * ins = table.inset->asInsetArgument())
                                                if (ins->name() == arg) {
                                                        // we have this already
                                                        enable = false;
                                                        break;
                                                }
-                                       }
-                               }
                        }
                } else
                        enable = false;
@@ -2864,6 +2891,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_QUOTE_INSERT:
                // always allow this, since we will inset a raw quote
                // if an inset is not allowed.
+               allow_in_passthru = true;
                break;
        case LFUN_SPECIALCHAR_INSERT:
                code = SPECIALCHAR_CODE;
@@ -3112,7 +3140,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                docstring layout = cmd.argument();
                if (layout.empty())
                        layout = tclass.defaultLayoutName();
-               enable = !cur.inset().forcePlainLayout() && tclass.hasLayout(layout);
+               enable = !owner_->forcePlainLayout() && tclass.hasLayout(layout);
 
                flag.setOnOff(layout == cur.paragraph().layout().name());
                break;
@@ -3148,7 +3176,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_PARAGRAPH_PARAMS:
        case LFUN_PARAGRAPH_PARAMS_APPLY:
        case LFUN_PARAGRAPH_UPDATE:
-               enable = cur.inset().allowParagraphCustomization();
+               enable = owner_->allowParagraphCustomization();
                break;
 
        // FIXME: why are accent lfuns forbidden with pass_thru layouts?
@@ -3178,6 +3206,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_FONT_STATE:
        case LFUN_FONT_UNDERLINE:
        case LFUN_FONT_STRIKEOUT:
+       case LFUN_FONT_CROSSOUT:
        case LFUN_FONT_UNDERUNDERLINE:
        case LFUN_FONT_UNDERWAVE:
        case LFUN_TEXTSTYLE_APPLY: