#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"
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) {
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
}
-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());
}
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())
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();
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);
}
}
} 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;
}
bv->buffer().errors("Paste");
+ bv->buffer().updatePreviews(); // bug 11619
cur.clearSelection(); // bug 393
cur.finishUndo();
break;
}
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;
}
}
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;
}
// 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();
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) {
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:
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;
bool enable = true;
bool allow_in_passthru = false;
InsetCode code = NO_CODE;
-
+
switch (cmd.action()) {
case LFUN_DEPTH_DECREMENT:
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;
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;
}
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: