X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fundo.C;h=536a2e4d5c161c6f8b43ab129ee84bc819e35134;hb=e7fc677261bd14fdf159e594fcf422e985c72664;hp=ab798f3dfe8d32c6d60eedb02da7bef9a09f4310;hpb=5198e1d9a383d60f915092f17661f98f59998ed0;p=lyx.git diff --git a/src/undo.C b/src/undo.C index ab798f3dfe..536a2e4d5c 100644 --- a/src/undo.C +++ b/src/undo.C @@ -22,18 +22,20 @@ #include "BufferView.h" #include "lyxtext.h" #include "paragraph.h" +#include "ParagraphList.h" #include "mathed/math_support.h" +#include "insets/inset.h" #include -using lyx::paroffset_type; +using lyx::pit_type; +using std::advance; +using std::endl; -namespace { -/// Whether actions are not added to the undo stacks. -bool undo_frozen; +namespace { /// The flag used by finishUndo(). bool undo_finished; @@ -41,28 +43,42 @@ bool undo_finished; std::ostream & operator<<(std::ostream & os, Undo const & undo) { - return os << " from: " << undo.from - << " end: " << undo.end + return os << " from: " << undo.from << " end: " << undo.end + << " cell:\n" << undo.cell << " cursor:\n" << undo.cursor; } -void recordUndo(Undo::undo_kind kind, - LCursor & cur, paroffset_type first_par, paroffset_type last_par, - limited_stack & stack) +bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) { - BOOST_ASSERT(first_par <= cur.lastpar()); - BOOST_ASSERT(last_par <= cur.lastpar()); + StableDocIterator tmpi2 = i2; + tmpi2.pos() = i1.pos(); + return i1 == tmpi2; +} - if (first_par > last_par) - std::swap(first_par, last_par); +void doRecordUndo(Undo::undo_kind kind, + DocIterator const & cell, + pit_type first_pit, pit_type last_pit, + DocIterator const & cur, + BufferParams const & bparams, + bool isFullBuffer, + limited_stack & stack) +{ + if (first_pit > last_pit) + std::swap(first_pit, last_pit); // create the position information of the Undo entry Undo undo; undo.kind = kind; - undo.cursor = StableDocumentIterator(cur); - undo.from = first_par; - undo.end = cur.lastpar() - last_par; + undo.cell = cell; + undo.cursor = cur; + undo.bparams = bparams ; + undo.isFullBuffer = isFullBuffer; + //lyxerr << "recordUndo: cur: " << cur << endl; + //lyxerr << "recordUndo: pos: " << cur.pos() << endl; + //lyxerr << "recordUndo: cell: " << cell << endl; + undo.from = first_pit; + undo.end = cell.lastpit() - last_pit; // Undo::ATOMIC are always recorded (no overlapping there). // As nobody wants all removed character appear one by one when undoing, @@ -70,31 +86,31 @@ void recordUndo(Undo::undo_kind kind, if (!undo_finished && kind != Undo::ATOMIC && !stack.empty() - && stack.top().cursor.size() == undo.cursor.size() - && stack.top().kind == undo.kind - && stack.top().from == undo.from - && stack.top().end == undo.end) + && samePar(stack.top().cell, undo.cell) + && stack.top().kind == undo.kind + && stack.top().from == undo.from + && stack.top().end == undo.end) return; // fill in the real data to be saved - if (cur.inMathed()) { + if (cell.inMathed()) { // simply use the whole cell - undo.array = asString(cur.cell()); + undo.array = asString(cell.cell()); } else { // some more effort needed here as 'the whole cell' of the // main LyXText _is_ the whole document. // record the relevant paragraphs - LyXText * text = cur.text(); + LyXText const * text = cell.text(); BOOST_ASSERT(text); - ParagraphList & plist = text->paragraphs(); - ParagraphList::iterator first = plist.begin(); - advance(first, first_par); - ParagraphList::iterator last = plist.begin(); - advance(last, last_par + 1); + ParagraphList const & plist = text->paragraphs(); + ParagraphList::const_iterator first = plist.begin(); + advance(first, first_pit); + ParagraphList::const_iterator last = plist.begin(); + advance(last, last_pit + 1); undo.pars = ParagraphList(first, last); } - // push the undo entry to undo stack + // push the undo entry to undo stack //lyxerr << "undo record: " << stack.top() << std::endl; stack.push(undo); @@ -103,20 +119,59 @@ void recordUndo(Undo::undo_kind kind, } -void performUndoOrRedo(BufferView & bv, Undo const & undo) +void recordUndo(Undo::undo_kind kind, + LCursor & cur, pit_type first_pit, pit_type last_pit, + limited_stack & stack) { - LCursor & cur = bv.cursor(); - lyxerr << "undo, performing: " << undo << std::endl; - cur.setCursor(undo.cursor.asDocumentIterator(&bv.buffer()->inset()), false); + BOOST_ASSERT(first_pit <= cur.lastpit()); + BOOST_ASSERT(last_pit <= cur.lastpit()); + + doRecordUndo(kind, cur, first_pit, last_pit, cur, + cur.bv().buffer()->params(), false, stack); +} + + + +// Returns false if no undo possible. +bool textUndoOrRedo(BufferView & bv, + limited_stack & stack, limited_stack & otherstack) +{ + finishUndo(); + + if (stack.empty()) { + // Nothing to do. + return false; + } - if (cur.inMathed()) { + // Adjust undo stack and get hold of current undo data. + Undo undo = stack.top(); + stack.pop(); + + // We will store in otherstack the part of the document under 'undo' + Buffer * buf = bv.buffer(); + DocIterator cell_dit = undo.cell.asDocIterator(&buf->inset()); + + doRecordUndo(Undo::ATOMIC, cell_dit, + undo.from, cell_dit.lastpit() - undo.end, bv.cursor(), + undo.bparams, undo.isFullBuffer, + otherstack); + + // This does the actual undo/redo. + //lyxerr << "undo, performing: " << undo << std::endl; + DocIterator dit = undo.cell.asDocIterator(&buf->inset()); + if (undo.isFullBuffer) { + // This is a full document + otherstack.top().bparams = buf->params(); + buf->params() = undo.bparams; + buf->paragraphs() = undo.pars; + } else if (dit.inMathed()) { // We stored the full cell here as there is not much to be // gained by storing just 'a few' paragraphs (most if not // all math inset cells have just one paragraph!) - asArray(undo.array, cur.cell()); + asArray(undo.array, dit.cell()); } else { // Some finer machinery is needed here. - LyXText * text = cur.text(); + LyXText * text = dit.text(); BOOST_ASSERT(text); ParagraphList & plist = text->paragraphs(); @@ -130,55 +185,23 @@ void performUndoOrRedo(BufferView & bv, Undo const & undo) // re-insert old stuff instead first = plist.begin(); advance(first, undo.from); + + // this ugly stuff is needed until we get rid of the + // inset_owner backpointer + ParagraphList::iterator pit = undo.pars.begin(); + ParagraphList::iterator const end = undo.pars.end(); + for (; pit != end; ++pit) + pit->setInsetOwner(dit.realInset()); plist.insert(first, undo.pars.begin(), undo.pars.end()); } + // Set cursor + LCursor & cur = bv.cursor(); + cur.setCursor(undo.cursor.asDocIterator(&buf->inset())); + cur.selection() = false; cur.resetAnchor(); finishUndo(); -} - - -// returns false if no undo possible -bool textUndoOrRedo(BufferView & bv, - limited_stack & stack, limited_stack & otherstack) -{ - if (stack.empty()) { - // nothing to do - finishUndo(); - return false; - } - - Undo undo = stack.top(); - stack.pop(); - finishUndo(); - - // this implements redo - if (!undo_frozen) { - otherstack.push(undo); - DocumentIterator dit = - undo.cursor.asDocumentIterator(&bv.buffer()->inset()); - if (dit.inMathed()) { - // not much to be done - } else { - otherstack.top().pars.clear(); - LyXText * text = dit.text(); - BOOST_ASSERT(text); - ParagraphList & plist = text->paragraphs(); - if (undo.from + undo.end <= int(plist.size())) { - ParagraphList::iterator first = plist.begin(); - advance(first, undo.from); - ParagraphList::iterator last = plist.begin(); - advance(last, plist.size() - undo.end); - otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last); - } - } - otherstack.top().cursor = bv.cursor(); - //lyxerr << " undo other: " << otherstack.top() << std::endl; - } - undo_frozen = true; - performUndoOrRedo(bv, undo); - undo_frozen = false; return true; } @@ -187,7 +210,7 @@ bool textUndoOrRedo(BufferView & bv, void finishUndo() { - // makes sure the next operation will be stored + // Make sure the next operation will be stored. undo_finished = true; } @@ -207,10 +230,8 @@ bool textRedo(BufferView & bv) void recordUndo(Undo::undo_kind kind, - LCursor & cur, paroffset_type first, paroffset_type last) + LCursor & cur, pit_type first, pit_type last) { - if (undo_frozen) - return; Buffer * buf = cur.bv().buffer(); recordUndo(kind, cur, first, last, buf->undostack()); buf->redostack().clear(); @@ -222,31 +243,48 @@ void recordUndo(Undo::undo_kind kind, void recordUndo(LCursor & cur, Undo::undo_kind kind) { - recordUndo(kind, cur, cur.par(), cur.par()); + recordUndo(kind, cur, cur.pit(), cur.pit()); +} + + +void recordUndoInset(LCursor & cur, Undo::undo_kind kind) +{ + LCursor c = cur; + c.pop(); + recordUndo(c, kind); } void recordUndoSelection(LCursor & cur, Undo::undo_kind kind) { - recordUndo(kind, cur, cur.selBegin().par(), cur.selEnd().par()); + recordUndo(kind, cur, cur.selBegin().pit(), cur.selEnd().pit()); } -void recordUndo(LCursor & cur, Undo::undo_kind kind, paroffset_type from) +void recordUndo(LCursor & cur, Undo::undo_kind kind, pit_type from) { - recordUndo(kind, cur, cur.par(), from); + recordUndo(kind, cur, cur.pit(), from); } void recordUndo(LCursor & cur, Undo::undo_kind kind, - paroffset_type from, paroffset_type to) + pit_type from, pit_type to) { recordUndo(kind, cur, from, to); } -void recordUndoFullDocument(LCursor &) +void recordUndoFullDocument(BufferView * bv) { - //recordUndo(Undo::ATOMIC, - // cur, 0, cur.bv().text()->paragraphs().size() - 1); + Buffer * buf = bv->buffer(); + doRecordUndo( + Undo::ATOMIC, + doc_iterator_begin(buf->inset()), + 0, buf->paragraphs().size() - 1, + bv->cursor(), + buf->params(), + true, + buf->undostack() + ); + undo_finished = false; }