Patch from Martin V.: Fix Undo/Redo bugs with outline.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15948 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2006-11-16 12:20:50 +00:00
parent bb8c9253e4
commit 454bf36bc3

View File

@ -31,13 +31,14 @@ namespace toc {
void outline(OutlineOp mode, LCursor & cur) void outline(OutlineOp mode, LCursor & cur)
{ {
recordUndo(cur);
Buffer * buf = & cur.buffer(); Buffer * buf = & cur.buffer();
pit_type & pit = cur.pit(); pit_type & pit = cur.pit();
ParagraphList & pars = buf->text().paragraphs(); ParagraphList & pars = buf->text().paragraphs();
ParagraphList::iterator bgn = pars.begin(); ParagraphList::iterator bgn = pars.begin();
ParagraphList::iterator s = boost::next(bgn, pit); // The first paragraph of the area to be copied:
ParagraphList::iterator p = s; ParagraphList::iterator start = boost::next(bgn, pit);
// The final paragraph of area to be copied:
ParagraphList::iterator finish = start;
ParagraphList::iterator end = pars.end(); ParagraphList::iterator end = pars.end();
LyXTextClass::const_iterator lit = LyXTextClass::const_iterator lit =
@ -45,86 +46,101 @@ void outline(OutlineOp mode, LCursor & cur)
LyXTextClass::const_iterator const lend = LyXTextClass::const_iterator const lend =
buf->params().getLyXTextClass().end(); buf->params().getLyXTextClass().end();
int const thistoclevel = s->layout()->toclevel; int const thistoclevel = start->layout()->toclevel;
int toclevel; int toclevel;
switch (mode) { switch (mode) {
case Up: { case Up: {
if (p != end) // Move out (down) from this section header
++p; if (finish != end)
for (; p != end; ++p) { ++finish;
toclevel = p->layout()->toclevel; // Seek the one (on same level) below
for (; finish != end; ++finish) {
toclevel = finish->layout()->toclevel;
if (toclevel != LyXLayout::NOT_IN_TOC if (toclevel != LyXLayout::NOT_IN_TOC
&& toclevel <= thistoclevel) { && toclevel <= thistoclevel) {
break; break;
} }
} }
ParagraphList::iterator q = s; ParagraphList::iterator dest = start;
if (q != bgn) // Move out (up) from this header
--q; if (dest != bgn)
--dest;
else else
break; break;
for (; q != bgn; --q) { // Search previous same-level header above
toclevel = q->layout()->toclevel; for (; dest != bgn; --dest) {
toclevel = dest->layout()->toclevel;
if (toclevel != LyXLayout::NOT_IN_TOC if (toclevel != LyXLayout::NOT_IN_TOC
&& toclevel <= thistoclevel) { && toclevel <= thistoclevel) {
break; break;
} }
} }
pit_type const newpit = std::distance(pars.begin(), q); // Not found; do nothing
pit_type const len = std::distance(s, p); if (dest == bgn)
break;
pit_type const newpit = std::distance(bgn, dest);
pit_type const len = std::distance(start, finish);
pit += len; pit += len;
pars.insert(q, s, p); pit = std::min(pit, cur.lastpit());
s = boost::next(pars.begin(), pit); recordUndo(cur, Undo::ATOMIC, newpit, pit);
ParagraphList::iterator t = boost::next(s, len); pars.insert(dest, start, finish);
start = boost::next(bgn, pit);
pit = newpit; pit = newpit;
pars.erase(s, t); pars.erase(start, finish);
break; break;
} }
case Down: { case Down: {
if (p != end) // Go down out of current header:
++p; if (finish != end)
for (; p != end; ++p) { ++finish;
toclevel = p->layout()->toclevel; // Find next same-level header:
for (; finish != end; ++finish) {
toclevel = finish->layout()->toclevel;
if (toclevel != LyXLayout::NOT_IN_TOC if (toclevel != LyXLayout::NOT_IN_TOC
&& toclevel <= thistoclevel) { && toclevel <= thistoclevel) {
break; break;
} }
} }
ParagraphList::iterator q = p; ParagraphList::iterator dest = finish;
if (q != end) // Go one down from *this* header:
++q; if (dest != end)
++dest;
else else
break; break;
for (; q != end; ++q) { // Go further down to find header to insert in front of:
toclevel = q->layout()->toclevel; for (; dest != end; ++dest) {
toclevel = dest->layout()->toclevel;
if (toclevel != LyXLayout::NOT_IN_TOC if (toclevel != LyXLayout::NOT_IN_TOC
&& toclevel <= thistoclevel) { && toclevel <= thistoclevel) {
break; break;
} }
} }
pit_type const newpit = std::distance(pars.begin(), q); // One such was found:
pit_type const len = std::distance(s, p); pit_type newpit = std::distance(bgn, dest);
pars.insert(q, s, p); pit_type const len = std::distance(start, finish);
s = boost::next(pars.begin(), pit); recordUndo(cur, Undo::ATOMIC, pit, newpit -1);
ParagraphList::iterator t = boost::next(s, len); pars.insert(dest, start, finish);
start = boost::next(bgn, pit);
pit = newpit - len; pit = newpit - len;
pars.erase(s, t); pars.erase(start, finish);
break; break;
} }
case In: case In:
recordUndo(cur);
for (; lit != lend; ++lit) { for (; lit != lend; ++lit) {
if ((*lit)->toclevel == thistoclevel + 1 && if ((*lit)->toclevel == thistoclevel + 1 &&
s->layout()->labeltype == (*lit)->labeltype) { start->layout()->labeltype == (*lit)->labeltype) {
s->layout((*lit)); start->layout((*lit));
break; break;
} }
} }
break; break;
case Out: case Out:
recordUndo(cur);
for (; lit != lend; ++lit) { for (; lit != lend; ++lit) {
if ((*lit)->toclevel == thistoclevel - 1 && if ((*lit)->toclevel == thistoclevel - 1 &&
s->layout()->labeltype == (*lit)->labeltype) { start->layout()->labeltype == (*lit)->labeltype) {
s->layout((*lit)); start->layout((*lit));
break; break;
} }
} }