From a5c7dde1e44c544bae0bc6d9c9e463d15b82ddc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Wed, 4 Jun 2003 12:45:26 +0000 Subject: [PATCH] the latest undo patch without the paragraphlist stuff git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@7102 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/iterators.C | 46 ++++--- src/iterators.h | 2 + src/text2.C | 2 +- src/undo.C | 29 ++--- src/undo.h | 16 ++- src/undo_funcs.C | 324 ++++++++++++++++++++++------------------------- 6 files changed, 201 insertions(+), 218 deletions(-) diff --git a/src/iterators.C b/src/iterators.C index 0821d0e667..5bd591273f 100644 --- a/src/iterators.C +++ b/src/iterators.C @@ -17,11 +17,13 @@ #include #include -#include +// it's conceptionally a stack, but undo needs random access... +//#include +#include using boost::next; using boost::optional; -using std::stack; +using std::vector; /// /// ParPosition @@ -68,14 +70,14 @@ bool operator!=(ParPosition const & pos1, ParPosition const & pos2) /// struct ParIterator::Pimpl { - typedef stack PosHolder; + typedef vector PosHolder; PosHolder positions; }; ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl) : pimpl_(new Pimpl) { - pimpl_->positions.push(ParPosition(pit, pl)); + pimpl_->positions.push_back(ParPosition(pit, pl)); } @@ -98,14 +100,14 @@ void ParIterator::operator=(ParIterator const & pi) ParIterator & ParIterator::operator++() { while (!pimpl_->positions.empty()) { - ParPosition & p = pimpl_->positions.top(); + ParPosition & p = pimpl_->positions.back(); // Does the current inset contain more "cells" ? if (p.index) { ++(*p.index); ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index); if (plist && !plist->empty()) { - pimpl_->positions.push(ParPosition(plist->begin(), *plist)); + pimpl_->positions.push_back(ParPosition(plist->begin(), *plist)); return *this; } ++(*p.it); @@ -121,7 +123,7 @@ ParIterator & ParIterator::operator++() ParagraphList * plist = (*p.it)->inset->getParagraphs(0); if (plist && !plist->empty()) { p.index.reset(0); - pimpl_->positions.push(ParPosition(plist->begin(), *plist)); + pimpl_->positions.push_back(ParPosition(plist->begin(), *plist)); return *this; } } @@ -137,7 +139,7 @@ ParIterator & ParIterator::operator++() } // Drop end and move up in the stack. - pimpl_->positions.pop(); + pimpl_->positions.pop_back(); } return *this; } @@ -145,13 +147,19 @@ ParIterator & ParIterator::operator++() ParagraphList::iterator ParIterator::operator*() const { - return pimpl_->positions.top().pit; + return pimpl_->positions.back().pit; } ParagraphList::iterator ParIterator::operator->() const { - return pimpl_->positions.top().pit; + return pimpl_->positions.back().pit; +} + + +ParagraphList::iterator ParIterator::outerPar() const +{ + return pimpl_->positions[0].pit; } @@ -163,7 +171,7 @@ size_t ParIterator::size() const ParagraphList & ParIterator::plist() const { - return *const_cast(pimpl_->positions.top().plist); + return *const_cast(pimpl_->positions.back().plist); } @@ -185,7 +193,7 @@ bool operator!=(ParIterator const & iter1, ParIterator const & iter2) struct ParConstIterator::Pimpl { - typedef stack PosHolder; + typedef vector PosHolder; PosHolder positions; }; @@ -194,7 +202,7 @@ ParConstIterator::ParConstIterator(ParagraphList::iterator pit, ParagraphList const & pl) : pimpl_(new Pimpl) { - pimpl_->positions.push(ParPosition(pit, pl)); + pimpl_->positions.push_back(ParPosition(pit, pl)); } @@ -210,14 +218,14 @@ ParConstIterator::ParConstIterator(ParConstIterator const & pi) ParConstIterator & ParConstIterator::operator++() { while (!pimpl_->positions.empty()) { - ParPosition & p = pimpl_->positions.top(); + ParPosition & p = pimpl_->positions.back(); // Does the current inset contain more "cells" ? if (p.index) { ++(*p.index); ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index); if (plist && !plist->empty()) { - pimpl_->positions.push(ParPosition(plist->begin(), *plist)); + pimpl_->positions.push_back(ParPosition(plist->begin(), *plist)); return *this; } ++(*p.it); @@ -233,7 +241,7 @@ ParConstIterator & ParConstIterator::operator++() ParagraphList * plist = (*p.it)->inset->getParagraphs(0); if (plist && !plist->empty()) { p.index.reset(0); - pimpl_->positions.push(ParPosition(plist->begin(), *plist)); + pimpl_->positions.push_back(ParPosition(plist->begin(), *plist)); return *this; } } @@ -249,7 +257,7 @@ ParConstIterator & ParConstIterator::operator++() } // Drop end and move up in the stack. - pimpl_->positions.pop(); + pimpl_->positions.pop_back(); } return *this; @@ -258,13 +266,13 @@ ParConstIterator & ParConstIterator::operator++() ParagraphList::iterator ParConstIterator::operator*() const { - return pimpl_->positions.top().pit; + return pimpl_->positions.back().pit; } ParagraphList::iterator ParConstIterator::operator->() const { - return pimpl_->positions.top().pit; + return pimpl_->positions.back().pit; } diff --git a/src/iterators.h b/src/iterators.h index 8c607ee212..f3153ad8e6 100644 --- a/src/iterators.h +++ b/src/iterators.h @@ -33,6 +33,8 @@ public: /// ParagraphList::iterator operator->() const; /// + ParagraphList::iterator outerPar() const; + /// ParagraphList & plist() const; /// size_t size() const; diff --git a/src/text2.C b/src/text2.C index 17c410da5a..4fe6b16612 100644 --- a/src/text2.C +++ b/src/text2.C @@ -658,7 +658,7 @@ void LyXText::redoDrawingOfParagraph(LyXCursor const & cur) } -// deletes and inserts again all paragaphs between the cursor +// deletes and inserts again all paragraphs between the cursor // and the specified par // This function is needed after SetLayout and SetFont etc. void LyXText::redoParagraphs(LyXCursor const & cur, diff --git a/src/undo.C b/src/undo.C index ca532b4b1c..80f8a35cf3 100644 --- a/src/undo.C +++ b/src/undo.C @@ -11,20 +11,19 @@ #include #include "undo.h" -#include "paragraph.h" - -Undo::Undo(undo_kind kind_arg, int id_inset_arg, - int number_before_arg, int number_behind_arg, - int cursor_par_arg, int cursor_pos_arg, - ParagraphList const & par_arg) - : pars(par_arg) -{ - kind = kind_arg; - number_of_inset_id = id_inset_arg; - number_of_before_par = number_before_arg; - number_of_behind_par = number_behind_arg; - number_of_cursor_par = cursor_par_arg; - cursor_pos = cursor_pos_arg; -} +Undo::Undo(undo_kind kind_arg, int inset, int plist, + int first, int last, + int cursor, int cursor_pos_arg, + ParagraphList const & par) + : + kind(kind_arg), + inset_id(inset), + plist_id(plist), + first_par_offset(first), + last_par_offset(last), + cursor_par_offset(cursor), + cursor_pos(cursor_pos_arg), + pars(par) +{} diff --git a/src/undo.h b/src/undo.h index 8b85b7f50c..57fad5f1d1 100644 --- a/src/undo.h +++ b/src/undo.h @@ -31,22 +31,24 @@ public: /// undo_kind kind; /// - int number_of_before_par; + int inset_id; // valid if >= 0, if < 0 then not in inset /// - int number_of_behind_par; + int plist_id; /// - int number_of_cursor_par; + int first_par_offset; /// - int number_of_inset_id; // valid if >= 0, if < 0 then not in inset + int last_par_offset; + /// + int cursor_par_offset; /// int cursor_pos; // valid if >= 0 /// ParagraphList pars; /// - Undo(undo_kind kind, int inset_id, - int before_par_id, int behind_par_id, - int cursor_par_id, int cursor_pos, + Undo(undo_kind kind, int inset_id, int plist_id, + int first, int last, + int cursor, int cursor_pos, ParagraphList const & par_arg); }; diff --git a/src/undo_funcs.C b/src/undo_funcs.C index b0e2eddbc0..5a272b463f 100644 --- a/src/undo_funcs.C +++ b/src/undo_funcs.C @@ -48,78 +48,53 @@ bool textHandleUndo(BufferView * bv, Undo & undo) { Buffer * buf = bv->buffer(); - ParIterator const before = buf->getParFromID(undo.number_of_before_par); - ParIterator const behind = buf->getParFromID(undo.number_of_behind_par); - ParIterator const null = buf->par_iterator_end(); + ParagraphList * plist = &buf->paragraphs; +/* + ParIterator null = buf->par_iterator_end(); - int const before_id = (before == null) ? -1 : before->id(); - int const behind_id = (behind == null) ? -1 : behind->id(); - int const inset_id = undo.number_of_inset_id; - - Inset * inset = bv->buffer()->getInsetFromID(inset_id); - LyXText * text = inset ? inset->getLyXText(bv) : bv->text; - - ParagraphList * plist = &bv->text->ownerParagraphs(); - if (inset) { - ParagraphList * tmp = inset->getParagraphs(0); - if (tmp && !tmp->empty()) - plist = tmp; - } - - ParagraphList::iterator first; - if (before == null) { - // if there's no before take the beginning of parlist. - first = plist->begin(); - text->setCursorIntern(plist->begin(), 0); - } else { - first = *before; - ++first; - } - int const first_id = first->id(); - - lyxerr << "\nhandle: before_id: " << before_id << "\n"; - lyxerr << "handle: first_id: " << first_id << "\n"; - lyxerr << "handle: behind_id: " << behind_id << "\n"; - lyxerr << "handle: inset_id: " << inset_id << "\n"; + for (ParIterator it = buf->par_iterator_begin(); it != null; ++it) + if (it.plist().id() == undo.plist_id) { + plist = &it.plist(); + break; + } +*/ // Set the right(new) inset-owner of the paragraph if there is any. - UpdatableInset * in = 0; - if (before != null) - in = before->inInset(); - else if (inset_id >= 0) { - Inset * inset = bv->buffer()->getInsetFromID(inset_id); - in = static_cast(inset); + UpdatableInset * inset = 0; + if (undo.inset_id >= 0) { + Inset * in = bv->buffer()->getInsetFromID(undo.inset_id); + inset = static_cast(in); } ParagraphList::iterator pit = undo.pars.begin(); ParagraphList::iterator end = undo.pars.end(); for ( ; pit != end; ++pit) - pit->setInsetOwner(in); - lyxerr << "in: " << in << "\n"; - lyxerr << "undo.pars.size(): " << undo.pars.size() << "\n"; + pit->setInsetOwner(inset); + + lyxerr << "\nhandle: inset_id: " << undo.inset_id << "\n"; + lyxerr << "handle: inset: " << inset << "\n"; + lyxerr << "handle: plist_id: " << undo.plist_id << "\n"; + lyxerr << "handle: undo.pars.size(): " << undo.pars.size() << "\n"; // remove stuff between first and behind - if (behind == null) - plist->erase(first, plist->end()); - else - plist->erase(first, *behind); - lyxerr << "after erase\n"; - - // re-create first - if (before == null) { - // if there's no before take the beginning of parlist. - lyxerr << "no 'before'\n"; - first = plist->begin(); - } else { - lyxerr << "have 'before'\n"; - first = *before; - ++first; + { + ParagraphList::iterator first = plist->begin(); + advance(first, undo.first_par_offset); + ParagraphList::iterator last = plist->begin(); + advance(last, plist->size() - undo.last_par_offset); + lyxerr << "handle: first_id: " << first->id() << "\n"; + lyxerr << "handle: last_id: " << last->id() << "\n"; + plist->erase(first, ++last); + lyxerr << "after remove\n"; } + // re-insert old stuff + { + ParagraphList::iterator first = plist->begin(); + advance(first, undo.first_par_offset); + plist->insert(first, undo.pars.begin(), undo.pars.end()); + lyxerr << "after insert\n"; + } - // inset saved paragraphs - lyxerr << "undo.pars.size(): " << undo.pars.size() << "\n"; - plist->insert(first, undo.pars.begin(), undo.pars.end()); - lyxerr << "after insert\n"; /* // A memory optimization for edit: // Only layout information @@ -131,53 +106,53 @@ bool textHandleUndo(BufferView * bv, Undo & undo) } */ - // Set the cursor for redoing - // if we have a par before the first. - if (before != null) { - Inset * it = before->inInset(); - LyXText * text = it ? it->getLyXText(bv) : bv->text; - text->setCursorIntern(*before, 0); - } - - UpdatableInset * it = 0; - if (first != plist->end()) - it = first->inInset(); - lyxerr << "it: " << it << "\n"; - - - text->redoParagraphs(text->cursor, plist->end()); - - ParIterator tmppar = bv->buffer()->getParFromID(inset_id); - - if (tmppar != null) { - lyxerr << "tmppar: " << tmppar->id() << "\n"; - LyXText * t; - Inset * it = tmppar->inInset(); - if (it) { - FuncRequest cmd(bv, LFUN_INSET_EDIT, "left"); - it->localDispatch(cmd); - t = it->getLyXText(bv); - } else { - t = bv->text; + // redo Paragraphs (should be handled outside undo...) + LyXText * text = inset ? inset->getLyXText(bv) : bv->text; + { + lyxerr << "text: " << text << "\n"; + if (undo.first_par_offset) { + ParagraphList::iterator redo = plist->begin(); + advance(redo, undo.first_par_offset); + text->setCursorIntern(plist->begin(), 0); } - t->setCursorIntern(*tmppar, undo.cursor_pos); - // Clear any selection and set the selection - // cursor for an evt. new selection. - t->clearSelection(); - t->selection.cursor = t->cursor; - t->updateCounters(); - } else { - lyxerr << "tmppar == null \n"; + text->redoParagraphs(text->cursor, plist->end()); + lyxerr << "after redo\n"; } +/* + Inset * = bv->buffer()->getInsetFromID(inset_id); + lyxerr << "tmppar: " << tmppar->id() << "\n"; + LyXText * t; if (it) { + FuncRequest cmd(bv, LFUN_INSET_EDIT, "left"); + it->localDispatch(cmd); + t = it->getLyXText(bv); + } else { + t = bv->text; + } + t->setCursorIntern(*tmppar, undo.cursor_pos); + // Clear any selection and set the selection + // cursor for an evt. new selection. + t->clearSelection(); + t->selection.cursor = t->cursor; + t->updateCounters(); +*/ + + if (inset) { lyxerr << "fit cursor...\n"; bv->fitCursor(); - bv->updateInset(it); - bv->text->setCursorIntern(bv->text->cursor.par(), - bv->text->cursor.pos()); + bv->updateInset(inset); } + // set cursor + { + ParagraphList::iterator cursor = plist->begin(); + advance(cursor, undo.cursor_par_offset); + bv->text->setCursorIntern(cursor, undo.cursor_pos); + lyxerr << "after setCursor\n"; + } + + finishUndo(); bv->text->postPaint(0); @@ -187,55 +162,60 @@ bool textHandleUndo(BufferView * bv, Undo & undo) void createUndo(BufferView * bv, Undo::undo_kind kind, - int first_id, int last_id, + ParagraphList::iterator first, ParagraphList::iterator last, limited_stack & stack) { Buffer * buf = bv->buffer(); - ParIterator null = buf->par_iterator_end(); - ParIterator prev = null; - ParIterator before = null; - ParIterator first = null; - ParIterator last = null; - ParIterator behind = null; - - for (ParIterator it = buf->par_iterator_begin(); it != null; ++it) { - if (it->id() == first_id) { - first = it; - before = prev; - } - if (it->id() == last_id) { - last = it; - behind = last; - ++behind; - } - prev = it; - } - - if (last == null) - last = first; - - int const before_id = (before == null) ? -1 : before->id(); - int const behind_id = (behind == null) ? -1 : behind->id(); - int inset_id = (first->inInset()) ? first->inInset()->id() : -1; - - lyxerr << "\ncreate: before_id: " << before_id << "\n"; - lyxerr << "create: first_id: " << first_id << "\n"; - lyxerr << "create: last_id: " << last_id << "\n"; - lyxerr << "create: behind_id: " << behind_id << "\n"; - lyxerr << "create: inset_id: " << inset_id << "\n"; - lyxerr << "create: kind: " << kind << "\n"; - ParagraphList * plist = 0; - if (first != null) - plist = &first.plist(); - else if (behind != null) - plist = &behind.plist(); - else if (!plist) { - lyxerr << "plist from buffer (should this happen?)\n"; - plist = &buf->paragraphs; + ParIterator null = buf->par_iterator_end(); + + lyxerr << "\n"; + +#if 0 + // this is what we'd like to have in the end for small grained undo + for (ParIterator it = buf->par_iterator_begin(); it != null; ++it) { + if (it->id() == first->id()) { + plist = &it.plist(); + break; + } } +#else + + // and that's the big stick we wield now + lyxerr << "create: first_id orig: " << first->id() << "\n"; + lyxerr << "create: last_id orig: " << last->id() << "\n"; + plist = &buf->paragraphs; + // this is what we'd like to have in the end for small grained undo + for (ParIterator it = buf->par_iterator_begin(); it != null; ++it) { + if (it->id() == first->id()) { + first = it.outerPar(); + last = it.outerPar(); + break; + } + } + +#endif + + int const inset_id = first->inInset() ? first->inInset()->id() : -1; + + int const first_offset = std::distance(plist->begin(), first); + int const last_offset = std::distance(last, plist->end()); + + if (last == plist->end()) { + lyxerr << "*** createUndo: last == end schould not happen\n"; + } + + //lyxerr << "create: plist_id: " << plist->id() << "\n"; + lyxerr << "create: first_id: " << first->id() << "\n"; + lyxerr << "create: last_id: " << last->id() << "\n"; + lyxerr << "create: first_offset: " << first_offset << "\n"; + lyxerr << "create: last_offset: " << last_offset << "\n"; + lyxerr << "create: inset_id: " << inset_id << "\n"; + lyxerr << "create: kind: " << kind << "\n"; + + // Undo::EDIT and Undo::FINISH are // always finished. (no overlapping there) // overlapping only with insert and delete inside one paragraph: @@ -247,27 +227,33 @@ void createUndo(BufferView * bv, Undo::undo_kind kind, // Check whether storing is needed. if (!buf->undostack.empty() && buf->undostack.top().kind == kind && - buf->undostack.top().number_of_before_par == before_id && - buf->undostack.top().number_of_behind_par == behind_id) { + buf->undostack.top().first_par_offset == first_offset && + buf->undostack.top().last_par_offset == last_offset) { // No undo needed. return; } } // Create a new Undo. +/* + // this should be re-activated once we are back at fine-grained undo LyXCursor const & cur = bv->theLockingInset() ? bv->theLockingInset()->cursor(bv) : bv->text->cursor; + int const cursor_offset = std::distance(plist->begin(), cur.par()); - stack.push(Undo(kind, inset_id, - before_id, behind_id, cur.par()->id(), cur.pos(), ParagraphList())); + stack.push(Undo(kind, inset_id, plist->id(), + first_offset, last_offset, cursor_offset, cur.pos(), ParagraphList())); +*/ + stack.push(Undo(kind, inset_id, 0, //plist->id(), + first_offset, last_offset, first_offset, 0, ParagraphList())); ParagraphList & undo_pars = stack.top().pars; - for (ParagraphList::iterator it = *first; it != *last; ++it) { + for (ParagraphList::iterator it = first; it != last; ++it) { undo_pars.push_back(*it); undo_pars.back().id(it->id()); } - undo_pars.push_back(**last); + undo_pars.push_back(*last); undo_pars.back().id(last->id()); // A memory optimization: Just store the layout @@ -284,7 +270,7 @@ void createUndo(BufferView * bv, Undo::undo_kind kind, // Returns false if no undo possible. bool textUndoOrRedo(BufferView * bv, limited_stack & stack, - limited_stack & /*otherstack*/) + limited_stack & otherstack) { if (stack.empty()) { finishNoUndo(bv); @@ -295,38 +281,24 @@ bool textUndoOrRedo(BufferView * bv, stack.pop(); finishUndo(); -/* if (!undo_frozen) { + otherstack.push(undo); + otherstack.top().pars.clear(); Buffer * buf = bv->buffer(); - ParIterator p = buf->getParFromID(undo->number_of_before_par); - ParIterator const end = buf->par_iterator_end(); - bool ok = false; - ParagraphList::iterator first; - // default constructed? - if (p != end) { - first = p.par(); - if (first->next()) - first = first->next(); - } else { - // Set first to the very first Paragraph depending of where - // we are so it will return the first paragraph of the buffer or the - // first paragraph of the textinset we're in. - first = bv->text->ownerParagraphs()->begin(); - Inset * inset = bv->buffer()->getInsetFromID(inset_id); - if (inset) { - ParagraphList * result = inset->getParagraphs(0); - if (result && !result->empty()) - first = result->begin(); - } - } - if (ok) { - ParIterator behind = buf->getParFromID(undo.number_of_behind_par); - createUndo(bv, undo.kind, first, behind.par(), otherstack); + ParagraphList & plist = buf->paragraphs; + lyxerr << "\nredo: first: " << undo.first_par_offset << "\n"; + lyxerr << "redo: last: " << undo.last_par_offset << "\n"; + lyxerr << "redo: size: " << plist.size() << "\n"; + if (undo.first_par_offset + undo.last_par_offset <= int(plist.size())) { + ParagraphList::iterator first = plist.begin(); + advance(first, undo.first_par_offset); + ParagraphList::iterator last = plist.begin(); + advance(last, plist.size() - undo.last_par_offset + 1); + otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last); } } -*/ - // Now we can unlock the inset for saftey because the inset + // Now we can unlock the inset for safety because the inset // pointer could be changed during the undo-function. Anyway // if needed we have to lock the right inset/position if this // is requested. @@ -386,7 +358,7 @@ void setUndo(BufferView * bv, Undo::undo_kind kind, ParagraphList::iterator first, ParagraphList::iterator last) { if (!undo_frozen) { - createUndo(bv, kind, first->id(), last->id(), bv->buffer()->undostack); + createUndo(bv, kind, first, last, bv->buffer()->undostack); bv->buffer()->redostack.clear(); } }