diff --git a/src/ChangeLog b/src/ChangeLog index 88bc9e7823..0dee81697e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ + +2003-10-15 André Pönitz + + * iterators.[Ch]: + * iterators.[Ch]: + * undo.[Ch]: make undo aware of inner insets + 2003-10-14 Angus Leeming * lyx_main.[Ch]: make LyX a singleton class, accessible though the new diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index 1959ddc91f..f85ebb44fa 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,10 @@ + +2003-10-15 André Pönitz + + * insetcollapsable.[Ch] + * insettabular.[Ch] + * inset.h: re-add some edit(bv, index) method called by undo + 2003-10-14 Angus Leeming * insetexternal.[Ch] (view, cache, view_): diff --git a/src/insets/inset.h b/src/insets/inset.h index dcfad21748..7fd12af7bf 100644 --- a/src/insets/inset.h +++ b/src/insets/inset.h @@ -246,6 +246,8 @@ public: int id() const; /// void id(int id_arg); + /// lock cell with given index + virtual void edit(BufferView *, int /*index*/) {} /// used to toggle insets // is the inset open? diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index 3e5eb44570..b010a160ff 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -271,6 +271,16 @@ bool InsetCollapsable::hitButton(FuncRequest const & cmd) const } +void InsetCollapsable::edit(BufferView * bv, int index) +{ + lyxerr << "InsetCollapsable: edit" << endl; + if (!bv->lockInset(this)) + lyxerr << "InsetCollapsable: can't lock index " << index << endl; + inset.localDispatch(FuncRequest(bv, LFUN_INSET_EDIT, "left")); + first_after_edit = true; +} + + dispatch_result InsetCollapsable::localDispatch(FuncRequest const & cmd) { //lyxerr << "InsetCollapsable::localDispatch: " diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index a1a4b10b60..e641701ca6 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -167,6 +167,8 @@ private: void lfunMouseRelease(FuncRequest const &); /// FuncRequest adjustCommand(FuncRequest const &); + /// + void edit(BufferView *, int index); public: /// diff --git a/src/insets/insetnote.C b/src/insets/insetnote.C index 051b27d6d8..1e3630aa88 100644 --- a/src/insets/insetnote.C +++ b/src/insets/insetnote.C @@ -57,8 +57,7 @@ InsetNote::InsetNote(InsetNote const & in) InsetNote::~InsetNote() { - InsetNoteMailer mailer("note", *this); - mailer.hideDialog(); + InsetNoteMailer("note", *this).hideDialog(); } diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 283e62f1e9..bcc75647d0 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -636,6 +636,30 @@ void InsetTabular::lfunMouseMotion(FuncRequest const & cmd) } +void InsetTabular::edit(BufferView * bv, int index) +{ + lyxerr << "InsetTabular::edit" << endl; + if (!bv->lockInset(this)) { + lyxerr << "InsetTabular::Cannot lock inset (2)" << endl; + return; + } + + locked = true; + the_locking_inset = 0; + inset_x = 0; + inset_y = 0; + actcell = index; + clearSelection(); + resetPos(bv); + bv->fitCursor(); + + UpdatableInset & inset = tabular.getCellInset(actcell); + inset.localDispatch(FuncRequest(bv, LFUN_INSET_EDIT, "left")); + if (the_locking_inset) + updateLocal(bv); +} + + dispatch_result InsetTabular::localDispatch(FuncRequest const & cmd) { // We need to save the value of the_locking_inset as the call to diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h index d02c0ca323..4edfd18b12 100644 --- a/src/insets/insettabular.h +++ b/src/insets/insettabular.h @@ -205,9 +205,11 @@ public: Buffer const & buffer() const; /// set the owning buffer - void buffer(Buffer * b); + void buffer(Buffer * buf); private: + /// lock cell with given index + void edit(BufferView * bv, int index); /// void lfunMousePress(FuncRequest const &); /// diff --git a/src/iterators.C b/src/iterators.C index dd92fd8d01..8aa88c5a7c 100644 --- a/src/iterators.C +++ b/src/iterators.C @@ -169,6 +169,15 @@ InsetOld * ParIterator::inset() const } +int ParIterator::index() const +{ + if (pimpl_->positions.size() <= 1) + return 0; + + return *(pimpl_->positions[pimpl_->positions.size() - 2].index); +} + + Paragraph & ParIterator::operator*() const { return *pimpl_->positions.back().pit; diff --git a/src/iterators.h b/src/iterators.h index e45e6dc3ab..c476b903da 100644 --- a/src/iterators.h +++ b/src/iterators.h @@ -44,8 +44,10 @@ public: /// returns 'innermost' LyXText if in an inset or '0' instead of //bv->text LyXText * text() const; - /// + /// returns innermost inset InsetOld * inset() const; + /// returns index of cell in innermost inset + int index() const; /// size_t size() const; /// diff --git a/src/undo.C b/src/undo.C index d8af9e1a27..bd2d6d0181 100644 --- a/src/undo.C +++ b/src/undo.C @@ -19,17 +19,10 @@ #include "buffer.h" #include "debug.h" #include "BufferView.h" -#include "funcrequest.h" #include "iterators.h" #include "lyxtext.h" #include "paragraph.h" -#include "insets/updatableinset.h" -#include "insets/insettext.h" - -#include - -using std::endl; using lyx::paroffset_type; @@ -39,88 +32,119 @@ bool undo_finished; /// Whether actions are not added to the undo stacks. bool undo_frozen; -Undo::Undo(undo_kind kind_arg, int text_arg, - int first, int last, - int cursor, int cursor_pos_arg, - ParagraphList const & par) +Undo::Undo(undo_kind kind_, int text_, int index_, + int first_par_, int end_par_, int cursor_par_, int cursor_pos_) : - kind(kind_arg), - text(text_arg), - first_par_offset(first), - last_par_offset(last), - cursor_par_offset(cursor), - cursor_pos(cursor_pos_arg), - pars(par) + kind(kind_), + text(text_), + index(index_), + first_par(first_par_), + end_par(end_par_), + cursor_par(cursor_par_), + cursor_pos(cursor_pos_) {} -std::ostream & operator<<(std::ostream & os, Undo const & undo) -{ - return os << " text: " << undo.text - << " first: " << undo.first_par_offset - << " last: " << undo.last_par_offset - << " cursor: " << undo.cursor_par_offset - << "/" << undo.cursor_pos; -} - - namespace { +std::ostream & operator<<(std::ostream & os, Undo const & undo) +{ + return os << " text: " << undo.text + << " index: " << undo.index + << " first: " << undo.first_par + << " from end: " << undo.end_par + << " cursor: " << undo.cursor_par + << "/" << undo.cursor_pos; +} + + +// translates LyXText pointer into offset count from document begin +ParIterator text2pit(LyXText * text, int & tcount) +{ + tcount = 0; + Buffer * buf = text->bv()->buffer(); + ParIterator pit = buf->par_iterator_begin(); + ParIterator end = buf->par_iterator_end(); + + // it.text() returns 0 for outermost text. + if (text == text->bv()->text) + return pit; + + for ( ; pit != end; ++pit, ++tcount) + if (pit.text() == text) + return pit; + lyxerr << "undo: should not happen" << std::endl; + return end; +} + + +// translates offset from buffer begin to ParIterator +ParIterator num2pit(BufferView * bv, int num) +{ + Buffer * buf = bv->buffer(); + ParIterator pit = buf->par_iterator_begin(); + ParIterator end = buf->par_iterator_end(); + + for ( ; num && pit != end; ++pit, --num) + ; + + if (pit != end) + return pit; + + // don't crash early... + lyxerr << "undo: num2pit: num: " << num << std::endl; + BOOST_ASSERT(false); + return buf->par_iterator_begin(); +} + + +// translates offset from buffer begin to LyXText +LyXText * pit2text(BufferView * bv, ParIterator const & pit) +{ + LyXText * text = pit.text(); + return text ? text : bv->text; +} + + void recordUndo(Undo::undo_kind kind, - LyXText * text, paroffset_type firstpar, paroffset_type lastpar, + LyXText * text, paroffset_type first_par, paroffset_type last_par, limited_stack & stack) { Buffer * buf = text->bv()->buffer(); - ParagraphList & plist = text->ownerParagraphs(); - ParagraphList::iterator first = plist.begin(); - advance(first, firstpar); - ParagraphList::iterator last = plist.begin(); - advance(last, lastpar); - - // try to find the appropriate list by counting the - // texts from buffer begin - ParIterator null = buf->par_iterator_end(); - - int tcount = 0; - // it.text() returns 0 for outermost text. - if (text != text->bv()->text) - for (ParIterator it = buf->par_iterator_begin(); it != null; ++it, ++tcount) - if (it.text() == text) - break; - - // and calculate a stable reference to them - int const first_offset = firstpar; - int const last_offset = plist.size() - lastpar; + int const end_par = text->ownerParagraphs().size() - last_par; // Undo::ATOMIC are always recorded (no overlapping there). // overlapping only with insert and delete inside one paragraph: // nobody wants all removed character appear one by one when undoing. - if (! undo_finished && kind != Undo::ATOMIC) { + if (!undo_finished && kind != Undo::ATOMIC) { // Check whether storing is needed. - if (! buf->undostack().empty() + if (!buf->undostack().empty() && buf->undostack().top().kind == kind - && buf->undostack().top().first_par_offset == first_offset - && buf->undostack().top().last_par_offset == last_offset) { + && buf->undostack().top().first_par == first_par + && buf->undostack().top().end_par == end_par) { // No additonal undo recording needed - // effectively, we combine undo recordings to one. return; } } - // Record the cursor position in a stable way. - int const cursor_offset = text->cursor.par(); - // make and push the Undo entry - stack.push(Undo(kind, tcount, - first_offset, last_offset, - cursor_offset, text->cursor.pos(), - ParagraphList())); - lyxerr << "undo record: " << stack.top() << endl; + int textnum; + ParIterator pit = text2pit(text, textnum); + stack.push(Undo(kind, textnum, pit.index(), + first_par, end_par, text->cursor.par(), text->cursor.pos())); + lyxerr << "undo record: " << stack.top() << std::endl; // record the relevant paragraphs ParagraphList & undo_pars = stack.top().pars; + ParagraphList & plist = text->ownerParagraphs(); + ParagraphList::iterator first = plist.begin(); + advance(first, first_par); + ParagraphList::iterator last = plist.begin(); + advance(last, last_par); + for (ParagraphList::iterator it = first; it != last; ++it) { undo_pars.push_back(*it); undo_pars.back().id(it->id()); @@ -133,29 +157,20 @@ void recordUndo(Undo::undo_kind kind, } -// Returns false if no undo possible. +// returns false if no undo possible bool performUndoOrRedo(BufferView * bv, Undo const & undo) { - lyxerr << "undo, performing: " << undo << endl; - Buffer * buf = bv->buffer(); - ParIterator plit = buf->par_iterator_begin(); - ParIterator null = buf->par_iterator_end(); - - int tcount = undo.text; - for ( ; tcount && plit != null; ++plit, --tcount) - ; - - LyXText * text = plit.text(); - if (!text) - text = bv->text; + lyxerr << "undo, performing: " << undo << std::endl; + ParIterator pit = num2pit(bv, undo.text); + LyXText * text = pit2text(bv, pit); ParagraphList & plist = text->ownerParagraphs(); // remove new stuff between first and last { ParagraphList::iterator first = plist.begin(); - advance(first, undo.first_par_offset); + advance(first, undo.first_par); ParagraphList::iterator last = plist.begin(); - advance(last, plist.size() - undo.last_par_offset); + advance(last, plist.size() - undo.end_par); plist.erase(first, ++last); } @@ -164,21 +179,23 @@ bool performUndoOrRedo(BufferView * bv, Undo const & undo) plist.assign(undo.pars.begin(), undo.pars.end()); } else { ParagraphList::iterator first = plist.begin(); - advance(first, undo.first_par_offset); + advance(first, undo.first_par); plist.insert(first, undo.pars.begin(), undo.pars.end()); } // set cursor - lyxerr << "undo, text: " << text << " inset: " << plit.inset() << endl; - InsetOld * inset = plit.inset(); + lyxerr << "undo, text: " << undo.text + << " inset: " << pit.inset() + << " index: " << undo.index + << std::endl; + InsetOld * inset = pit.inset(); if (inset) { - // Magic needed to cope with inset locking - FuncRequest cmd(bv, LFUN_INSET_EDIT, "left"); - inset->localDispatch(cmd); + // magic needed to cope with inset locking + inset->edit(bv, undo.index); } // set cursor again to force the position to be the right one - text->setCursorIntern(undo.cursor_par_offset, undo.cursor_pos); + text->setCursorIntern(undo.cursor_par, undo.cursor_pos); // clear any selection text->clearSelection(); @@ -193,15 +210,12 @@ bool performUndoOrRedo(BufferView * bv, Undo const & undo) } -// Returns false if no undo possible. +// returns false if no undo possible bool textUndoOrRedo(BufferView * bv, limited_stack & stack, limited_stack & otherstack) { if (stack.empty()) { - /* - * Finish the undo operation in the case there was no entry - * on the stack to perform. - */ + // nothing to do freezeUndo(); bv->unlockInset(bv->theLockingInset()); finishUndo(); @@ -216,17 +230,19 @@ bool textUndoOrRedo(BufferView * bv, if (!undo_frozen) { otherstack.push(undo); otherstack.top().pars.clear(); - Buffer * buf = bv->buffer(); - ParagraphList & plist = buf->paragraphs(); - if (undo.first_par_offset + undo.last_par_offset <= int(plist.size())) { + ParIterator pit = num2pit(bv, undo.text); + ParagraphList & plist = pit.plist(); + if (undo.first_par + undo.end_par <= int(plist.size())) { ParagraphList::iterator first = plist.begin(); - advance(first, undo.first_par_offset); + advance(first, undo.first_par); ParagraphList::iterator last = plist.begin(); - advance(last, plist.size() - undo.last_par_offset + 1); + advance(last, plist.size() - undo.end_par + 1); otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last); } - //otherstack.top().cursor_pos = text; - //lyxerr << " undo other: " << otherstack.top() << endl; + LyXText * text = pit2text(bv, pit); + otherstack.top().cursor_pos = text->cursor.pos(); + otherstack.top().cursor_par = text->cursor.par(); + lyxerr << " undo other: " << otherstack.top() << std::endl; } // Now we can unlock the inset for safety because the inset @@ -245,21 +261,21 @@ bool textUndoOrRedo(BufferView * bv, void freezeUndo() { - // This is dangerous and for internal use only. + // this is dangerous and for internal use only undo_frozen = true; } void unFreezeUndo() { - // This is dangerous and for internal use only. + // this is dangerous and for internal use only undo_frozen = false; } void finishUndo() { - // Makes sure the next operation will be stored. + // makes sure the next operation will be stored undo_finished = true; } @@ -281,12 +297,11 @@ bool textRedo(BufferView * bv) void recordUndo(Undo::undo_kind kind, LyXText const * text, paroffset_type first, paroffset_type last) { - if (!undo_frozen) { - Buffer * buf = text->bv()->buffer(); - recordUndo(kind, const_cast(text), - first, last, buf->undostack()); - buf->redostack().clear(); - } + if (undo_frozen) + return; + Buffer * buf = text->bv()->buffer(); + recordUndo(kind, const_cast(text), first, last, buf->undostack()); + buf->redostack().clear(); } diff --git a/src/undo.h b/src/undo.h index 33ed9c34db..edf8f5562e 100644 --- a/src/undo.h +++ b/src/undo.h @@ -49,55 +49,49 @@ public: /// Atomic - each of these will have its own entry in the stack ATOMIC }; - /// - Undo(undo_kind kind, int text, - int first, int last, - int cursor, int cursor_pos, - ParagraphList const & par_arg); + /// constructor + Undo(undo_kind kind, int text, int index, + int first_par, int end_par, int cursor_par, int cursor_pos); - /// Which kind of operation are we recording for? + /// which kind of operation are we recording for? undo_kind kind; /// hosting LyXText counted from buffer begin int text; - /// Offset to the first paragraph in the main document paragraph list - int first_par_offset; + /// cell in a tabular or similar + int index; - /// Offset to the last paragraph from the end of the main par. list - int last_par_offset; + /// offset to the first paragraph in the paragraph list + int first_par; - /** - * Offset from the start of the main document paragraph list, - * except if inside an inset, in which case it's the offset - * inside the hosting inset. - */ - int cursor_par_offset; + /// offset to the last paragraph from the end of parargraph list + int end_par; - /// The position of the cursor in the hosting paragraph + /// offset to the first paragraph in the paragraph list + int cursor_par; + + /// the position of the cursor in the hosting paragraph int cursor_pos; - /// The contents of the paragraphs saved + /// the contents of the paragraphs saved ParagraphList pars; }; -/// This will undo the last action - returns false if no undo possible +/// this will undo the last action - returns false if no undo possible bool textUndo(BufferView *); -/// This will redo the last undo - returns false if no redo possible +/// this will redo the last undo - returns false if no redo possible bool textRedo(BufferView *); -/// Makes sure the next operation will be stored +/// makes sure the next operation will be stored void finishUndo(); -/** - * Whilst undo is frozen, all actions do not get added - * to the undo stack - */ +/// whilst undo is frozen, all actions do not get added to the undo stack void freezeUndo(); -/// Track undos again +/// track undos again void unFreezeUndo(); /** @@ -110,14 +104,14 @@ void unFreezeUndo(); void recordUndo(Undo::undo_kind kind, LyXText const * text, lyx::paroffset_type first, lyx::paroffset_type last); -/// Convienience: Prepare undo when change in a single paragraph. +/// convienience: prepare undo when change in a single paragraph void recordUndo(Undo::undo_kind kind, LyXText const * text, lyx::paroffset_type par); -/// Convienience: Prepare undo for the paragraph that contains the cursor +/// convienience: prepare undo for the paragraph that contains the cursor void recordUndo(BufferView *, Undo::undo_kind kind); -/// Are we avoiding tracking undos currently ? +/// are we avoiding tracking undos currently? extern bool undo_frozen; #endif // UNDO_FUNCS_H