]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
Add outliner section for broken refs and citations
[lyx.git] / src / Text3.cpp
index b06b0f7611b073808b728701a3ecd585eac4b102..4a4755637a9b0fe226e0f142efdeb70ffed20d9e 100644 (file)
@@ -70,6 +70,7 @@
 
 #include "support/convert.h"
 #include "support/debug.h"
+#include "support/filetools.h"
 #include "support/gettext.h"
 #include "support/lassert.h"
 #include "support/limited_stack.h"
@@ -295,8 +296,16 @@ static bool doInsertInset(Cursor & cur, Text * text,
        if (cur.selection()) {
                if (cmd.action() == LFUN_INDEX_INSERT)
                        copySelectionToTemp(cur);
-               else
+               else {
                        cutSelectionToTemp(cur, pastesel);
+                       /* Move layout information inside the inset if the whole
+                        * 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.
+                        */
+                       if (cur.paragraph().empty() && !inset->forcePlainLayout())
+                               cur.paragraph().setPlainOrDefaultLayout(bparams.documentClass());
+               }
                cur.clearSelection();
                gotsel = true;
        } else if (cmd.action() == LFUN_INDEX_INSERT) {
@@ -319,24 +328,17 @@ static bool doInsertInset(Cursor & cur, Text * text,
        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());
-                       cur.pos() = 0;
-                       cur.pit() = 0;
-                       // Merge multiple paragraphs -- hack
-                       while (cur.lastpit() > 0)
-                               mergeParagraph(bparams, cur.text()->paragraphs(), 0);
-                       if (cmd.action() == LFUN_FLEX_INSERT)
-                               return true;
-                       Cursor old = cur;
-                       cur.leaveInset(*inset);
-                       if (cmd.action() == LFUN_PREVIEW_INSERT
-                           || cmd.action() == LFUN_IPA_INSERT)
-                               // trigger preview
-                               notifyCursorLeavesOrEnters(old, cur);
-               }
+               cur.pos() = 0;
+               cur.pit() = 0;
+               // FIXME: what does this do?
+               if (cmd.action() == LFUN_FLEX_INSERT)
+                       return true;
+               Cursor old = cur;
+               cur.leaveInset(*inset);
+               if (cmd.action() == LFUN_PREVIEW_INSERT
+                       || cmd.action() == LFUN_IPA_INSERT)
+                       // trigger preview
+                       notifyCursorLeavesOrEnters(old, cur);
        } else {
                cur.leaveInset(*inset);
                // reset surrounding par to default
@@ -561,10 +563,10 @@ void Text::number(Cursor & cur)
 }
 
 
-bool Text::isRTL(Paragraph const & par) const
+bool Text::isRTL(pit_type const pit) const
 {
        Buffer const & buffer = owner_->buffer();
-       return par.isRTL(buffer.params());
+       return pars_[pit].isRTL(buffer.params());
 }
 
 
@@ -579,7 +581,6 @@ Language const * getLanguage(Cursor const & cur, string const & lang)
 docstring resolveLayout(docstring layout, DocIterator const & dit)
 {
        Paragraph const & par = dit.paragraph();
-       docstring const old_layout = par.layout().name();
        DocumentClass const & tclass = dit.buffer()->params().documentClass();
 
        if (layout.empty())
@@ -672,7 +673,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_PARAGRAPH_MOVE_DOWN: {
                pit_type const pit = cur.pit();
                cur.recordUndo(pit, pit + 1);
-               cur.finishUndo();
                pars_.swap(pit, pit + 1);
                needsUpdate = true;
                cur.forceBufferUpdate();
@@ -926,6 +926,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_PARAGRAPH_SELECT:
+               if (cur.pos() > 0)
+                       needsUpdate |= setCursor(cur, cur.pit(), 0);
+               needsUpdate |= cur.selHandle(true);
+               if (cur.pos() < cur.lastpos())
+                       needsUpdate |= setCursor(cur, cur.pit(), cur.lastpos());
+               break;
+
        case LFUN_PARAGRAPH_UP:
        case LFUN_PARAGRAPH_UP_SELECT:
                needsUpdate |= cur.selHandle(cmd.action() == LFUN_PARAGRAPH_UP_SELECT);
@@ -1241,7 +1249,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                }
                        }
                } else {
+                       DocIterator const dit = cur.selectionBegin();
                        cutSelection(cur, false);
+                       if (cur.buffer()->params().track_changes)
+                               // since we're doing backwards deletion,
+                               // and the selection is not really cut,
+                               // move cursor before selection (#11630)
+                               cur.setCursor(dit);
                        singleParUpdate = false;
                }
                break;
@@ -1255,6 +1269,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                pit_type prev = pit > 0 ? depthHook(pit, par.getDepth()) : pit;
                if (prev < pit && cur.pos() == par.beginOfBody()
                    && !par.size() && !par.isEnvSeparator(cur.pos())
+                   && !par.layout().keepempty
                    && !par.layout().isCommand()
                    && pars_[prev].layout() != par.layout()
                    && pars_[prev].layout().isEnvironment()
@@ -1512,6 +1527,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
 
                bv->buffer().errors("Paste");
+               bv->buffer().updatePreviews(); // bug 11619
                cur.clearSelection(); // bug 393
                cur.finishUndo();
                break;
@@ -1585,11 +1601,19 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
 
                DocumentClass const & tclass = bv->buffer().params().documentClass();
+               bool inautoarg = false;
                for (auto const & la_pair : tclass[layout].args()) {
                        Layout::latexarg const & arg = la_pair.second;
                        if (arg.autoinsert) {
+                               // If we had already inserted an arg automatically,
+                               // leave this now in order to insert the next one.
+                               if (inautoarg) {
+                                       cur.leaveInset(cur.inset());
+                                       cur.posForward();
+                               }
                                FuncRequest const cmd2(LFUN_ARGUMENT_INSERT, la_pair.first);
                                lyx::dispatch(cmd2);
+                               inautoarg = true;
                        }
                }
 
@@ -1760,9 +1784,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_MOUSE_TRIPLE:
                if (cmd.button() == mouse_button::button1) {
-                       tm->cursorHome(cur);
+                       if (cur.pos() > 0)
+                               setCursor(cur, cur.pit(), 0);
+                       bv->cursor() = cur;
                        cur.resetAnchor();
-                       tm->cursorEnd(cur);
+                       if (cur.pos() < cur.lastpos())
+                               setCursor(cur, cur.pit(), cur.lastpos());
                        cur.setSelection();
                        bv->cursor() = cur;
                }
@@ -2029,6 +2056,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // inside it.
                doInsertInset(cur, this, cmd, true, true);
                cur.posForward();
+               if (act == LFUN_SCRIPT_INSERT) {
+                       /* Script insets change the font style 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 wrong. 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();
@@ -2040,18 +2077,33 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool const sel = cur.selection();
                doInsertInset(cur, this, cmd, true, true);
                // Insert auto-insert arguments
-               bool autoargs = false;
-               Layout::LaTeXArgMap args = cur.inset().getLayout().latexargs();
+               bool autoargs = false, inautoarg = false;
+               Layout::LaTeXArgMap args = cur.inset().getLayout().args();
                Layout::LaTeXArgMap::const_iterator lait = args.begin();
                Layout::LaTeXArgMap::const_iterator const laend = args.end();
                for (; lait != laend; ++lait) {
                        Layout::latexarg arg = (*lait).second;
+                       if (!inautoarg && arg.insertonnewline && cur.pos() > 0) {
+                               FuncRequest cmd2(LFUN_PARAGRAPH_BREAK);
+                               lyx::dispatch(cmd2);
+                       }
                        if (arg.autoinsert) {
                                // The cursor might have been invalidated by the replaceSelection.
                                cur.buffer()->changed(true);
+                               // If we had already inserted an arg automatically,
+                               // leave this now in order to insert the next one.
+                               if (inautoarg) {
+                                       cur.leaveInset(cur.inset());
+                                       cur.posForward();
+                                       if (arg.insertonnewline && cur.pos() > 0) {
+                                               FuncRequest cmd2(LFUN_PARAGRAPH_BREAK);
+                                               lyx::dispatch(cmd2);
+                                       }
+                               }
                                FuncRequest cmd2(LFUN_ARGUMENT_INSERT, (*lait).first);
                                lyx::dispatch(cmd2);
                                autoargs = true;
+                               inautoarg = true;
                        }
                }
                if (!autoargs) {
@@ -2065,14 +2117,78 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_TABULAR_INSERT:
+       case LFUN_TABULAR_INSERT: {
                // if there were no arguments, just open the dialog
+               if (cmd.argument().empty()) {
+                       bv->showDialog("tabularcreate");
+                       break;
+               } else if (cur.buffer()->masterParams().tablestyle != "default"
+                          || bv->buffer().params().documentClass().tablestyle() != "default") {
+                       string tabstyle = cur.buffer()->masterParams().tablestyle;
+                       if (tabstyle == "default")
+                               tabstyle = bv->buffer().params().documentClass().tablestyle();
+                       if (!libFileSearch("tabletemplates", tabstyle + ".lyx").empty()) {
+                               FuncRequest fr(LFUN_TABULAR_STYLE_INSERT,
+                                              tabstyle + " " + to_ascii(cmd.argument()));
+                               lyx::dispatch(fr);
+                               break;
+                       } else
+                               // Unknown style. Report and fall back to default.
+                               cur.errorMessage(from_utf8(N_("Table Style ")) + from_utf8(tabstyle) +
+                                                    from_utf8(N_(" not known")));
+                       
+               }
                if (doInsertInset(cur, this, cmd, false, true))
                        cur.posForward();
-               else
-                       bv->showDialog("tabularcreate");
+               break;
+       }
 
+       case LFUN_TABULAR_STYLE_INSERT: {
+               string const style = cmd.getArg(0);
+               string const rows = cmd.getArg(1);
+               string const cols = cmd.getArg(2);
+               if (cols.empty() || !isStrInt(cols)
+                   || rows.empty() || !isStrInt(rows))
+                       break;
+               int const r = convert<int>(rows);
+               int const c = convert<int>(cols);
+                       
+               string suffix;
+               if (r == 1)
+                       suffix = "_1x1";
+               else if (r == 2)
+                       suffix = "_1x2";
+               FileName const tabstyle = libFileSearch("tabletemplates",
+                                                       style + suffix + ".lyx", "lyx");
+               if (tabstyle.empty())
+                           break;
+               UndoGroupHelper ugh(cur.buffer());
+               cur.recordUndo();
+               FuncRequest cmd2(LFUN_FILE_INSERT, tabstyle.absFileName() + " ignorelang");
+               lyx::dispatch(cmd2);
+               // go into table
+               cur.backwardPos();
+               if (r > 2) {
+                       // move one cell up to middle cell
+                       cur.up();
+                       // add the missing rows
+                       int const addrows = r - 3;
+                       for (int i = 0 ; i < addrows ; ++i) {
+                               FuncRequest fr(LFUN_TABULAR_FEATURE, "append-row");
+                               lyx::dispatch(fr);
+                       }
+               }
+               // add the missing columns
+               int const addcols = c - 1;
+               for (int i = 0 ; i < addcols ; ++i) {
+                       FuncRequest fr(LFUN_TABULAR_FEATURE, "append-column");
+                       lyx::dispatch(fr);
+               }
+               if (r > 1)
+                       // go to first cell
+                       cur.up();
                break;
+       }
 
        case LFUN_FLOAT_INSERT:
        case LFUN_FLOAT_WIDE_INSERT:
@@ -2390,7 +2506,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // Set the freefont using the contents of \param data dispatched from
        // the frontends and apply it at the current cursor location.
        case LFUN_TEXTSTYLE_UPDATE: {
-               Font font;
+               Font font(ignore_font, ignore_language);
                bool toggle;
                if (font.fromString(to_utf8(cmd.argument()), toggle)) {
                        docstring const props = font.stateText(&bv->buffer().params(), true);
@@ -2649,14 +2765,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_OUTLINE_UP:
                outline(OutlineUp, cur, this);
-               setCursor(cur, cur.pit(), 0);
+               setCursor(cur, cur.pit(), cur.pos());
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_DOWN:
                outline(OutlineDown, cur, this);
-               setCursor(cur, cur.pit(), 0);
+               setCursor(cur, cur.pit(), cur.pos());
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;
@@ -2771,7 +2887,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        bool enable = true;
        bool allow_in_passthru = false;
        InsetCode code = NO_CODE;
-
+       
        switch (cmd.action()) {
 
        case LFUN_DEPTH_DECREMENT:
@@ -2861,6 +2977,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_TABULAR_INSERT:
                code = TABULAR_CODE;
                break;
+       case LFUN_TABULAR_STYLE_INSERT:
+               code = TABULAR_CODE;
+               break;
        case LFUN_MARGINALNOTE_INSERT:
                code = MARGIN_CODE;
                break;
@@ -3233,15 +3352,22 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        for (DocIterator it = cur.selectionBegin(); ; it.forwardPar()) {
                                pos_type const beg = it.pos();
                                pos_type end;
-                               bool const in_last_par = (it.pit() == cur.selectionEnd().pit());
+                               bool const in_last_par = (it.pit() == cur.selectionEnd().pit() &&
+                                                         it.idx() == cur.selectionEnd().idx());
                                if (in_last_par)
                                        end = cur.selectionEnd().pos();
                                else
-                                       end = it.lastpos();
+                                       // the +1 is needed for cases, e.g., where there is a
+                                       // paragraph break. See #11629.
+                                       end = it.lastpos() + 1;
                                if (beg != end && it.paragraph().isChanged(beg, end)) {
                                        enable = true;
                                        break;
                                }
+                               if (beg != end && it.paragraph().hasChangedInsets(beg, end)) {
+                                       enable = true;
+                                       break;
+                               }
                                if (in_last_par)
                                        break;
                        }
@@ -3454,6 +3580,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_UP_SELECT:
        case LFUN_DOWN:
        case LFUN_DOWN_SELECT:
+       case LFUN_PARAGRAPH_SELECT:
        case LFUN_PARAGRAPH_UP_SELECT:
        case LFUN_PARAGRAPH_DOWN_SELECT:
        case LFUN_LINE_BEGIN_SELECT: