X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FUndo.cpp;h=143af4e83ff0b9f29eac7ecc2f1abbf5e6c8ceb4;hb=28be7d552f62cc02fa86d7f79201d089bfb2d7b5;hp=b305edef7909bbe1ab761e2884d769bdd5e1ca7c;hpb=7021f4c3421afc74ca0c52c038743dad4a222aa9;p=lyx.git diff --git a/src/Undo.cpp b/src/Undo.cpp index b305edef79..143af4e83f 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -21,6 +21,8 @@ #include "BufferParams.h" #include "buffer_funcs.h" #include "Cursor.h" +#include "CutAndPaste.h" +#include "ErrorList.h" #include "Paragraph.h" #include "ParagraphList.h" #include "Text.h" @@ -29,10 +31,12 @@ #include "mathed/MathData.h" #include "insets/Inset.h" +#include "insets/InsetText.h" #include "support/debug.h" #include "support/gettext.h" #include "support/lassert.h" +#include "support/lyxtime.h" #include #include @@ -72,7 +76,7 @@ struct UndoElement 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) + lyx_clean(lc), group_id(gid), time(current_time()) { } /// @@ -80,11 +84,11 @@ struct UndoElement 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) + lyx_clean(lc), group_id(gid), time(current_time()) { } /// - UndoElement(UndoElement const & ue) + UndoElement(UndoElement const & ue) : time(current_time()) { kind = ue.kind; cur_before = ue.cur_before; @@ -121,12 +125,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; /// 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(); @@ -192,7 +198,7 @@ private: struct Undo::Private { Private(Buffer & buffer) : buffer_(buffer), undo_finished_(true), - group_id(0), group_level(0) {} + group_id_(0), group_level_(0) {} // Do one undo/redo step void doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, @@ -229,9 +235,11 @@ struct Undo::Private bool undo_finished_; /// Current group Id. - size_t group_id; + size_t group_id_; /// Current group nesting nevel. - size_t group_level; + size_t group_level_; + /// the position of cursor before the group was created + CursorData group_cur_before_; }; @@ -260,8 +268,8 @@ void Undo::clear() d->undo_finished_ = true; // We used to do that, but I believe it is better to keep // groups (only used in Buffer::reload for now (JMarc) - //d->group_id = 0; - //d->group_level = 0; + //d->group_id_ = 0; + //d->group_level_ = 0; } @@ -305,9 +313,9 @@ void Undo::Private::doRecordUndo(UndoKind kind, CursorData const & cur_before, UndoElementStack & stack) { - if (!group_level) { + if (!group_level_) { LYXERR0("There is no group open (creating one)"); - ++group_id; + ++group_id_; } if (first_pit > last_pit) @@ -321,19 +329,25 @@ 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; } - 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_.isClean(), group_id); + UndoElement undo(kind, + group_cur_before_.empty() ? cur_before : group_cur_before_, + cell, from, end, 0, 0, buffer_.isClean(), group_id_); // fill in the real data to be saved if (cell.inMathed()) { @@ -382,17 +396,18 @@ void Undo::Private::recordUndo(UndoKind kind, void Undo::Private::doRecordUndoBufferParams(CursorData const & cur_before, - UndoElementStack & stack) + UndoElementStack & stack) { - if (!group_level) { + if (!group_level_) { LYXERR0("There is no group open (creating one)"); - ++group_id; + ++group_id_; } - LYXERR(Debug::UNDO, "Create full buffer undo element of group " << 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); + UndoElement undo(group_cur_before_.empty() ? cur_before : group_cur_before_, + buffer_.params(), buffer_.isClean(), + group_id_); // push the undo entry to undo stack stack.push(undo); @@ -426,10 +441,12 @@ void Undo::Private::doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, if (undo.bparams) doRecordUndoBufferParams(undo.cur_after, otherstack); - else + else { + LATTEST(undo.end <= cell_dit.lastpit()); 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. @@ -439,7 +456,13 @@ void Undo::Private::doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, // This is a params undo element delete otherstack.top().bparams; otherstack.top().bparams = new BufferParams(buffer_.params()); + DocumentClassConstPtr olddc = buffer_.params().documentClassPtr(); buffer_.params() = *undo.bparams; + // The error list is not supposed to be helpful here. + ErrorList el; + cap::switchBetweenClasses(olddc, buffer_.params().documentClassPtr(), + static_cast(buffer_.inset()), el); + LATTEST(el.empty()); } 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 @@ -536,74 +559,71 @@ bool Undo::textRedo(CursorData & cur) void Undo::beginUndoGroup() { - if (d->group_level == 0) { + if (d->group_level_ == 0) { // create a new group - ++d->group_id; - LYXERR(Debug::UNDO, "+++++++Creating new group " << d->group_id); + ++d->group_id_; + LYXERR(Debug::UNDO, "+++++++Creating new group " << d->group_id_); } - ++d->group_level; + ++d->group_level_; +} + + +void Undo::beginUndoGroup(CursorData const & cur_before) +{ + beginUndoGroup(); + if (d->group_cur_before_.empty()) + d->group_cur_before_ = cur_before; } void Undo::endUndoGroup() { - if (d->group_level == 0) { + if (d->group_level_ == 0) { LYXERR0("There is no undo group to end here"); return; } - --d->group_level; - if (d->group_level == 0) { + --d->group_level_; + if (d->group_level_ == 0) { // real end of the group - LYXERR(Debug::UNDO, "-------End of group " << d->group_id); + d->group_cur_before_ = CursorData(); + LYXERR(Debug::UNDO, "-------End of group " << d->group_id_); } } -void Undo::endUndoGroup(CursorData const & cur) +void Undo::endUndoGroup(CursorData const & cur_after) { endUndoGroup(); if (!d->undostack_.empty() && d->undostack_.top().cur_after.empty()) - d->undostack_.top().cur_after = cur; + d->undostack_.top().cur_after = cur_after; } -// 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); } -void Undo::recordUndoInset(CursorData const & cur, UndoKind kind, - Inset const * inset) +void Undo::recordUndo(CursorData const & cur, pit_type from, pit_type to) +{ + d->recordUndo(ATOMIC_UNDO, cur, from, to, cur); +} + + +void Undo::recordUndoInset(CursorData const & cur, Inset const * inset) { if (!inset || inset == &cur.inset()) { DocIterator c = cur; c.pop_back(); - d->recordUndo(kind, c, c.pit(), c.pit(), cur); + d->recordUndo(ATOMIC_UNDO, c, c.pit(), c.pit(), cur); } else if (inset == cur.nextInset()) - recordUndo(cur, kind); + recordUndo(cur); else LYXERR0("Inset not found, no undo stack added."); } -void Undo::recordUndo(CursorData const & cur, UndoKind kind, pit_type from) -{ - d->recordUndo(kind, cur, cur.pit(), from, cur); -} - - -void Undo::recordUndo(CursorData const & cur, UndoKind kind, - pit_type from, pit_type to) -{ - d->recordUndo(kind, cur, from, to, cur); -} - - void Undo::recordUndoBufferParams(CursorData const & cur) { d->recordUndoBufferParams(cur); @@ -621,5 +641,18 @@ void Undo::recordUndoFullBuffer(CursorData const & cur) endUndoGroup(); } +/// UndoGroupHelper class stuff + +void UndoGroupHelper::resetBuffer(Buffer * buf) +{ + if (buf == buffer_) + return; + if (buffer_) + buffer_->undo().endUndoGroup(); + buffer_ = buf; + if (buffer_) + buffer_->undo().beginUndoGroup(); +} + } // namespace lyx