diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 1135b18ef0..e24d3e3857 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -165,9 +165,7 @@ class Buffer::Impl { public: Impl(Buffer & parent, FileName const & file, bool readonly); - - limited_stack undostack; - limited_stack redostack; + BufferParams params; LyXVC lyxvc; string temppath; @@ -219,6 +217,9 @@ public: /// frontend::WorkAreaManager * wa_; + + /// + Undo undo_; }; @@ -226,7 +227,7 @@ Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_) : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_), filename(file), file_fully_loaded(false), inset(params), toc_backend(&parent), embedded_files(&parent), timestamp_(0), - checksum_(0), wa_(0) + checksum_(0), wa_(0), undo_(parent) { inset.setAutoBreakRows(true); lyxvc.buffer(&parent); @@ -304,30 +305,6 @@ Inset & Buffer::inset() const } -limited_stack & Buffer::undostack() -{ - return pimpl_->undostack; -} - - -limited_stack const & Buffer::undostack() const -{ - return pimpl_->undostack; -} - - -limited_stack & Buffer::redostack() -{ - return pimpl_->redostack; -} - - -limited_stack const & Buffer::redostack() const -{ - return pimpl_->redostack; -} - - BufferParams & Buffer::params() { return pimpl_->params; @@ -405,6 +382,12 @@ EmbeddedFiles const & Buffer::embeddedFiles() const return pimpl_->embedded_files; } +Undo & Buffer::undo() +{ + return pimpl_->undo_; +} + + string const Buffer::getLatexName(bool const no_path) const { diff --git a/src/Buffer.h b/src/Buffer.h index 37a2670265..7f3ccd14eb 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -29,6 +29,9 @@ namespace lyx { class BufferParams; +// FIXME: Remove! +class BufferView; +class Cursor; class EmbeddedFiles; class ErrorItem; class ErrorList; @@ -301,14 +304,6 @@ public: /// bool isMultiLingual() const; - /// Does this mean that this is buffer local? - limited_stack & undostack(); - limited_stack const & undostack() const; - - /// Does this mean that this is buffer local? - limited_stack & redostack(); - limited_stack const & redostack() const; - /// BufferParams & params(); BufferParams const & params() const; @@ -390,6 +385,8 @@ public: EmbeddedFiles & embeddedFiles(); EmbeddedFiles const & embeddedFiles() const; //@} + + Undo & undo(); /// This function is called when the buffer is changed. void changed() const; diff --git a/src/BufferView.cpp b/src/BufferView.cpp index ca7e4bc7a7..320477bdf4 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -50,7 +50,6 @@ #include "TextClass.h" #include "TextMetrics.h" #include "TexRow.h" -#include "Undo.h" #include "VSpace.h" #include "WordLangTuple.h" @@ -273,7 +272,7 @@ void outline(OutlineOp mode, Cursor & cur) pit_type const newpit = std::distance(bgn, dest); pit_type const len = std::distance(start, finish); pit_type const deletepit = pit + len; - recordUndo(cur, Undo::ATOMIC, newpit, deletepit - 1); + buf.undo().recordUndo(cur, ATOMIC_UNDO, newpit, deletepit - 1); pars.insert(dest, start, finish); start = boost::next(pars.begin(), deletepit); pit = newpit; @@ -305,7 +304,7 @@ void outline(OutlineOp mode, Cursor & cur) // One such was found: pit_type newpit = std::distance(bgn, dest); pit_type const len = std::distance(start, finish); - recordUndo(cur, Undo::ATOMIC, pit, newpit - 1); + buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, newpit - 1); pars.insert(dest, start, finish); start = boost::next(bgn, pit); pit = newpit - len; @@ -313,7 +312,7 @@ void outline(OutlineOp mode, Cursor & cur) break; } case OutlineIn: - recordUndo(cur); + buf.undo().recordUndo(cur); for (; lit != lend; ++lit) { if ((*lit)->toclevel == thistoclevel + 1 && start->layout()->labeltype == (*lit)->labeltype) { @@ -323,7 +322,7 @@ void outline(OutlineOp mode, Cursor & cur) } break; case OutlineOut: - recordUndo(cur); + buf.undo().recordUndo(cur); for (; lit != lend; ++lit) { if ((*lit)->toclevel == thistoclevel - 1 && start->layout()->labeltype == (*lit)->labeltype) { @@ -853,10 +852,10 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd) switch (cmd.action) { case LFUN_UNDO: - flag.enabled(!buffer_.undostack().empty()); + flag.enabled(!buffer_.undo().hasUndoStack()); break; case LFUN_REDO: - flag.enabled(!buffer_.redostack().empty()); + flag.enabled(!buffer_.undo().hasRedoStack()); break; case LFUN_FILE_INSERT: case LFUN_FILE_INSERT_PLAINTEXT_PARA: @@ -1018,7 +1017,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) case LFUN_UNDO: cur.message(_("Undo")); cur.clearSelection(); - if (!textUndo(*this)) { + if (!cur.textUndo()) { cur.message(_("No further undo information")); updateFlags = Update::None; } @@ -1027,7 +1026,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) case LFUN_REDO: cur.message(_("Redo")); cur.clearSelection(); - if (!textRedo(*this)) { + if (!cur.textRedo()) { cur.message(_("No further redo information")); updateFlags = Update::None; } @@ -1346,7 +1345,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) cur.reset(buffer_.inset()); d->text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_); //FIXME: what to do with cur.x_target()? - finishUndo(); + cur.finishUndo(); // The metrics are already up to date. see scroll() updateFlags = Update::None; break; @@ -1361,7 +1360,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) // FIXME: We need to verify if the cursor stayed within an inset... //cur.reset(buffer_.inset()); d->text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_); - finishUndo(); + cur.finishUndo(); while (cur.depth() > initial_depth) { cur.forwardInset(); } @@ -1748,7 +1747,7 @@ bool BufferView::mouseSetCursor(Cursor & cur, bool select) else d->cursor_.clearSelection(); - finishUndo(); + d->cursor_.finishUndo(); return update; } @@ -1973,7 +1972,7 @@ void BufferView::menuInsertLyXFile(string const & filenm) ErrorList & el = buffer_.errorList("Parse"); // Copy the inserted document error list into the current buffer one. el = buf.errorList("Parse"); - recordUndo(d->cursor_); + buffer_.undo().recordUndo(d->cursor_); cap::pasteParagraphList(d->cursor_, buf.paragraphs(), buf.params().getTextClassPtr(), el); res = _("Document %1$s inserted."); @@ -2261,12 +2260,11 @@ void BufferView::insertPlaintextFile(string const & f, bool asParagraph) Cursor & cur = cursor(); cap::replaceSelection(cur); - recordUndo(cur); + buffer_.undo().recordUndo(cur); if (asParagraph) cur.innerText()->insertStringAsParagraphs(cur, tmpstr); else cur.innerText()->insertStringAsLines(cur, tmpstr); } - } // namespace lyx diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 4e4770a4ca..5eea06c7bb 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -1552,4 +1552,78 @@ void Cursor::setCurrentFont() } } + +bool Cursor::textUndo() +{ + DocIterator dit = *this; + // Undo::textUndo() will modify dit. + if (!bv_->buffer().undo().textUndo(dit)) + return false; + // Set cursor + setCursor(dit); + selection() = false; + resetAnchor(); + fixIfBroken(); + return true; +} + + +bool Cursor::textRedo() +{ + DocIterator dit = *this; + // Undo::textRedo() will modify dit. + if (!bv_->buffer().undo().textRedo(dit)) + return false; + // Set cursor + setCursor(dit); + selection() = false; + resetAnchor(); + fixIfBroken(); + return true; +} + + +void Cursor::finishUndo() +{ + bv_->buffer().undo().finishUndo(); +} + + +void Cursor::recordUndo(UndoKind kind, pit_type from, pit_type to) +{ + bv_->buffer().undo().recordUndo(*this, kind, from, to); +} + + +void Cursor::recordUndo(UndoKind kind, pit_type from) +{ + bv_->buffer().undo().recordUndo(*this, kind, from); +} + + +void Cursor::recordUndo(UndoKind kind) +{ + bv_->buffer().undo().recordUndo(*this, kind); +} + + +void Cursor::recordUndoInset(UndoKind kind) +{ + bv_->buffer().undo().recordUndoInset(*this, kind); +} + + +void Cursor::recordUndoFullDocument() +{ + bv_->buffer().undo().recordUndoFullDocument(*this); +} + + +void Cursor::recordUndoSelection() +{ + bv_->buffer().undo().recordUndo(*this, ATOMIC_UNDO, + selBegin().pit(), selEnd().pit()); +} + + } // namespace lyx diff --git a/src/Cursor.h b/src/Cursor.h index 27f2174d3c..750b801fc7 100644 --- a/src/Cursor.h +++ b/src/Cursor.h @@ -15,6 +15,7 @@ #include "DispatchResult.h" #include "DocIterator.h" #include "Font.h" +#include "Undo.h" #include #include @@ -189,6 +190,33 @@ public: /// output friend std::ostream & operator<<(std::ostream & os, Cursor const & cur); + /// + bool textUndo(); + /// + bool textRedo(); + + /// makes sure the next operation will be stored + void finishUndo(); + + /// The general case: prepare undo for an arbitrary range. + void recordUndo(UndoKind kind, pit_type from, pit_type to); + + /// Convenience: prepare undo for the range between 'from' and cursor. + void recordUndo(UndoKind kind, pit_type from); + + /// Convenience: prepare undo for the single paragraph or cell + /// containing the cursor + void recordUndo(UndoKind kind = ATOMIC_UNDO); + + /// Convenience: prepare undo for the inset containing the cursor + void recordUndoInset(UndoKind kind = ATOMIC_UNDO); + + /// Convenience: prepare undo for the whole buffer + void recordUndoFullDocument(); + + /// Convenience: prepare undo for the selected paragraphs + void recordUndoSelection(); + public: /// BufferView * bv_; diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index 5136df37df..63fa7ccdae 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -518,7 +518,7 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut) saveSelection(cur); // make sure that the depth behind the selection are restored, too - recordUndoSelection(cur); + cur.recordUndoSelection(); pit_type begpit = cur.selBegin().pit(); pit_type endpit = cur.selEnd().pit(); @@ -566,11 +566,11 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut) if (cur.selBegin().idx() != cur.selEnd().idx()) { // The current selection spans more than one cell. // Record all cells - recordUndoInset(cur); + cur.recordUndoInset(); } else { // Record only the current cell to avoid a jumping // cursor after undo - recordUndo(cur); + cur.recordUndo(); } if (realcut) copySelection(cur); @@ -733,7 +733,7 @@ void pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index) if (!checkPastePossible(sel_index)) return; - recordUndo(cur); + cur.recordUndo(); pasteParagraphList(cur, theCuts[sel_index].first, theCuts[sel_index].second, errorList); cur.setSelection(); @@ -757,7 +757,7 @@ void pasteClipboard(Cursor & cur, ErrorList & errorList, bool asParagraphs) Buffer buffer("", false); buffer.setUnnamed(true); if (buffer.readString(lyx)) { - recordUndo(cur); + cur.recordUndo(); pasteParagraphList(cur, buffer.paragraphs(), buffer.params().getTextClassPtr(), errorList); cur.setSelection(); @@ -770,7 +770,7 @@ void pasteClipboard(Cursor & cur, ErrorList & errorList, bool asParagraphs) docstring const text = theClipboard().getAsText(); if (text.empty()) return; - recordUndo(cur); + cur.recordUndo(); if (asParagraphs) cur.text()->insertStringAsParagraphs(cur, text); else @@ -782,7 +782,7 @@ void pasteSelection(Cursor & cur, ErrorList & errorList) { if (selectionBuffer.empty()) return; - recordUndo(cur); + cur.recordUndo(); pasteParagraphList(cur, selectionBuffer[0].first, selectionBuffer[0].second, errorList); } @@ -790,7 +790,7 @@ void pasteSelection(Cursor & cur, ErrorList & errorList) void replaceSelectionWithString(Cursor & cur, docstring const & str, bool backwards) { - recordUndo(cur); + cur.recordUndo(); DocIterator selbeg = cur.selectionBegin(); // Get font setting before we cut diff --git a/src/LyXFunc.cpp b/src/LyXFunc.cpp index e0d370ed48..b4d2bc3a3f 100644 --- a/src/LyXFunc.cpp +++ b/src/LyXFunc.cpp @@ -59,7 +59,6 @@ #include "Session.h" #include "TextClassList.h" #include "ToolbarBackend.h" -#include "Undo.h" #include "insets/InsetBox.h" #include "insets/InsetBranch.h" @@ -1798,7 +1797,9 @@ void LyXFunc::dispatch(FuncRequest const & cmd) Buffer * buffer = lyx_view_->buffer(); TextClassPtr oldClass = buffer->params().getTextClassPtr(); - recordUndoFullDocument(view()); + + Cursor & cur = view()->cursor(); + cur.recordUndoFullDocument(); istringstream ss(argument); Lexer lex(0,0); @@ -1818,7 +1819,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd) lyx_view_->buffer()->params().getEngine(); if (oldEngine != newEngine) { - Cursor & cur = view()->cursor(); FuncRequest fr(LFUN_INSET_REFRESH); Inset & inset = lyx_view_->buffer()->inset(); @@ -1837,7 +1837,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd) BOOST_ASSERT(lyx_view_); Buffer * buffer = lyx_view_->buffer(); TextClassPtr oldClass = buffer->params().getTextClassPtr(); - recordUndoFullDocument(view()); + view()->cursor().recordUndoFullDocument(); buffer->params().clearLayoutModules(); updateLayout(oldClass, buffer); updateFlags = Update::Force | Update::FitCursor; @@ -1848,7 +1848,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd) BOOST_ASSERT(lyx_view_); Buffer * buffer = lyx_view_->buffer(); TextClassPtr oldClass = buffer->params().getTextClassPtr(); - recordUndoFullDocument(view()); + view()->cursor().recordUndoFullDocument(); buffer->params().addLayoutModule(argument); updateLayout(oldClass, buffer); updateFlags = Update::Force | Update::FitCursor; @@ -1876,7 +1876,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd) //Save the old, possibly modular, layout for use in conversion. TextClassPtr oldClass = buffer->params().getTextClassPtr(); - recordUndoFullDocument(view()); + view()->cursor().recordUndoFullDocument(); buffer->params().setBaseClass(new_class); updateLayout(oldClass, buffer); updateFlags = Update::Force | Update::FitCursor; diff --git a/src/Text.cpp b/src/Text.cpp index c6c1d1dc87..917d797091 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -44,7 +44,6 @@ #include "Paragraph.h" #include "paragraph_funcs.h" #include "ParagraphParameters.h" -#include "Undo.h" #include "TextMetrics.h" #include "VSpace.h" #include "WordLangTuple.h" @@ -438,7 +437,7 @@ void Text::insertChar(Cursor & cur, char_type c) BOOST_ASSERT(this == cur.text()); BOOST_ASSERT(c != Paragraph::META_INSET); - recordUndo(cur, Undo::INSERT); + cur.recordUndo(INSERT_UNDO); TextMetrics const & tm = cur.bv().textMetrics(this); Buffer const & buffer = cur.buffer(); @@ -566,11 +565,11 @@ void Text::insertChar(Cursor & cur, char_type c) // cur.updateFlags(Update::Force); setCursor(cur.top(), cur.pit(), cur.pos() + 1); - charInserted(); + charInserted(cur); } -void Text::charInserted() +void Text::charInserted(Cursor & cur) { // Here we call finishUndo for every 20 characters inserted. // This is from my experience how emacs does it. (Lgb) @@ -578,7 +577,7 @@ void Text::charInserted() if (counter < 20) { ++counter; } else { - finishUndo(); + cur.finishUndo(); counter = 0; } } @@ -664,7 +663,7 @@ void Text::acceptOrRejectChanges(Cursor & cur, ChangeOp op) if (!cur.selection()) return; - recordUndoSelection(cur, Undo::ATOMIC); + cur.recordUndoSelection(); pit_type begPit = cur.selectionBegin().pit(); pit_type endPit = cur.selectionEnd().pit(); @@ -753,7 +752,7 @@ void Text::acceptOrRejectChanges(Cursor & cur, ChangeOp op) // - finishUndo(); + cur.finishUndo(); cur.clearSelection(); setCursorIntern(cur, begPit, begPos); cur.updateFlags(Update::Force); @@ -851,7 +850,7 @@ void Text::changeCase(Cursor & cur, Text::TextCase action) cursorRightOneWord(cur); } - recordUndoSelection(cur, Undo::ATOMIC); + cur.recordUndoSelection(); pit_type begPit = from.pit(); pit_type endPit = to.pit(); @@ -953,7 +952,7 @@ bool Text::handleBibitems(Cursor & cur) } Paragraph const & prevpar = prevcur.paragraph(); if (cur.pit() > 0 && par.layout() == prevpar.layout()) { - recordUndo(cur, Undo::ATOMIC, prevcur.pit()); + cur.recordUndo(ATOMIC_UNDO, prevcur.pit()); mergeParagraph(bufparams, cur.text()->paragraphs(), prevcur.pit()); updateLabels(cur.buffer()); @@ -978,7 +977,7 @@ bool Text::erase(Cursor & cur) if (cur.pos() != cur.lastpos()) { // this is the code for a normal delete, not pasting // any paragraphs - recordUndo(cur, Undo::DELETE); + cur.recordUndo(DELETE_UNDO); if(!par.eraseChar(cur.pos(), cur.buffer().params().trackChanges)) { // the character has been logically deleted only => skip it cur.top().forwardPos(); @@ -1032,14 +1031,14 @@ bool Text::backspacePos0(Cursor & cur) // is it an empty paragraph? if (cur.lastpos() == 0 || (cur.lastpos() == 1 && par.isSeparator(0))) { - recordUndo(cur, Undo::ATOMIC, prevcur.pit(), cur.pit()); + cur.recordUndo(ATOMIC_UNDO, prevcur.pit(), cur.pit()); plist.erase(boost::next(plist.begin(), cur.pit())); needsUpdate = true; } // is previous par empty? else if (prevcur.lastpos() == 0 || (prevcur.lastpos() == 1 && prevpar.isSeparator(0))) { - recordUndo(cur, Undo::ATOMIC, prevcur.pit(), cur.pit()); + cur.recordUndo(ATOMIC_UNDO, prevcur.pit(), cur.pit()); plist.erase(boost::next(plist.begin(), prevcur.pit())); needsUpdate = true; } @@ -1049,7 +1048,7 @@ bool Text::backspacePos0(Cursor & cur) // Correction: Pasting is always allowed with standard-layout else if (par.layout() == prevpar.layout() || par.layout() == tclass.defaultLayout()) { - recordUndo(cur, Undo::ATOMIC, prevcur.pit()); + cur.recordUndo(ATOMIC_UNDO, prevcur.pit()); mergeParagraph(bufparams, plist, prevcur.pit()); needsUpdate = true; } @@ -1085,7 +1084,7 @@ bool Text::backspace(Cursor & cur) } else { // this is the code for a normal backspace, not pasting // any paragraphs - recordUndo(cur, Undo::DELETE); + cur.recordUndo(DELETE_UNDO); // We used to do cursorLeftIntern() here, but it is // not a good idea since it triggers the auto-delete // mechanism. So we do a cursorLeftIntern()-lite, @@ -1115,7 +1114,7 @@ bool Text::dissolveInset(Cursor & cur) { if (isMainText(cur.bv().buffer()) || cur.inset().nargs() != 1) return false; - recordUndoInset(cur); + cur.recordUndoInset(); cur.selHandle(false); // save position pos_type spos = cur.pos(); @@ -1456,7 +1455,7 @@ void Text::charsTranspose(Cursor & cur) // Track the changes if Change Tracking is enabled. bool const trackChanges = cur.buffer().params().trackChanges; - recordUndo(cur); + cur.recordUndo(); par.eraseChar(pos2, trackChanges); par.eraseChar(pos1, trackChanges); diff --git a/src/Text.h b/src/Text.h index b542c36a15..d26bd2a893 100644 --- a/src/Text.h +++ b/src/Text.h @@ -287,7 +287,7 @@ private: /// handle the case where bibitems were deleted bool handleBibitems(Cursor & cur); /// - void charInserted(); + void charInserted(Cursor & cur); /// set 'number' font property void number(Cursor & cur); diff --git a/src/Text2.cpp b/src/Text2.cpp index bd7effb23f..2472cda888 100644 --- a/src/Text2.cpp +++ b/src/Text2.cpp @@ -48,7 +48,6 @@ #include "Server.h" #include "ServerSocket.h" #include "TextMetrics.h" -#include "Undo.h" #include "VSpace.h" #include "frontends/FontMetrics.h" @@ -292,7 +291,7 @@ void Text::changeDepth(Cursor & cur, DEPTH_CHANGE type) BOOST_ASSERT(this == cur.text()); pit_type const beg = cur.selBegin().pit(); pit_type const end = cur.selEnd().pit() + 1; - recordUndoSelection(cur); + cur.recordUndoSelection(); int max_depth = (beg != 0 ? pars_[beg - 1].getMaxDepthAfter() : 0); for (pit_type pit = beg; pit != end; ++pit) { @@ -340,7 +339,7 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall) return; // Ok, we have a selection. - recordUndoSelection(cur); + cur.recordUndoSelection(); setFont(cur.bv(), cur.selectionBegin().top(), cur.selectionEnd().top(), font, toggleall); @@ -812,7 +811,7 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur, if (oldpar.empty() || (oldpar.size() == 1 && oldpar.isLineSeparator(0))) { // Delete old par. - recordUndo(old, Undo::ATOMIC, + old.recordUndo(ATOMIC_UNDO, max(old.pit() - 1, pit_type(0)), min(old.pit() + 1, old.lastpit())); ParagraphList & plist = old.text()->paragraphs(); @@ -893,13 +892,13 @@ void Text::deleteEmptyParagraphMechanism(pit_type first, pit_type last, bool tra void Text::recUndo(Cursor & cur, pit_type first, pit_type last) const { - recordUndo(cur, Undo::ATOMIC, first, last); + cur.recordUndo(ATOMIC_UNDO, first, last); } void Text::recUndo(Cursor & cur, pit_type par) const { - recordUndo(cur, Undo::ATOMIC, par, par); + cur.recordUndo(ATOMIC_UNDO, par, par); } } // namespace lyx diff --git a/src/Text3.cpp b/src/Text3.cpp index c95b90787c..726b65b8a9 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -44,7 +44,6 @@ #include "paragraph_funcs.h" #include "ParagraphParameters.h" #include "TextMetrics.h" -#include "Undo.h" #include "VSpace.h" #include "ParIterator.h" @@ -118,14 +117,14 @@ static void moveCursor(Cursor & cur, bool selecting) static void finishChange(Cursor & cur, bool selecting) { - finishUndo(); + cur.finishUndo(); moveCursor(cur, selecting); } static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) { - recordUndo(cur); + cur.recordUndo(); docstring sel = cur.selectionAsString(false); // It may happen that sel is empty but there is a selection @@ -176,7 +175,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) static void specialChar(Cursor & cur, InsetSpecialChar::Kind kind) { - recordUndo(cur); + cur.recordUndo(); cap::replaceSelection(cur); cur.insert(new InsetSpecialChar(kind)); cur.posRight(); @@ -190,7 +189,7 @@ static bool doInsertInset(Cursor & cur, Text * text, if (!inset) return false; - recordUndo(cur); + cur.recordUndo(); if (cmd.action == LFUN_INDEX_INSERT) { docstring ds = support::subst(text->getStringToIndex(cur), '\n', ' '); text->insertInset(cur, inset); @@ -290,7 +289,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_PARAGRAPH_MOVE_DOWN: { pit_type const pit = cur.pit(); recUndo(cur, pit, pit + 1); - finishUndo(); + cur.finishUndo(); std::swap(pars_[pit], pars_[pit + 1]); updateLabels(cur.buffer()); needsUpdate = true; @@ -301,7 +300,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_PARAGRAPH_MOVE_UP: { pit_type const pit = cur.pit(); recUndo(cur, pit - 1, pit); - finishUndo(); + cur.finishUndo(); std::swap(pars_[pit], pars_[pit - 1]); updateLabels(cur.buffer()); --cur.pit(); @@ -325,7 +324,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } } - recordUndo(cur); + cur.recordUndo(); par.params().startOfAppendix(start); // we can set the refreshing parameters now @@ -508,7 +507,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // this avoids a double undo // FIXME: should not be needed, ideally if (!cur.selection()) - recordUndo(cur); + cur.recordUndo(); cap::replaceSelection(cur); cur.insert(new InsetNewline); cur.posRight(); @@ -639,7 +638,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_INSET_INSERT: { - recordUndo(cur); + cur.recordUndo(); Inset * inset = createInset(bv, cmd); if (inset) { // FIXME (Abdel 01/02/2006): @@ -740,7 +739,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } bv->buffer().errors("Paste"); cur.clearSelection(); // bug 393 - finishUndo(); + cur.finishUndo(); break; case LFUN_CUT: @@ -870,7 +869,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // this avoids a double undo // FIXME: should not be needed, ideally if (!cur.selection()) - recordUndo(cur); + cur.recordUndo(); cap::replaceSelection(cur); pos = cur.pos(); char_type c; @@ -947,7 +946,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bv->buffer().errorList("Paste")); bv->buffer().errors("Paste"); bv->buffer().markDirty(); - finishUndo(); + bv->cursor().finishUndo(); } else { lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph")); } @@ -1200,7 +1199,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) Inset * inset = createInset(&cur.bv(), cmd); if (!inset) break; - recordUndo(cur); + cur.recordUndo(); cur.clearSelection(); insertInset(cur, inset); // Show the dialog for the nomenclature entry, since the @@ -1437,7 +1436,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FLOAT_LIST: { TextClass const & tclass = bv->buffer().params().getTextClass(); if (tclass.floats().typeExist(to_utf8(cmd.argument()))) { - recordUndo(cur); + cur.recordUndo(); if (cur.selection()) cutSelection(cur, true, false); breakParagraph(cur); @@ -1958,7 +1957,7 @@ void Text::pasteString(Cursor & cur, docstring const & clip, { cur.clearSelection(); if (!clip.empty()) { - recordUndo(cur); + cur.recordUndo(); if (asParagraphs) insertStringAsParagraphs(cur, clip); else diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 859f43a41d..3dd79c234f 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -38,7 +38,6 @@ #include "ParIterator.h" #include "rowpainter.h" #include "Text.h" -#include "Undo.h" #include "VSpace.h" #include "frontends/FontMetrics.h" @@ -1592,7 +1591,7 @@ void TextMetrics::cursorPrevious(Cursor & cur) // simplest solution is to move to the previous row instead. cur.dispatch(FuncRequest(cur.selection()? LFUN_UP_SELECT: LFUN_UP)); - finishUndo(); + cur.finishUndo(); cur.updateFlags(Update::Force | Update::FitCursor); } @@ -1612,7 +1611,7 @@ void TextMetrics::cursorNext(Cursor & cur) cur.dispatch( FuncRequest(cur.selection()? LFUN_DOWN_SELECT: LFUN_DOWN)); - finishUndo(); + cur.finishUndo(); cur.updateFlags(Update::Force | Update::FitCursor); } diff --git a/src/Undo.cpp b/src/Undo.cpp index 8b6af36301..9efd218918 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -8,6 +8,7 @@ * \author John Levon * \author André Pönitz * \author Jürgen Vigna + * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. */ @@ -17,13 +18,13 @@ #include "Undo.h" #include "Buffer.h" +#include "BufferParams.h" #include "buffer_funcs.h" -#include "Cursor.h" #include "debug.h" -#include "BufferView.h" -#include "Text.h" +#include "DocIterator.h" #include "Paragraph.h" #include "ParagraphList.h" +#include "Text.h" #include "mathed/MathSupport.h" #include "mathed/MathData.h" @@ -32,20 +33,117 @@ #include +using std::advance; +using std::endl; namespace lyx { -using std::advance; -using std::endl; + +/** +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 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. + +*/ +struct UndoElement +{ + /// Which kind of operation are we recording for? + UndoKind kind; + /// the position of the cursor + StableDocIterator cursor; + /// the position of the cell described + StableDocIterator cell; + /// counted from begin of cell + pit_type from; + /// complement to end of this cell + pit_type end; + /// the contents of the saved Paragraphs (for texted) + ParagraphList * pars; + /// the contents of the saved MathData (for mathed) + MathData * array; + /// Only used in case of full backups + BufferParams bparams; + /// Only used in case of full backups + bool isFullBuffer; +}; + + +struct Undo::Private +{ + Private(Buffer & buffer): buffer_(buffer) {} + + // Returns false if no undo possible. + bool textUndoOrRedo(DocIterator & cur, bool isUndoOperation); + /// + void doRecordUndo(UndoKind kind, + DocIterator const & cell, + pit_type first_pit, + pit_type last_pit, + DocIterator const & cur, + bool isFullBuffer, + bool isUndoOperation); + + /// + void recordUndo(UndoKind kind, + DocIterator & cur, + pit_type first_pit, + pit_type last_pit); + + /// + Buffer & buffer_; + /// Undo stack. + limited_stack undostack; + /// Redo stack. + limited_stack redostack; + + /// The flag used by Undo::finishUndo(). + bool undo_finished; +}; + + +Undo::Undo(Buffer & buffer): d(new Undo::Private(buffer)) +{ +} + + +Undo::~Undo() +{ + delete d; +} + + +bool Undo::hasUndoStack() const +{ + return !d->undostack.empty(); +} + + +bool Undo::hasRedoStack() const +{ + return !d->redostack.empty(); +} + + namespace { -/// The flag used by finishUndo(). -bool undo_finished; - - -std::ostream & operator<<(std::ostream & os, Undo const & undo) +std::ostream & operator<<(std::ostream & os, UndoElement const & undo) { return os << " from: " << undo.from << " end: " << undo.end << " cell:\n" << undo.cell @@ -60,25 +158,26 @@ bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) return i1 == tmpi2; } +} // namespace anon -void doRecordUndo(Undo::undo_kind kind, + +void Undo::Private::doRecordUndo(UndoKind kind, DocIterator const & cell, pit_type first_pit, pit_type last_pit, DocIterator const & cur, - BufferParams const & bparams, bool isFullBuffer, - limited_stack & stack) + bool isUndoOperation) { if (first_pit > last_pit) std::swap(first_pit, last_pit); // create the position information of the Undo entry - Undo undo; + UndoElement undo; undo.array = 0; undo.pars = 0; undo.kind = kind; undo.cell = cell; undo.cursor = cur; - undo.bparams = bparams ; + undo.bparams = buffer_.params(); undo.isFullBuffer = isFullBuffer; //lyxerr << "recordUndo: cur: " << cur << endl; //lyxerr << "recordUndo: pos: " << cur.pos() << endl; @@ -86,11 +185,14 @@ void doRecordUndo(Undo::undo_kind kind, undo.from = first_pit; undo.end = cell.lastpit() - last_pit; + limited_stack & stack = isUndoOperation ? + undostack : redostack; + // Undo::ATOMIC are always recorded (no overlapping there). // As nobody wants all removed character appear one by one when undoing, // we want combine 'similar' non-ATOMIC undo recordings to one. if (!undo_finished - && kind != Undo::ATOMIC + && kind != ATOMIC_UNDO && !stack.empty() && samePar(stack.top().cell, undo.cell) && stack.top().kind == undo.kind @@ -125,53 +227,58 @@ void doRecordUndo(Undo::undo_kind kind, } -void recordUndo(Undo::undo_kind kind, - Cursor & cur, pit_type first_pit, pit_type last_pit, - limited_stack & stack) +void Undo::Private::recordUndo(UndoKind kind, DocIterator & cur, + pit_type first_pit, pit_type last_pit) { 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); + false, true); + + undo_finished = false; + redostack.clear(); + //lyxerr << "undostack:\n"; + //for (size_t i = 0, n = buf.undostack().size(); i != n && i < 6; ++i) + // lyxerr << " " << i << ": " << buf.undostack()[i] << std::endl; } - -// Returns false if no undo possible. -bool textUndoOrRedo(BufferView & bv, - limited_stack & stack, limited_stack & otherstack) +bool Undo::Private::textUndoOrRedo(DocIterator & cur, bool isUndoOperation) { - finishUndo(); + undo_finished = true; - if (stack.empty()) { + limited_stack & stack = isUndoOperation ? + undostack : redostack; + + if (stack.empty()) // Nothing to do. return false; - } + + limited_stack & otherstack = isUndoOperation ? + redostack : undostack; // Adjust undo stack and get hold of current undo data. - Undo undo = stack.top(); + UndoElement 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()); + DocIterator cell_dit = undo.cell.asDocIterator(&buffer_.inset()); - doRecordUndo(Undo::ATOMIC, cell_dit, - undo.from, cell_dit.lastpit() - undo.end, bv.cursor(), - undo.bparams, undo.isFullBuffer, - otherstack); + doRecordUndo(ATOMIC_UNDO, cell_dit, + undo.from, cell_dit.lastpit() - undo.end, cur, + undo.isFullBuffer, !isUndoOperation); // This does the actual undo/redo. //lyxerr << "undo, performing: " << undo << std::endl; bool labelsUpdateNeeded = false; - DocIterator dit = undo.cell.asDocIterator(&buf.inset()); + DocIterator dit = undo.cell.asDocIterator(&buffer_.inset()); if (undo.isFullBuffer) { BOOST_ASSERT(undo.pars); // This is a full document - otherstack.top().bparams = buf.params(); - buf.params() = undo.bparams; - std::swap(buf.paragraphs(), *undo.pars); + otherstack.top().bparams = buffer_.params(); + buffer_.params() = undo.bparams; + std::swap(buffer_.paragraphs(), *undo.pars); delete undo.pars; undo.pars = 0; } else if (dit.inMathed()) { @@ -215,103 +322,71 @@ bool textUndoOrRedo(BufferView & bv, BOOST_ASSERT(undo.pars == 0); BOOST_ASSERT(undo.array == 0); - // Set cursor - Cursor & cur = bv.cursor(); - cur.setCursor(undo.cursor.asDocIterator(&buf.inset())); - cur.selection() = false; - cur.resetAnchor(); - cur.fixIfBroken(); + cur = undo.cursor.asDocIterator(&buffer_.inset()); if (labelsUpdateNeeded) - updateLabels(buf); - finishUndo(); + updateLabels(buffer_); + undo_finished = true; return true; } -} // namespace anon - -void finishUndo() +void Undo::finishUndo() { // Make sure the next operation will be stored. - undo_finished = true; + d->undo_finished = true; } -bool textUndo(BufferView & bv) +bool Undo::textUndo(DocIterator & cur) { - return textUndoOrRedo(bv, bv.buffer().undostack(), - bv.buffer().redostack()); + return d->textUndoOrRedo(cur, true); } -bool textRedo(BufferView & bv) +bool Undo::textRedo(DocIterator & cur) { - return textUndoOrRedo(bv, bv.buffer().redostack(), - bv.buffer().undostack()); + return d->textUndoOrRedo(cur, false); } -void recordUndo(Undo::undo_kind kind, - Cursor & cur, pit_type first, pit_type last) +void Undo::recordUndo(DocIterator & cur, UndoKind kind) { - Buffer & buf = cur.bv().buffer(); - recordUndo(kind, cur, first, last, buf.undostack()); - buf.redostack().clear(); - //lyxerr << "undostack:\n"; - //for (size_t i = 0, n = buf.undostack().size(); i != n && i < 6; ++i) - // lyxerr << " " << i << ": " << buf.undostack()[i] << std::endl; + d->recordUndo(kind, cur, cur.pit(), cur.pit()); } -void recordUndo(Cursor & cur, Undo::undo_kind kind) +void Undo::recordUndoInset(DocIterator & cur, UndoKind kind) { - recordUndo(kind, cur, cur.pit(), cur.pit()); + DocIterator c = cur; + c.pop_back(); + d->doRecordUndo(kind, c, c.pit(), c.pit(), cur, false, true); } -void recordUndoInset(Cursor & cur, Undo::undo_kind kind) +void Undo::recordUndo(DocIterator & cur, UndoKind kind, pit_type from) { - Cursor c = cur; - c.pop(); - Buffer & buf = cur.bv().buffer(); - doRecordUndo(kind, c, c.pit(), c.pit(), cur, - buf.params(), false, buf.undostack()); + d->recordUndo(kind, cur, cur.pit(), from); } -void recordUndoSelection(Cursor & cur, Undo::undo_kind kind) -{ - recordUndo(kind, cur, cur.selBegin().pit(), cur.selEnd().pit()); -} - - -void recordUndo(Cursor & cur, Undo::undo_kind kind, pit_type from) -{ - recordUndo(kind, cur, cur.pit(), from); -} - - -void recordUndo(Cursor & cur, Undo::undo_kind kind, +void Undo::recordUndo(DocIterator & cur, UndoKind kind, pit_type from, pit_type to) { - recordUndo(kind, cur, from, to); + d->recordUndo(kind, cur, from, to); } -void recordUndoFullDocument(BufferView * bv) +void Undo::recordUndoFullDocument(DocIterator & cur) { - Buffer & buf = bv->buffer(); - doRecordUndo( - Undo::ATOMIC, - doc_iterator_begin(buf.inset()), - 0, buf.paragraphs().size() - 1, - bv->cursor(), - buf.params(), + d->doRecordUndo( + ATOMIC_UNDO, + doc_iterator_begin(d->buffer_.inset()), + 0, d->buffer_.paragraphs().size() - 1, + cur, true, - buf.undostack() + true ); - undo_finished = false; } diff --git a/src/Undo.h b/src/Undo.h index 8bdc6af3c8..160f3ac40e 100644 --- a/src/Undo.h +++ b/src/Undo.h @@ -9,6 +9,7 @@ * \author John Levon * \author André Pönitz * \author Jürgen Vigna + * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. */ @@ -16,95 +17,33 @@ #ifndef UNDO_H #define UNDO_H -#include "DocIterator.h" -#include "BufferParams.h" - #include "support/types.h" -#include - - namespace lyx { +class Buffer; class BufferParams; -class BufferView; class DocIterator; -class Cursor; class MathData; class ParagraphList; - -/** -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 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. - -*/ - -class Undo { -public: - /// This is used to combine consecutive undo recordings of the same kind. - enum undo_kind { - /** - * Insert something - these will combine to one big chunk - * when many inserts come after each other. - */ - INSERT, - /** - * Delete something - these will combine to one big chunk - * when many deletes come after each other. - */ - DELETE, - /// Atomic - each of these will have its own entry in the stack - ATOMIC - }; - - /// Which kind of operation are we recording for? - undo_kind kind; - /// the position of the cursor - StableDocIterator cursor; - /// the position of the cell described - StableDocIterator cell; - /// counted from begin of cell - pit_type from; - /// complement to end of this cell - pit_type end; - /// the contents of the saved Paragraphs (for texted) - ParagraphList * pars; - /// the contents of the saved MathData (for mathed) - MathData * array; - /// Only used in case of full backups - BufferParams bparams; - /// Only used in case of full backups - bool isFullBuffer; +/// This is used to combine consecutive undo recordings of the same kind. +enum UndoKind { + /** + * Insert something - these will combine to one big chunk + * when many inserts come after each other. + */ + INSERT_UNDO, + /** + * Delete something - these will combine to one big chunk + * when many deletes come after each other. + */ + DELETE_UNDO, + /// Atomic - each of these will have its own entry in the stack + ATOMIC_UNDO }; -/// this will undo the last action - returns false if no undo possible -bool textUndo(BufferView & bv); - -/// this will redo the last undo - returns false if no redo possible -bool textRedo(BufferView & bv); - -/// makes sure the next operation will be stored -void finishUndo(); - - /** * Record undo information - call with the current cursor and the 'other * end' of the range of changed paragraphs. So we give an inclusive range. @@ -115,31 +54,54 @@ void finishUndo(); * Right now we use recordUndoInset if more than one cell is changed, * but that puts the cursor in front of the inset after undo. We would need * something like - * recordUndoGrid(Cursor & cur, Undo::undo_kind kind, idx_type from, idx_type to); + * recordUndoGrid(DocIterator & cur, UndoKind kind, idx_type from, idx_type to); * and store the cell information in class Undo. */ +class Undo +{ +public: -/// The general case: prepare undo for an arbitrary range. -/// FIXME: replace Cursor with DocIterator. This is not possible right -/// now because we need access to Buffer->params()!. -void recordUndo(Cursor & cur, Undo::undo_kind kind, - pit_type from, pit_type to); + Undo(Buffer &); -/// Convenience: prepare undo for the range between 'from' and cursor. -void recordUndo(Cursor & cur, Undo::undo_kind kind, pit_type from); + ~Undo(); -/// Convenience: prepare undo for the single paragraph or cell -/// containing the cursor -void recordUndo(Cursor & cur, Undo::undo_kind kind = Undo::ATOMIC); -/// Convenience: prepare undo for the inset containing the cursor -void recordUndoInset(Cursor & cur, Undo::undo_kind kind = Undo::ATOMIC); -/// Convenience: prepare undo for the selected paragraphs -void recordUndoSelection(Cursor & cur, Undo::undo_kind kind = Undo::ATOMIC); + /// this will undo the last action - returns false if no undo possible + bool textUndo(DocIterator &); + + /// this will redo the last undo - returns false if no redo possible + bool textRedo(DocIterator &); + + /// makes sure the next operation will be stored + void finishUndo(); + + /// + bool hasUndoStack() const; + /// + bool hasRedoStack() const; + + /// The general case: prepare undo for an arbitrary range. + void recordUndo(DocIterator & cur, UndoKind kind, + pit_type from, pit_type to); + + /// Convenience: prepare undo for the range between 'from' and cursor. + void recordUndo(DocIterator & cur, UndoKind kind, pit_type from); + + /// Convenience: prepare undo for the single paragraph or cell + /// containing the cursor + void recordUndo(DocIterator & cur, UndoKind kind = ATOMIC_UNDO); + /// Convenience: prepare undo for the inset containing the cursor + void recordUndoInset(DocIterator & cur, UndoKind kind = ATOMIC_UNDO); + + /// Convenience: prepare undo for the whole buffer + void recordUndoFullDocument(DocIterator & cur); + +private: + struct Private; + Private * const d; +}; -/// Convenience: prepare undo for the whole buffer -void recordUndoFullDocument(BufferView * bv); } // namespace lyx -#endif // UNDO_FUNCS_H +#endif // UNDO_H diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 7041004107..8a2fa91208 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -44,7 +44,6 @@ #include "ParagraphParameters.h" #include "ParIterator.h" #include "TextMetrics.h" -#include "Undo.h" #include "support/convert.h" #include "support/lstrings.h" @@ -3154,7 +3153,7 @@ docstring const InsetTabular::editMessage() const void InsetTabular::edit(Cursor & cur, bool left) { //lyxerr << "InsetTabular::edit: " << this << endl; - finishUndo(); + cur.finishUndo(); cur.selection() = false; cur.push(*this); if (left) { @@ -3384,7 +3383,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CUT: if (tablemode(cur)) { if (copySelection(cur)) { - recordUndoInset(cur, Undo::DELETE); + cur.recordUndoInset(DELETE_UNDO); cutSelection(cur); } } @@ -3395,7 +3394,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHAR_DELETE_BACKWARD: case LFUN_CHAR_DELETE_FORWARD: if (tablemode(cur)) { - recordUndoInset(cur, Undo::DELETE); + cur.recordUndoInset(DELETE_UNDO); cutSelection(cur); } else @@ -3406,7 +3405,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) if (!cur.selection()) break; if (tablemode(cur)) { - finishUndo(); + cur.finishUndo(); copySelection(cur); } else cell(cur.idx())->dispatch(cur, cmd); @@ -3437,7 +3436,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_PASTE: if (tabularStackDirty() && theClipboard().isInternal()) { - recordUndoInset(cur, Undo::INSERT); + cur.recordUndoInset(INSERT_UNDO); pasteClipboard(cur); break; } @@ -4127,7 +4126,7 @@ void InsetTabular::tabularFeatures(Cursor & cur, break; } - recordUndoInset(cur, Undo::ATOMIC); + cur.recordUndoInset(ATOMIC_UNDO); getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end); row_type const row = tabular.cellRow(cur.idx()); diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 3219e59dcf..91366ef852 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -44,7 +44,6 @@ #include "sgml.h" #include "TextMetrics.h" #include "TexRow.h" -#include "Undo.h" #include "frontends/alert.h" #include "frontends/Painter.h" @@ -217,7 +216,7 @@ void InsetText::edit(Cursor & cur, bool left) int const pos = left ? 0 : paragraphs().back().size(); text_.setCursor(cur.top(), pit, pos); cur.clearSelection(); - finishUndo(); + cur.finishUndo(); } diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index 81f9a6f1ad..4da5b14d56 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -16,6 +16,7 @@ #include "lyxfind.h" #include "Buffer.h" +#include "BufferParams.h" #include "Cursor.h" #include "CutAndPaste.h" #include "buffer_funcs.h" @@ -26,7 +27,6 @@ #include "Text.h" #include "Paragraph.h" #include "ParIterator.h" -#include "Undo.h" #include "frontends/alert.h" @@ -177,7 +177,7 @@ int replaceAll(BufferView * bv, if (!searchAllowed(bv, searchstr) || buf.isReadonly()) return 0; - recordUndoFullDocument(bv); + bv->cursor().recordUndoFullDocument(); MatchString const match(searchstr, cs, mw); int num = 0; diff --git a/src/mathed/InsetMathCases.cpp b/src/mathed/InsetMathCases.cpp index 46d2602ab7..ccbbee508a 100644 --- a/src/mathed/InsetMathCases.cpp +++ b/src/mathed/InsetMathCases.cpp @@ -20,7 +20,6 @@ #include "Cursor.h" #include "FuncRequest.h" #include "gettext.h" -#include "Undo.h" #include "support/lstrings.h" @@ -72,7 +71,7 @@ void InsetMathCases::doDispatch(Cursor & cur, FuncRequest & cmd) //lyxerr << "*** InsetMathCases: request: " << cmd << endl; switch (cmd.action) { case LFUN_TABULAR_FEATURE: { - recordUndo(cur); + cur.recordUndo(); docstring const & s = cmd.argument(); if (s == "add-vline-left" || s == "add-vline-right") { cur.undispatched(); diff --git a/src/mathed/InsetMathGrid.cpp b/src/mathed/InsetMathGrid.cpp index 5d36b3d5d2..0bf0fb9c81 100644 --- a/src/mathed/InsetMathGrid.cpp +++ b/src/mathed/InsetMathGrid.cpp @@ -23,7 +23,6 @@ #include "debug.h" #include "FuncRequest.h" #include "gettext.h" -#include "Undo.h" #include "frontends/Clipboard.h" #include "frontends/Painter.h" @@ -1081,7 +1080,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) // multiple cells. Unfortunately this puts the cursor in front // of the inset after undo. This is (especilally for large // grids) annoying. - recordUndoInset(cur); + cur.recordUndoInset(); //autocorrect_ = false; //macroModeClose(); //if (selection_) { @@ -1097,7 +1096,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_CELL_SPLIT: - recordUndo(cur); + cur.recordUndo(); splitCell(cur); break; @@ -1121,7 +1120,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_BREAK_LINE: { - recordUndoInset(cur); + cur.recordUndoInset(); row_type const r = cur.row(); addRow(r); @@ -1142,7 +1141,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_TABULAR_FEATURE: { - recordUndoInset(cur); + cur.recordUndoInset(); //lyxerr << "handling tabular-feature " << to_utf8(cmd.argument()) << endl; istringstream is(to_utf8(cmd.argument())); string s; @@ -1272,12 +1271,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) if (grid.nargs() == 1) { // single cell/part of cell - recordUndo(cur); + cur.recordUndo(); cur.cell().insert(cur.pos(), grid.cell(0)); cur.pos() += grid.cell(0).size(); } else { // multiple cells - recordUndoInset(cur); + cur.recordUndoInset(); col_type const numcols = min(grid.ncols(), ncols() - col(cur.idx())); row_type const numrows = @@ -1299,7 +1298,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) cell(i).append(grid.cell(grid.index(r, c))); } cur.clearSelection(); // bug 393 - finishUndo(); + cur.finishUndo(); break; } diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index fb48a99e42..3c19dc6c05 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -42,7 +42,6 @@ #include "sgml.h" #include "Text.h" #include "TextPainter.h" -#include "Undo.h" #include "insets/RenderPreview.h" #include "insets/InsetLabel.h" @@ -1052,7 +1051,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_BREAK_LINE: // some magic for the common case if (type_ == hullSimple || type_ == hullEquation) { - recordUndoInset(cur); + cur.recordUndoInset(); bool const align = cur.bv().buffer().params().use_amsmath == BufferParams::package_on; mutate(align ? hullAlign : hullEqnArray); @@ -1065,7 +1064,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MATH_NUMBER: //lyxerr << "toggling all numbers" << endl; if (display()) { - recordUndoInset(cur); + cur.recordUndoInset(); bool old = numberedType(); if (type_ == hullMultline) numbered(nrows() - 1, !old); @@ -1079,7 +1078,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MATH_NONUMBER: if (display()) { - recordUndoInset(cur); + cur.recordUndoInset(); row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); bool old = numbered(r); cur.message(old ? _("No number") : _("Number")); @@ -1088,7 +1087,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_LABEL_INSERT: { - recordUndoInset(cur); + cur.recordUndoInset(); row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); docstring old_label = label(r); docstring const default_label = from_ascii( @@ -1116,7 +1115,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) InsetCommandParams p("label"); InsetCommandMailer::string2params(name, to_utf8(cmd.argument()), p); docstring str = p["name"]; - recordUndoInset(cur); + cur.recordUndoInset(); row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); str = support::trim(str); if (!str.empty()) @@ -1134,12 +1133,12 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_MATH_EXTERN: - recordUndoInset(cur); + cur.recordUndoInset(); doExtern(cur, cmd); break; case LFUN_MATH_MUTATE: { - recordUndoInset(cur); + cur.recordUndoInset(); row_type row = cur.row(); col_type col = cur.col(); mutate(hullType(cmd.argument())); @@ -1155,7 +1154,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_MATH_DISPLAY: { - recordUndoInset(cur); + cur.recordUndoInset(); mutate(type_ == hullSimple ? hullEquation : hullSimple); cur.idx() = 0; cur.pos() = cur.lastpos(); @@ -1287,7 +1286,7 @@ void InsetMathHull::handleFont(Cursor & cur, docstring const & arg, { // this whole function is a hack and won't work for incremental font // changes... - recordUndo(cur); + cur.recordUndo(); if (cur.inset().asInsetMath()->name() == font) cur.handleFont(to_utf8(font)); else { @@ -1299,7 +1298,7 @@ void InsetMathHull::handleFont(Cursor & cur, docstring const & arg, void InsetMathHull::handleFont2(Cursor & cur, docstring const & arg) { - recordUndo(cur); + cur.recordUndo(); Font font; bool b; font.fromString(to_utf8(arg), b); diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index fd511d9e0f..9f21af7005 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -46,7 +46,6 @@ #include "gettext.h" #include "Text.h" #include "OutputParams.h" -#include "Undo.h" #include "support/lstrings.h" #include "support/textutils.h" @@ -416,10 +415,10 @@ void InsetMathNest::handleFont // changes... if (cur.inset().asInsetMath()->name() == font) { - recordUndoInset(cur, Undo::ATOMIC); + cur.recordUndoInset(); cur.handleFont(to_utf8(font)); } else { - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); cur.handleNest(createInsetMath(font)); cur.insert(arg); } @@ -428,7 +427,7 @@ void InsetMathNest::handleFont void InsetMathNest::handleFont2(Cursor & cur, docstring const & arg) { - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); Font font; bool b; font.fromString(to_utf8(arg), b); @@ -447,7 +446,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) switch (cmd.action) { case LFUN_PASTE: { - recordUndo(cur); + cur.recordUndo(); cur.message(_("Paste")); replaceSelection(cur); docstring topaste; @@ -461,12 +460,12 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } cur.niceInsert(topaste); cur.clearSelection(); // bug 393 - finishUndo(); + cur.finishUndo(); break; } case LFUN_CUT: - recordUndo(cur); + cur.recordUndo(); cutSelection(cur, true, true); cur.message(_("Cut")); // Prevent stale position >= size crash @@ -670,9 +669,9 @@ goto_char_backwards: case LFUN_CHAR_DELETE_BACKWARD: if (cur.pos() == 0) // May affect external cell: - recordUndoInset(cur, Undo::ATOMIC); + cur.recordUndoInset(); else - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); // if the inset can not be removed from within, delete it if (!cur.backspace()) { FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD); @@ -684,9 +683,9 @@ goto_char_backwards: case LFUN_CHAR_DELETE_FORWARD: if (cur.pos() == cur.lastpos()) // May affect external cell: - recordUndoInset(cur, Undo::ATOMIC); + cur.recordUndoInset(); else - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); // if the inset can not be removed from within, delete it if (!cur.erase()) { FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD); @@ -704,14 +703,14 @@ goto_char_backwards: break; case LFUN_INSET_TOGGLE: - recordUndo(cur); + cur.recordUndo(); lock(!lock()); cur.popRight(); break; case LFUN_SELF_INSERT: if (cmd.argument().size() != 1) { - recordUndo(cur); + cur.recordUndo(); docstring const arg = cmd.argument(); if (!interpretString(cur, arg)) cur.insert(arg); @@ -727,7 +726,7 @@ goto_char_backwards: // A side effect is that an undo before the macro is finished // undoes the complete macro, not only the last character. if (!cur.inMacroMode()) - recordUndo(cur); + cur.recordUndo(); // spacial handling of space. If we insert an inset // via macro mode, we want to put the cursor inside it @@ -766,7 +765,7 @@ goto_char_backwards: if (cmd.argument().empty()) { // do superscript if LyX handles // deadkeys - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); script(cur, true, grabAndEraseSelection(cur)); } break; @@ -875,13 +874,13 @@ goto_char_backwards: case LFUN_MATH_SIZE: #if 0 - recordUndo(cur); + cur.recordUndo(); cur.setSize(arg); #endif break; case LFUN_MATH_MATRIX: { - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); unsigned int m = 1; unsigned int n = 1; docstring v_align; @@ -906,7 +905,7 @@ goto_char_backwards: ls = '('; if (rs.empty()) rs = ')'; - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); cur.handleNest(MathAtom(new InsetMathDelim(ls, rs))); break; } @@ -925,7 +924,7 @@ goto_char_backwards: // We mimic LFUN_MATH_DELIM in case we have an empty left // or right delimiter. if (have_l || have_r) { - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); docstring const selection = grabAndEraseSelection(cur); selClearOrDel(cur); if (have_l) @@ -943,31 +942,31 @@ goto_char_backwards: case LFUN_SPACE_INSERT: case LFUN_MATH_SPACE: - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); cur.insert(MathAtom(new InsetMathSpace(from_ascii(",")))); break; case LFUN_ERT_INSERT: // interpret this as if a backslash was typed - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); interpretChar(cur, '\\'); break; case LFUN_MATH_SUBSCRIPT: // interpret this as if a _ was typed - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); interpretChar(cur, '_'); break; case LFUN_MATH_SUPERSCRIPT: // interpret this as if a ^ was typed - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); interpretChar(cur, '^'); break; case LFUN_QUOTE_INSERT: // interpret this as if a straight " was typed - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); interpretChar(cur, '\"'); break; @@ -975,7 +974,7 @@ goto_char_backwards: // handling such that "self-insert" works on "arbitrary stuff" too, and // math-insert only handles special math things like "matrix". case LFUN_MATH_INSERT: { - recordUndo(cur, Undo::ATOMIC); + cur.recordUndo(); if (cmd.argument() == "^" || cmd.argument() == "_") { interpretChar(cur, cmd.argument()[0]); } else @@ -997,7 +996,7 @@ goto_char_backwards: case LFUN_INSET_INSERT: { MathData ar; if (createInsetMath_fromDialogStr(cmd.argument(), ar)) { - recordUndo(cur); + cur.recordUndo(); cur.insert(ar); } else cur.undispatched(); @@ -1005,7 +1004,7 @@ goto_char_backwards: } case LFUN_INSET_DISSOLVE: if (!asHullInset()) { - recordUndoInset(cur, Undo::ATOMIC); + cur.recordUndoInset(); cur.pullArg(); } break; diff --git a/src/mathed/InsetMathScript.cpp b/src/mathed/InsetMathScript.cpp index a9e1afa03d..71061b18b4 100644 --- a/src/mathed/InsetMathScript.cpp +++ b/src/mathed/InsetMathScript.cpp @@ -20,7 +20,6 @@ #include "Cursor.h" #include "debug.h" #include "FuncRequest.h" -#include "Undo.h" #include @@ -673,18 +672,18 @@ bool InsetMathScript::notifyCursorLeaves(Cursor & cur) // Case of two scripts. In this case, 1 = super, 2 = sub if (cur.idx() == 2 && cell(2).empty()) { // must be a subscript... - recordUndoInset(cur); + cur.recordUndoInset(); removeScript(false); return true; } else if (cur.idx() == 1 && cell(1).empty()) { // must be a superscript... - recordUndoInset(cur); + cur.recordUndoInset(); removeScript(true); return true; } } else if (nargs() > 1 && cur.idx() == 1 && cell(1).empty()) { // could be either subscript or super script - recordUndoInset(cur); + cur.recordUndoInset(); removeScript(cell_1_is_up_); // Let the script inset commit suicide. This is // modelled on Cursor.pullArg(), but tries not to diff --git a/src/support/FileName.h b/src/support/FileName.h index 2fc0be4d95..e5059b24e4 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -13,6 +13,7 @@ #define FILENAME_H #include +#include namespace lyx {