X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FUndo.cpp;h=28438c10f39711b0caa2cbcd6441a3bd6f1d6a5f;hb=8ea66efe16ad109a5c107716185fb82bbebca8c8;hp=e130cd8fdc61d32a6a15112aa6340bd0fadf805a;hpb=5577e877bb0a25a0919db09b10effe9f54ff1333;p=lyx.git diff --git a/src/Undo.cpp b/src/Undo.cpp index e130cd8fdc..28438c10f3 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -43,37 +43,36 @@ using namespace lyx::support; namespace lyx { /** -These are the elements put on the undo stack. Each object contains complete -paragraphs from some cell and sufficient information to restore the cursor -state. +These are the elements put on the undo stack. Each object contains +complete paragraphs from some cell and sufficient information to +restore the cursor state. -The cell is given by a DocIterator pointing to this cell, the 'interesting' -range of paragraphs by counting them from begin and end of cell, -respectively. +The cell is given by a DocIterator pointing to this cell, the +'interesting' range of paragraphs by counting them from begin and end +of cell, respectively. -The cursor is also given as DocIterator and should point to some place in -the stored paragraph range. In case of math, we simply store the whole -cell, as there usually is just a simple paragraph in a cell. +The cursor is also given as DocIterator and should point to some place +in the stored paragraph range. In case of math, we simply store the +whole cell, as there usually is just a simple paragraph in a cell. The idea is to store the contents of 'interesting' paragraphs in some structure ('Undo') _before_ it is changed in some edit operation. -Obviously, the stored ranged should be as small as possible. However, it -there is a lower limit: The StableDocIterator pointing stored in the undo -class must be valid after the changes, too, as it will used as a pointer -where to insert the stored bits when performining undo. +Obviously, the stored range should be as small as possible. However, +there is a lower limit: The StableDocIterator stored in the undo class +must be valid after the changes, too, as it will used as a pointer +where to insert the stored bits when performining undo. */ - - struct UndoElement { /// - UndoElement(UndoKind kin, StableDocIterator const & cur, + UndoElement(UndoKind kin, StableDocIterator const & cb, StableDocIterator const & cel, pit_type fro, pit_type en, ParagraphList * pl, MathData * ar, BufferParams const & bp, - bool ifb, size_t gid) : - kind(kin), cursor(cur), cell(cel), from(fro), end(en), - pars(pl), array(ar), bparams(0), isFullBuffer(ifb), group_id(gid) + bool ifb, bool lc, size_t gid) : + kind(kin), cur_before(cb), cell(cel), from(fro), end(en), + pars(pl), array(ar), bparams(0), isFullBuffer(ifb), + lyx_clean(lc), group_id(gid) { if (isFullBuffer) bparams = new BufferParams(bp); @@ -82,7 +81,8 @@ struct UndoElement UndoElement(UndoElement const & ue) { kind = ue.kind; - cursor = ue.cursor; + cur_before = ue.cur_before; + cur_after = ue.cur_after; cell = ue.cell; from = ue.from; end = ue.end; @@ -91,6 +91,7 @@ struct UndoElement bparams = ue.isFullBuffer ? new BufferParams(*ue.bparams) : ue.bparams; isFullBuffer = ue.isFullBuffer; + lyx_clean = ue.lyx_clean; group_id = ue.group_id; } /// @@ -101,8 +102,10 @@ struct UndoElement } /// Which kind of operation are we recording for? UndoKind kind; - /// the position of the cursor - StableDocIterator cursor; + /// the position of the cursor before recordUndo + StableDocIterator cur_before; + /// the position of the cursor at the end of the undo group + StableDocIterator cur_after; /// the position of the cell described StableDocIterator cell; /// counted from begin of cell @@ -117,6 +120,8 @@ struct UndoElement BufferParams const * bparams; /// Only used in case of full backups bool isFullBuffer; + /// Was the buffer clean at this point? + bool lyx_clean; /// the element's group id size_t group_id; private: @@ -163,6 +168,12 @@ public: } } + /// Mark all the elements of the stack as dirty + void markDirty() { + for (size_t i = 0; i != c_.size(); ++i) + c_[i].lyx_clean = false; + } + private: /// Internal contents. std::deque c_; @@ -177,7 +188,8 @@ struct Undo::Private group_id(0), group_level(0) {} // Do one undo/redo step - void doTextUndoOrRedo(DocIterator & cur, UndoElementStack & stack, UndoElementStack & otherStack); + void doTextUndoOrRedo(DocIterator & cur, UndoElementStack & stack, + UndoElementStack & otherStack); // Apply one undo/redo group. Returns false if no undo possible. bool textUndoOrRedo(DocIterator & cur, bool isUndoOperation); @@ -186,14 +198,16 @@ struct Undo::Private DocIterator const & cell, pit_type first_pit, pit_type last_pit, - DocIterator const & cur, + StableDocIterator const & cur, bool isFullBuffer, UndoElementStack & stack); /// void recordUndo(UndoKind kind, - DocIterator const & cur, + DocIterator const & cell, pit_type first_pit, - pit_type last_pit); + pit_type last_pit, + DocIterator const & cur, + bool isFullBuffer); /// Buffer & buffer_; @@ -230,6 +244,16 @@ Undo::~Undo() } +void Undo::clear() +{ + d->undostack_.clear(); + d->redostack_.clear(); + d->undo_finished_ = true; + d->group_id = 0; + d->group_level = 0; +} + + bool Undo::hasUndoStack() const { return !d->undostack_.empty(); @@ -242,11 +266,11 @@ bool Undo::hasRedoStack() const } -static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) +void Undo::markDirty() { - StableDocIterator tmpi2 = i2; - tmpi2.pos() = i1.pos(); - return i1 == tmpi2; + d->undo_finished_ = true; + d->undostack_.markDirty(); + d->redostack_.markDirty(); } @@ -256,10 +280,18 @@ static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) // /////////////////////////////////////////////////////////////////////// +static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) +{ + StableDocIterator tmpi2 = i2; + tmpi2.pos() = i1.pos(); + return i1 == tmpi2; +} + + void Undo::Private::doRecordUndo(UndoKind kind, DocIterator const & cell, pit_type first_pit, pit_type last_pit, - DocIterator const & cur, + StableDocIterator const & cur_before, bool isFullBuffer, UndoElementStack & stack) { @@ -282,16 +314,19 @@ void Undo::Private::doRecordUndo(UndoKind kind, && samePar(stack.top().cell, cell) && stack.top().kind == kind && stack.top().from == from - && stack.top().end == end) + && stack.top().end == end) { + // reset cur_after; it will be filled correctly by endUndoGroup. + stack.top().cur_after = StableDocIterator(); return; + } if (isFullBuffer) LYXERR(Debug::UNDO, "Create full buffer undo element of group " << group_id); else LYXERR(Debug::UNDO, "Create undo element of group " << group_id); // create the position information of the Undo entry - UndoElement undo(kind, cur, cell, from, end, 0, 0, - buffer_.params(), isFullBuffer, group_id); + UndoElement undo(kind, cur_before, cell, from, end, 0, 0, + buffer_.params(), isFullBuffer, buffer_.isClean(), group_id); // fill in the real data to be saved if (cell.inMathed()) { @@ -315,22 +350,27 @@ void Undo::Private::doRecordUndo(UndoKind kind, // push the undo entry to undo stack stack.push(undo); //lyxerr << "undo record: " << stack.top() << endl; - - // next time we'll try again to combine entries if possible - undo_finished_ = false; } -void Undo::Private::recordUndo(UndoKind kind, DocIterator const & cur, - pit_type first_pit, pit_type last_pit) +void Undo::Private::recordUndo(UndoKind kind, + DocIterator const & cell, + pit_type first_pit, pit_type last_pit, + DocIterator const & cur, + bool isFullBuffer) { - LASSERT(first_pit <= cur.lastpit(), /**/); - LASSERT(last_pit <= cur.lastpit(), /**/); + LASSERT(first_pit <= cell.lastpit(), /**/); + LASSERT(last_pit <= cell.lastpit(), /**/); - doRecordUndo(kind, cur, first_pit, last_pit, cur, - false, undostack_); + doRecordUndo(kind, cell, first_pit, last_pit, cur, + isFullBuffer, undostack_); + // next time we'll try again to combine entries if possible undo_finished_ = false; + + // If we ran recordUndo, it means that we plan to change the buffer + buffer_.markDirty(); + redostack_.clear(); //lyxerr << "undostack:\n"; //for (size_t i = 0, n = buf.undostack().size(); i != n && i < 6; ++i) @@ -350,8 +390,9 @@ void Undo::Private::doTextUndoOrRedo(DocIterator & cur, UndoElementStack & stack DocIterator cell_dit = undo.cell.asDocIterator(&buffer_); doRecordUndo(ATOMIC_UNDO, cell_dit, - undo.from, cell_dit.lastpit() - undo.end, cur, + undo.from, cell_dit.lastpit() - undo.end, undo.cur_after, undo.isFullBuffer, otherstack); + otherstack.top().cur_after = undo.cur_before; // This does the actual undo/redo. //LYXERR0("undo, performing: " << undo); @@ -405,7 +446,12 @@ void Undo::Private::doTextUndoOrRedo(DocIterator & cur, UndoElementStack & stack LASSERT(undo.pars == 0, /**/); LASSERT(undo.array == 0, /**/); - cur = undo.cursor.asDocIterator(&buffer_); + if (undo.cur_before.size()) + cur = undo.cur_before.asDocIterator(&buffer_); + if (undo.lyx_clean) + buffer_.markClean(); + else + buffer_.markDirty(); // Now that we're done with undo, we pop it off the stack. stack.pop(); } @@ -475,31 +521,48 @@ void Undo::endUndoGroup() } +void Undo::endUndoGroup(DocIterator const & cur) +{ + endUndoGroup(); + if (!d->undostack_.empty() && !d->undostack_.top().cur_after.size()) + d->undostack_.top().cur_after = cur; +} + + +// FIXME: remove these convenience functions and make +// Private::recordUndo public as sole interface. The code in the +// convenience functions can move to Cursor.cpp. void Undo::recordUndo(DocIterator const & cur, UndoKind kind) { - d->recordUndo(kind, cur, cur.pit(), cur.pit()); + d->recordUndo(kind, cur, cur.pit(), cur.pit(), cur, false); } -void Undo::recordUndoInset(DocIterator const & cur, UndoKind kind) +void Undo::recordUndoInset(DocIterator const & cur, UndoKind kind, + Inset const * inset) { - DocIterator c = cur; - c.pop_back(); - d->doRecordUndo(kind, c, c.pit(), c.pit(), cur, false, d->undostack_); + if (!inset || inset == &cur.inset()) { + DocIterator c = cur; + c.pop_back(); + d->recordUndo(kind, c, c.pit(), c.pit(), cur, false); + } else if (inset == cur.nextInset()) + recordUndo(cur, kind); + else + LYXERR0("Inset not found, no undo stack added."); } void Undo::recordUndo(DocIterator const & cur, UndoKind kind, pit_type from) { - d->recordUndo(kind, cur, cur.pit(), from); + d->recordUndo(kind, cur, cur.pit(), from, cur, false); } void Undo::recordUndo(DocIterator const & cur, UndoKind kind, pit_type from, pit_type to) { - d->recordUndo(kind, cur, from, to); + d->recordUndo(kind, cur, from, to, cur, false); } @@ -508,14 +571,8 @@ void Undo::recordUndoFullDocument(DocIterator const & cur) // This one may happen outside of the main undo group, so we // put it in its own subgroup to avoid complaints. beginUndoGroup(); - d->doRecordUndo( - ATOMIC_UNDO, - doc_iterator_begin(&d->buffer_), - 0, d->buffer_.paragraphs().size() - 1, - cur, - true, - d->undostack_ - ); + d->recordUndo(ATOMIC_UNDO, doc_iterator_begin(&d->buffer_), + 0, d->buffer_.paragraphs().size() - 1, cur, true); endUndoGroup(); }