#include "Paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
+#include "ParIterator.h"
+#include "TextClass.h"
#include "TextMetrics.h"
#include "VSpace.h"
-#include "ParIterator.h"
#include "frontends/Clipboard.h"
#include "frontends/Selection.h"
#include "mathed/MathMacroTemplate.h"
#include <boost/current_function.hpp>
+#include <boost/next_prior.hpp>
#include <clocale>
#include <sstream>
text->toggleFree(cur, font, toggleall);
if (font.language() != ignore_language ||
- font.fontInfo().number() != FONT_IGNORE) {
+ font.fontInfo().number() != FONT_IGNORE) {
TextMetrics const & tm = cur.bv().textMetrics(text);
- if (cur.boundary() != tm.isRTLBoundary(cur.pit(),
- cur.pos(), cur.real_current_font))
+ if (cur.boundary() != tm.isRTLBoundary(cur.pit(), cur.pos(),
+ cur.real_current_font))
text->setCursor(cur, cur.pit(), cur.pos(),
- false, !cur.boundary());
+ false, !cur.boundary());
}
}
cur.recordUndo();
cap::replaceSelection(cur);
cur.insert(new InsetSpecialChar(kind));
- cur.posRight();
+ cur.posForward();
}
static bool doInsertInset(Cursor & cur, Text * text,
FuncRequest const & cmd, bool edit, bool pastesel)
{
- Inset * inset = createInset(&cur.bv(), cmd);
+ Inset * inset = createInset(cur.bv().buffer(), cmd);
if (!inset)
return false;
}
+/// the type of outline operation
+enum OutlineOp {
+ OutlineUp, // Move this header with text down
+ OutlineDown, // Move this header with text up
+ OutlineIn, // Make this header deeper
+ OutlineOut // Make this header shallower
+};
+
+
+static void outline(OutlineOp mode, Cursor & cur)
+{
+ Buffer & buf = cur.buffer();
+ pit_type & pit = cur.pit();
+ ParagraphList & pars = buf.text().paragraphs();
+ ParagraphList::iterator bgn = pars.begin();
+ // The first paragraph of the area to be copied:
+ ParagraphList::iterator start = boost::next(bgn, pit);
+ // The final paragraph of area to be copied:
+ ParagraphList::iterator finish = start;
+ ParagraphList::iterator end = pars.end();
+
+ TextClass::const_iterator lit =
+ buf.params().getTextClass().begin();
+ TextClass::const_iterator const lend =
+ buf.params().getTextClass().end();
+
+ int const thistoclevel = start->layout()->toclevel;
+ int toclevel;
+ switch (mode) {
+ case OutlineUp: {
+ // Move out (down) from this section header
+ if (finish != end)
+ ++finish;
+ // Seek the one (on same level) below
+ for (; finish != end; ++finish) {
+ toclevel = finish->layout()->toclevel;
+ if (toclevel != Layout::NOT_IN_TOC
+ && toclevel <= thistoclevel) {
+ break;
+ }
+ }
+ ParagraphList::iterator dest = start;
+ // Move out (up) from this header
+ if (dest == bgn)
+ break;
+ // Search previous same-level header above
+ do {
+ --dest;
+ toclevel = dest->layout()->toclevel;
+ } while(dest != bgn
+ && (toclevel == Layout::NOT_IN_TOC
+ || toclevel > thistoclevel));
+ // Not found; do nothing
+ if (toclevel == Layout::NOT_IN_TOC || toclevel > thistoclevel)
+ break;
+ pit_type const newpit = std::distance(bgn, dest);
+ pit_type const len = std::distance(start, finish);
+ pit_type const deletepit = pit + len;
+ buf.undo().recordUndo(cur, ATOMIC_UNDO, newpit, deletepit - 1);
+ pars.insert(dest, start, finish);
+ start = boost::next(pars.begin(), deletepit);
+ pit = newpit;
+ pars.erase(start, finish);
+ break;
+ }
+ case OutlineDown: {
+ // Go down out of current header:
+ if (finish != end)
+ ++finish;
+ // Find next same-level header:
+ for (; finish != end; ++finish) {
+ toclevel = finish->layout()->toclevel;
+ if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel)
+ break;
+ }
+ ParagraphList::iterator dest = finish;
+ // Go one down from *this* header:
+ if (dest != end)
+ ++dest;
+ else
+ break;
+ // Go further down to find header to insert in front of:
+ for (; dest != end; ++dest) {
+ toclevel = dest->layout()->toclevel;
+ if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel)
+ break;
+ }
+ // One such was found:
+ pit_type newpit = std::distance(bgn, dest);
+ pit_type const len = std::distance(start, finish);
+ buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, newpit - 1);
+ pars.insert(dest, start, finish);
+ start = boost::next(bgn, pit);
+ pit = newpit - len;
+ pars.erase(start, finish);
+ break;
+ }
+ case OutlineIn:
+ buf.undo().recordUndo(cur);
+ for (; lit != lend; ++lit) {
+ if ((*lit)->toclevel == thistoclevel + 1 &&
+ start->layout()->labeltype == (*lit)->labeltype) {
+ start->layout((*lit));
+ break;
+ }
+ }
+ break;
+ case OutlineOut:
+ buf.undo().recordUndo(cur);
+ for (; lit != lend; ++lit) {
+ if ((*lit)->toclevel == thistoclevel - 1 &&
+ start->layout()->labeltype == (*lit)->labeltype) {
+ start->layout((*lit));
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
void Text::number(Cursor & cur)
{
FontInfo font = ignore_font;
cur.recordUndo();
cap::replaceSelection(cur);
cur.insert(new InsetNewline);
- cur.posRight();
+ cur.posForward();
moveCursor(cur, false);
}
break;
case LFUN_INSET_INSERT: {
cur.recordUndo();
- Inset * inset = createInset(bv, cmd);
+ Inset * inset = createInset(bv->buffer(), cmd);
if (inset) {
// FIXME (Abdel 01/02/2006):
// What follows would be a partial fix for bug 2154:
if (cur.selection())
cutSelection(cur, true, false);
insertInset(cur, inset);
- cur.posRight();
+ cur.posForward();
}
break;
}
insertChar(cur, ' ');
else {
doInsertInset(cur, this, cmd, false, false);
- cur.posRight();
+ cur.posForward();
}
moveCursor(cur, false);
break;
cur.insert(new InsetQuotes(c,
bufparams.quotes_language,
InsetQuotes::DoubleQ));
- cur.posRight();
+ cur.posForward();
}
else
lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, "\""));
// true (on).
if (lyxrc.auto_region_delete && cur.selection()) {
+ pit_type const begpit = cur.selBegin().pit();
+ pit_type const endpit = cur.selEnd().pit();
cutSelection(cur, false, false);
- // When change tracking is set to off, the metrics update
- // mechanism correctly detects if a full update is needed or not.
- // This detection fails when a selection spans multiple rows and
- // change tracking is enabled because the paragraph metrics stays
- // the same. In this case, we force the full update:
- // (see http://bugzilla.lyx.org/show_bug.cgi?id=3992)
- if (cur.buffer().params().trackChanges)
+ // When a selection spans multiple paragraphs, the metrics update
+ // mechanism sometimes fail to detect that a full update is needed.
+ // In this case, we force the full update:
+ // (see http://bugzilla.lyx.org/show_bug.cgi?id=4317)
+ if (isMainText(cur.bv().buffer()) && begpit != endpit)
cur.updateFlags(Update::Force);
}
}
case LFUN_INFO_INSERT: {
- Inset * inset = createInset(&cur.bv(), cmd);
+ Inset * inset = createInset(cur.bv().buffer(), cmd);
if (!inset)
break;
// if an empty inset is created (cmd.argument() is empty)
static_cast<InsetInfo *>(inset)->setInfo(to_utf8(ds));
}
insertInset(cur, inset);
- cur.posRight();
+ cur.posForward();
break;
}
#if 0
// Open the inset, and move the current selection
// inside it.
doInsertInset(cur, this, cmd, true, true);
- cur.posRight();
+ cur.posForward();
// These insets are numbered.
updateLabels(bv->buffer());
break;
// Open the inset, and move the current selection
// inside it.
doInsertInset(cur, this, cmd, true, true);
- cur.posRight();
+ cur.posForward();
break;
case LFUN_TABULAR_INSERT:
// if there were no arguments, just open the dialog
if (doInsertInset(cur, this, cmd, false, true))
- cur.posRight();
+ cur.posForward();
else
bv->showDialog("tabularcreate");
bool content = cur.selection(); // will some text be moved into the inset?
doInsertInset(cur, this, cmd, true, true);
- cur.posRight();
+ cur.posForward();
ParagraphList & pars = cur.text()->paragraphs();
TextClass const & tclass = bv->buffer().params().getTextClass();
case LFUN_INDEX_INSERT:
doInsertInset(cur, this, cmd, true, true);
- cur.posRight();
+ cur.posForward();
break;
+
case LFUN_NOMENCL_INSERT: {
- Inset * inset = createInset(&cur.bv(), cmd);
+ FuncRequest cmd1 = cmd;
+ if (cmd.argument().empty())
+ cmd1 = FuncRequest(cmd,
+ bv->cursor().innerText()->getStringToIndex(bv->cursor()));
+ Inset * inset = createInset(cur.bv().buffer(), cmd1);
if (!inset)
break;
cur.recordUndo();
// description entry still needs to be filled in.
if (cmd.action == LFUN_NOMENCL_INSERT)
inset->edit(cur, true);
- cur.posRight();
+ cur.posForward();
break;
}
case LFUN_CLEARDOUBLEPAGE_INSERT:
// do nothing fancy
doInsertInset(cur, this, cmd, false, false);
- cur.posRight();
+ cur.posForward();
break;
case LFUN_DEPTH_DECREMENT:
ParagraphParameters p;
setParagraphs(cur, p);
insertInset(cur, new InsetFloatList(to_utf8(cmd.argument())));
- cur.posRight();
+ cur.posForward();
} else {
lyxerr << "Non-existent float type: "
<< to_utf8(cmd.argument()) << endl;
}
break;
+ case LFUN_OUTLINE_UP:
+ outline(OutlineUp, cur);
+ setCursor(cur, cur.pit(), 0);
+ updateLabels(cur.buffer());
+ needsUpdate = true;
+ break;
+
+ case LFUN_OUTLINE_DOWN:
+ outline(OutlineDown, cur);
+ setCursor(cur, cur.pit(), 0);
+ updateLabels(cur.buffer());
+ needsUpdate = true;
+ break;
+
+ case LFUN_OUTLINE_IN:
+ outline(OutlineIn, cur);
+ updateLabels(cur.buffer());
+ needsUpdate = true;
+ break;
+
+ case LFUN_OUTLINE_OUT:
+ outline(OutlineOut, cur);
+ updateLabels(cur.buffer());
+ needsUpdate = true;
+ break;
+
default:
LYXERR(Debug::ACTION)
<< BOOST_CURRENT_FUNCTION
== olddim.height()) {
// if so, update _only_ this paragraph
cur.updateFlags(Update::SinglePar |
- Update::FitCursor |
- Update::MultiParSel);
+ Update::FitCursor);
return;
} else
needsUpdate = true;
enable = true;
break;
+ case LFUN_OUTLINE_UP:
+ case LFUN_OUTLINE_DOWN:
+ case LFUN_OUTLINE_IN:
+ case LFUN_OUTLINE_OUT:
+ enable = (cur.paragraph().layout()->toclevel != Layout::NOT_IN_TOC);
+ break;
+
case LFUN_WORD_DELETE_FORWARD:
case LFUN_WORD_DELETE_BACKWARD:
case LFUN_LINE_DELETE: