X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FUndo.cpp;h=95eb160d60c9c19494cf3646fac858b90964db48;hb=52fee3556e63859f3ba52609e8f025a491767a81;hp=31eaec3dbd84977ee7d52e3dca4c86b3726df7f9;hpb=4356f2254af1a0ea5e4215e29881296452b1e8d9;p=lyx.git diff --git a/src/Undo.cpp b/src/Undo.cpp index 31eaec3dbd..95eb160d60 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -33,6 +33,7 @@ #include "support/debug.h" #include "support/gettext.h" #include "support/lassert.h" +#include "support/lyxtime.h" #include #include @@ -68,18 +69,23 @@ struct UndoElement /// UndoElement(UndoKind kin, CursorData const & cb, StableDocIterator const & cel, - pit_type fro, pit_type en, ParagraphList * pl, - MathData * ar, BufferParams const & bp, - 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) + pit_type fro, pit_type en, ParagraphList * pl, MathData * ar, + bool lc, size_t gid) : + kind(kin), cur_before(cb), cell(cel), from(fro), end(en), + pars(pl), array(ar), bparams(0), + lyx_clean(lc), group_id(gid), time(current_time()) + { + } + /// + UndoElement(CursorData const & cb, BufferParams const & bp, + bool lc, size_t gid) : + kind(ATOMIC_UNDO), cur_before(cb), cell(), from(0), end(0), + pars(0), array(0), bparams(new BufferParams(bp)), + lyx_clean(lc), group_id(gid), time(current_time()) { - if (isFullBuffer) - bparams = new BufferParams(bp); } /// - UndoElement(UndoElement const & ue) + UndoElement(UndoElement const & ue) : time(current_time()) { kind = ue.kind; cur_before = ue.cur_before; @@ -89,16 +95,15 @@ struct UndoElement end = ue.end; pars = ue.pars; array = ue.array; - bparams = ue.isFullBuffer - ? new BufferParams(*ue.bparams) : ue.bparams; - isFullBuffer = ue.isFullBuffer; + bparams = ue.bparams + ? new BufferParams(*ue.bparams) : 0; lyx_clean = ue.lyx_clean; group_id = ue.group_id; } /// ~UndoElement() { - if (isFullBuffer) + if (bparams) delete bparams; } /// Which kind of operation are we recording for? @@ -117,14 +122,14 @@ struct UndoElement ParagraphList * pars; /// the contents of the saved MathData (for mathed) MathData * array; - /// Only used in case of full backups + /// Only used in case of params undo 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; + /// timestamp + time_t time; private: /// Protect construction UndoElement(); @@ -204,15 +209,17 @@ struct Undo::Private pit_type first_pit, pit_type last_pit, CursorData const & cur, - bool isFullBuffer, UndoElementStack & stack); /// void recordUndo(UndoKind kind, DocIterator const & cell, pit_type first_pit, pit_type last_pit, - CursorData const & cur, - bool isFullBuffer); + CursorData const & cur); + /// + void doRecordUndoBufferParams(CursorData const & cur, UndoElementStack & stack); + /// + void recordUndoBufferParams(CursorData const & cur); /// Buffer & buffer_; @@ -299,7 +306,6 @@ void Undo::Private::doRecordUndo(UndoKind kind, DocIterator const & cell, pit_type first_pit, pit_type last_pit, CursorData const & cur_before, - bool isFullBuffer, UndoElementStack & stack) { if (!group_level) { @@ -318,22 +324,24 @@ void Undo::Private::doRecordUndo(UndoKind kind, if (!undo_finished_ && kind != ATOMIC_UNDO && !stack.empty() + && !stack.top().bparams && samePar(stack.top().cell, cell) && stack.top().kind == kind && stack.top().from == from - && stack.top().end == end) { + && stack.top().end == end + && stack.top().cur_after == cur_before + && current_time() - stack.top().time <= 2) { // reset cur_after; it will be filled correctly by endUndoGroup. stack.top().cur_after = CursorData(); + // update the timestamp of the undo element + stack.top().time = current_time(); 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); + LYXERR(Debug::UNDO, "Create undo element of group " << group_id); // create the position information of the Undo entry UndoElement undo(kind, cur_before, cell, from, end, 0, 0, - buffer_.params(), isFullBuffer, buffer_.isClean(), group_id); + buffer_.isClean(), group_id); // fill in the real data to be saved if (cell.inMathed()) { @@ -363,14 +371,45 @@ void Undo::Private::doRecordUndo(UndoKind kind, void Undo::Private::recordUndo(UndoKind kind, DocIterator const & cell, pit_type first_pit, pit_type last_pit, - CursorData const & cur, - bool isFullBuffer) + CursorData const & cur) { LASSERT(first_pit <= cell.lastpit(), return); LASSERT(last_pit <= cell.lastpit(), return); doRecordUndo(kind, cell, first_pit, last_pit, cur, - isFullBuffer, undostack_); + 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(); +} + + +void Undo::Private::doRecordUndoBufferParams(CursorData const & cur_before, + UndoElementStack & stack) +{ + if (!group_level) { + LYXERR0("There is no group open (creating one)"); + ++group_id; + } + + LYXERR(Debug::UNDO, "Create full buffer undo element of group " << group_id); + // create the position information of the Undo entry + UndoElement undo(cur_before, buffer_.params(), buffer_.isClean(), + group_id); + + // push the undo entry to undo stack + stack.push(undo); +} + + +void Undo::Private::recordUndoBufferParams(CursorData const & cur) +{ + doRecordUndoBufferParams(cur, undostack_); // next time we'll try again to combine entries if possible undo_finished_ = false; @@ -379,9 +418,6 @@ void Undo::Private::recordUndo(UndoKind kind, buffer_.markDirty(); redostack_.clear(); - //lyxerr << "undostack:\n"; - //for (size_t i = 0, n = buf.undostack().size(); i != n && i < 6; ++i) - // lyxerr << " " << i << ": " << buf.undostack()[i] << endl; } @@ -396,23 +432,22 @@ void Undo::Private::doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, // We will store in otherstack the part of the document under 'undo' DocIterator cell_dit = undo.cell.asDocIterator(&buffer_); - doRecordUndo(ATOMIC_UNDO, cell_dit, - undo.from, cell_dit.lastpit() - undo.end, undo.cur_after, - undo.isFullBuffer, otherstack); + if (undo.bparams) + doRecordUndoBufferParams(undo.cur_after, otherstack); + else + doRecordUndo(ATOMIC_UNDO, cell_dit, + undo.from, cell_dit.lastpit() - undo.end, undo.cur_after, + otherstack); otherstack.top().cur_after = undo.cur_before; // This does the actual undo/redo. //LYXERR0("undo, performing: " << undo); DocIterator dit = undo.cell.asDocIterator(&buffer_); - if (undo.isFullBuffer) { - LBUFERR(undo.pars); - // This is a full document + if (undo.bparams) { + // This is a params undo element delete otherstack.top().bparams; otherstack.top().bparams = new BufferParams(buffer_.params()); buffer_.params() = *undo.bparams; - swap(buffer_.paragraphs(), *undo.pars); - delete undo.pars; - undo.pars = 0; } 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 @@ -540,50 +575,32 @@ void Undo::endUndoGroup(CursorData const & 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(CursorData const & cur, UndoKind kind) { - d->recordUndo(kind, cur, cur.pit(), cur.pit(), cur, false); -} - - -void Undo::recordUndoInset(CursorData const & cur, UndoKind kind, - Inset const * inset) -{ - 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."); + d->recordUndo(kind, cur, cur.pit(), cur.pit(), cur); } -void Undo::recordUndo(CursorData const & cur, UndoKind kind, pit_type from) +void Undo::recordUndo(CursorData const & cur, pit_type from, pit_type to) { - d->recordUndo(kind, cur, cur.pit(), from, cur, false); + d->recordUndo(ATOMIC_UNDO, cur, from, to, cur); } -void Undo::recordUndo(CursorData const & cur, UndoKind kind, - pit_type from, pit_type to) +void Undo::recordUndoBufferParams(CursorData const & cur) { - d->recordUndo(kind, cur, from, to, cur, false); + d->recordUndoBufferParams(cur); } -void Undo::recordUndoFullDocument(CursorData const & cur) +void Undo::recordUndoFullBuffer(CursorData 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->recordUndo(ATOMIC_UNDO, doc_iterator_begin(&d->buffer_), - 0, d->buffer_.paragraphs().size() - 1, cur, true); + 0, d->buffer_.paragraphs().size() - 1, cur); + d->recordUndoBufferParams(cur); endUndoGroup(); }