diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index b7eafa9d96..939d590d05 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -1340,7 +1340,7 @@ bool BufferView::Pimpl::insertInset(InsetOld * inset, string const & lout) } // not quite sure if we want this... - recordUndo(bv_, Undo::ATOMIC); + bv_->text->recUndo(bv_->text->cursor.par()); freezeUndo(); beforeChange(bv_->text); diff --git a/src/ChangeLog b/src/ChangeLog index 8bd297542b..57be76bc3a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ + +2003-10-13 André Pönitz + + * BufferView_pimpl.C: + * lyxtext.h: + * text.C: + * text2.C: + * text3.C: + * undo_funcs.[Ch]: use paroffset_type instead of + ParagraphList::iterators to prevent multiple conversion + (and get a more robust interface) + 2003-10-13 Lars Gullik Bjønnes * lyxfunc.C (dispatch): RESULT -> dispatch_result diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 232ada36a4..c9f84033f9 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -635,8 +635,12 @@ dispatch_result InsetTabular::localDispatch(FuncRequest const & cmd) if (cmd.action == LFUN_INSET_EDIT) { + lyxerr << "InsetTabular::edit: " << this << " args: '" + << cmd.argument << "' first cell: " + << &tabular.cell_info[0][0].inset << endl; + if (!bv->lockInset(this)) { - lyxerr[Debug::INSETTEXT] << "InsetTabular::Cannot lock inset" << endl; + lyxerr << "InsetTabular::Cannot lock inset" << endl; return DISPATCHED; } @@ -2538,6 +2542,11 @@ bool InsetTabular::forceDefaultParagraphs(InsetOld const * in) const if (cell != -1) return tabular.getPWidth(cell).zero(); + // this is a workaround for a crash (New, Insert->Tabular, + // Insert->FootNote) + if (!owner()) + return false; + // well we didn't obviously find it so maybe our owner knows more BOOST_ASSERT(owner()); return owner()->forceDefaultParagraphs(in); diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 6224d2099a..6c8d37a857 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -1336,7 +1336,7 @@ void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall, if (text_.selection.set()) - recordUndo(bv, Undo::ATOMIC, text_.cursorPar()); + text_.recUndo(text_.cursor.par()); if (selectall) { text_.cursorTop(); diff --git a/src/lyxtext.h b/src/lyxtext.h index 9492ca92ff..fd18da9abe 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -258,6 +258,10 @@ public: lyx::pos_type pos, LyXFont const & font) const; + /// + void recUndo(lyx::paroffset_type first, lyx::paroffset_type last) const; + /// + void recUndo(lyx::paroffset_type first) const; /// void setCursorFromCoordinates(int x, int y); /// diff --git a/src/text.C b/src/text.C index 16db12f50a..cf321783b4 100644 --- a/src/text.C +++ b/src/text.C @@ -1206,7 +1206,7 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) && layout->labeltype != LABEL_SENSITIVE) return; - recordUndo(bv(), Undo::ATOMIC, cursorPar()); + recUndo(cursor.par()); // Always break behind a space // @@ -1284,7 +1284,7 @@ void LyXText::redoParagraph() // same Paragraph one to the right and make a rebreak void LyXText::insertChar(char c) { - recordUndo(bv(), Undo::INSERT, cursorPar()); + recordUndo(bv(), Undo::INSERT, ownerParagraphs(), cursor.par(), cursor.par()); // When the free-spacing option is set for the current layout, // disable the double-space checking @@ -1568,7 +1568,7 @@ void LyXText::acceptChange() if (selection.start.par() == selection.end.par()) { LyXCursor & startc = selection.start; LyXCursor & endc = selection.end; - recordUndo(bv(), Undo::INSERT, getPar(startc)); + recordUndo(bv(), Undo::INSERT, ownerParagraphs(), startc.par()); getPar(startc)->acceptChange(startc.pos(), endc.pos()); finishUndo(); clearSelection(); @@ -1587,7 +1587,7 @@ void LyXText::rejectChange() if (selection.start.par() == selection.end.par()) { LyXCursor & startc = selection.start; LyXCursor & endc = selection.end; - recordUndo(bv(), Undo::INSERT, getPar(startc)); + recordUndo(bv(), Undo::INSERT, ownerParagraphs(), startc.par()); getPar(startc)->rejectChange(startc.pos(), endc.pos()); finishUndo(); clearSelection(); @@ -1797,7 +1797,7 @@ void LyXText::changeCase(LyXText::TextCase action) setCursor(to.par(), to.pos() + 1); } - recordUndo(bv(), Undo::ATOMIC, getPar(from), getPar(to)); + recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), from.par(), to.par()); pos_type pos = from.pos(); int par = from.par(); @@ -1858,11 +1858,7 @@ void LyXText::Delete() // if you had success make a backspace if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) { - LyXCursor tmpcursor = cursor; - // to make sure undo gets the right cursor position - cursor = old_cursor; - recordUndo(bv(), Undo::DELETE, cursorPar()); - cursor = tmpcursor; + recordUndo(bv(), Undo::DELETE, ownerParagraphs(), old_cursor.par()); backspace(); } } @@ -1911,11 +1907,9 @@ void LyXText::backspace() } } - if (cursorPar() != ownerParagraphs().begin()) { - recordUndo(bv(), Undo::DELETE, - boost::prior(cursorPar()), - cursorPar()); - } + if (cursor.par() != 0) + recordUndo(bv(), Undo::DELETE, ownerParagraphs(), + cursor.par() - 1, cursor.par()); ParagraphList::iterator tmppit = cursorPar(); // We used to do cursorLeftIntern() here, but it is @@ -1954,7 +1948,7 @@ void LyXText::backspace() } else { // this is the code for a normal backspace, not pasting // any paragraphs - recordUndo(bv(), Undo::DELETE, cursorPar()); + recordUndo(bv(), Undo::DELETE, ownerParagraphs(), cursor.par()); // 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, @@ -1988,7 +1982,7 @@ ParagraphList::iterator LyXText::getPar(LyXCursor const & cur) const ParagraphList::iterator LyXText::getPar(int par) const { BOOST_ASSERT(par >= 0); - BOOST_ASSERT(par < ownerParagraphs().size()); + BOOST_ASSERT(par < int(ownerParagraphs().size())); ParagraphList::iterator pit = ownerParagraphs().begin(); std::advance(pit, par); return pit; diff --git a/src/text2.C b/src/text2.C index e3994ced4f..b3102acf6f 100644 --- a/src/text2.C +++ b/src/text2.C @@ -276,7 +276,7 @@ void LyXText::toggleInset() // do we want to keep this?? (JMarc) if (!isHighlyEditableInset(inset)) - recordUndo(bv(), Undo::ATOMIC); + recUndo(cursor.par()); if (inset->isOpen()) inset->close(bv()); @@ -328,7 +328,7 @@ LyXText::setLayout(LyXCursor & cur, LyXCursor & sstart_cur, ++endpit; } - recordUndo(bv(), Undo::ATOMIC, getPar(sstart_cur), boost::prior(undoendpit)); + recUndo(sstart_cur.par(), parOffset(undoendpit) - 1); // ok we have a selection. This is always between sstart_cur // and sel_end cursor @@ -421,7 +421,7 @@ bool LyXText::changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only) ParagraphList::iterator pastend = boost::next(end); if (!test_only) - recordUndo(bv(), Undo::ATOMIC, start, end); + recUndo(parOffset(start), parOffset(end)); bool changed = false; @@ -514,7 +514,7 @@ void LyXText::setFont(LyXFont const & font, bool toggleall) // ok we have a selection. This is always between sel_start_cursor // and sel_end cursor - recordUndo(bv(), Undo::ATOMIC, getPar(selection.start), getPar(selection.end)); + recUndo(selection.start.par(), selection.end.par()); freezeUndo(); cursor = selection.start; while (cursor.par() != selection.end.par() || @@ -787,8 +787,7 @@ void LyXText::setParagraph(bool line_top, bool line_bottom, ++endpit; } - recordUndo(bv(), Undo::ATOMIC, getPar(selection.start), - boost::prior(undoendpit)); + recUndo(selection.start.par(), parOffset(undoendpit) - 1); int tmppit = selection.end.par(); @@ -1125,7 +1124,7 @@ void LyXText::insertInset(InsetOld * inset) { if (!cursorPar()->insetAllowed(inset->lyxCode())) return; - recordUndo(bv(), Undo::ATOMIC, cursorPar()); + recUndo(cursor.par()); freezeUndo(); cursorPar()->insertInset(cursor.pos(), inset); // Just to rebreak and refresh correctly. @@ -1175,8 +1174,7 @@ void LyXText::cutSelection(bool doclear, bool realcut) ++endpit; } - recordUndo(bv(), Undo::DELETE, getPar(selection.start), - boost::prior(undoendpit)); + recUndo(selection.start.par(), parOffset(undoendpit) - 1); endpit = getPar(selection.end.par()); int endpos = selection.end.pos(); @@ -1246,7 +1244,7 @@ void LyXText::pasteSelection(size_t sel_index) if (!CutAndPaste::checkPastePossible()) return; - recordUndo(bv(), Undo::INSERT, cursorPar()); + recUndo(cursor.par()); ParagraphList::iterator endpit; PitPosPair ppp; @@ -1289,7 +1287,7 @@ void LyXText::setSelectionRange(lyx::pos_type length) // simple replacing. The font of the first selected character is used void LyXText::replaceSelectionWithString(string const & str) { - recordUndo(bv(), Undo::ATOMIC); + recUndo(cursor.par()); freezeUndo(); if (!selection.set()) { // create a dummy selection @@ -1325,7 +1323,7 @@ void LyXText::insertStringAsLines(string const & str) pos_type pos = cursor.pos(); ParagraphList::iterator endpit = boost::next(cursorPar()); - recordUndo(bv(), Undo::ATOMIC); + recUndo(cursor.par()); // only to be sure, should not be neccessary clearSelection(); @@ -1905,7 +1903,7 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) while (endpit != ownerParagraphs().end() && endpit->getDepth()) ++endpit; - recordUndo(bv(), Undo::DELETE, old_pit, boost::prior(endpit)); + recUndo(parOffset(old_pit), parOffset(endpit) - 1); cursor = tmpcursor; // delete old par @@ -1938,6 +1936,18 @@ ParagraphList & LyXText::ownerParagraphs() const } +void LyXText::recUndo(paroffset_type first, paroffset_type last) const +{ + recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), first, last); +} + + +void LyXText::recUndo(lyx::paroffset_type par) const +{ + recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), par, par); +} + + bool LyXText::isInInset() const { // Sub-level has non-null bv owner and non-null inset owner. diff --git a/src/text3.C b/src/text3.C index 35380d1f27..638ea44936 100644 --- a/src/text3.C +++ b/src/text3.C @@ -412,14 +412,14 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd) for (; tmp != end; ++tmp) { if (tmp->params().startOfAppendix()) { - recordUndo(bv, Undo::ATOMIC, tmp); + recUndo(parOffset(tmp)); tmp->params().startOfAppendix(false); redoParagraph(tmp); break; } } - recordUndo(bv, Undo::ATOMIC, pit); + recUndo(parOffset(pit)); pit->params().startOfAppendix(start); // we can set the refreshing parameters now @@ -964,7 +964,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd) break; case LFUN_TRANSPOSE_CHARS: - recordUndo(bv, Undo::ATOMIC, cursorPar()); + recUndo(cursor.par()); redoParagraph(); bv->update(); break; @@ -1434,7 +1434,7 @@ dispatch_result LyXText::dispatch(FuncRequest const & cmd) // ...or maybe the recordUndo() // below isn't necessary at all anylonger? if (inset_hit->lyxCode() == InsetOld::REF_CODE) - recordUndo(bv, Undo::ATOMIC); + recUndo(cursor.par()); bv->owner()->message(inset_hit->editMessage()); diff --git a/src/undo_funcs.C b/src/undo_funcs.C index b12a4a885f..b1de438daf 100644 --- a/src/undo_funcs.C +++ b/src/undo_funcs.C @@ -17,6 +17,7 @@ #include "undo_funcs.h" #include "buffer.h" +#include "debug.h" #include "BufferView.h" #include "funcrequest.h" #include "iterators.h" @@ -25,8 +26,13 @@ #include "insets/updatableinset.h" +#include -/// The flag used by FinishUndo(). +using std::endl; +using lyx::paroffset_type; + + +/// The flag used by finishUndo(). bool undo_finished; /// Whether actions are not added to the undo stacks. @@ -36,18 +42,22 @@ namespace { void recordUndo(BufferView * bv, Undo::undo_kind kind, - ParagraphList::iterator first, ParagraphList::iterator last, + ParagraphList & plist, paroffset_type firstpar, paroffset_type lastpar, limited_stack & stack) { Buffer * buf = bv->buffer(); + ParagraphList::iterator first = plist.begin(); + advance(first, firstpar); + ParagraphList::iterator last = plist.begin(); + advance(last, lastpar); + // First, record inset id, if cursor is in one UpdatableInset * inset = first->inInset(); LyXText * text = inset ? inset->getLyXText(bv) : bv->text; int const inset_id = inset ? inset->id() : -1; // We simply record the entire outer paragraphs - ParagraphList & plist = buf->paragraphs(); ParIterator null = buf->par_iterator_end(); // First, identify the outer paragraphs @@ -59,8 +69,8 @@ void recordUndo(BufferView * bv, Undo::undo_kind kind, } // And calculate a stable reference to them - int const first_offset = std::distance(plist.begin(), first); - int const last_offset = std::distance(last, plist.end()); + int const first_offset = firstpar; + int const last_offset = plist.size() - lastpar; // Undo::ATOMIC are always recorded (no overlapping there). @@ -87,6 +97,7 @@ void recordUndo(BufferView * bv, Undo::undo_kind kind, cursor_offset, text->cursor.pos(), ParagraphList())); + lyxerr << "G" << endl; // Record the relevant paragraphs ParagraphList & undo_pars = stack.top().pars; @@ -103,7 +114,7 @@ void recordUndo(BufferView * bv, Undo::undo_kind kind, // Returns false if no undo possible. -bool performUndoOrRedo(BufferView * bv, Undo & undo) +bool performUndoOrRedo(BufferView * bv, Undo const & undo) { Buffer * buf = bv->buffer(); ParagraphList & plist = buf->paragraphs(); @@ -141,10 +152,17 @@ bool performUndoOrRedo(BufferView * bv, Undo & undo) LyXText * text = inset ? inset->getLyXText(bv) : bv->text; text->setCursorIntern(undo.cursor_par_offset, undo.cursor_pos); + lyxerr << "undo, inset: " << inset << endl; + if (inset) { + lyxerr << "undo, inset owner: " << inset->owner() << endl; + // Magic needed to update inset internal state FuncRequest cmd(bv, LFUN_INSET_EDIT, "left"); - inset->localDispatch(cmd); + if (inset->owner()) + inset->owner()->localDispatch(cmd); + else + inset->localDispatch(cmd); } // set cursor again to force the position to be the right one @@ -247,24 +265,23 @@ bool textRedo(BufferView * bv) void recordUndo(BufferView * bv, Undo::undo_kind kind, - ParagraphList::iterator first, ParagraphList::iterator last) + ParagraphList & plist, paroffset_type first, paroffset_type last) { if (!undo_frozen) { - recordUndo(bv, kind, first, last, bv->buffer()->undostack()); + recordUndo(bv, kind, plist, first, last, bv->buffer()->undostack()); bv->buffer()->redostack().clear(); } } void recordUndo(BufferView * bv, Undo::undo_kind kind, - ParagraphList::iterator first) + ParagraphList & plist, paroffset_type par) { - recordUndo(bv, kind, first, first); + recordUndo(bv, kind, plist, par, par); } void recordUndo(BufferView * bv, Undo::undo_kind kind) { - recordUndo(bv, kind, bv->text->cursorPar()); + recordUndo(bv, kind, bv->text->ownerParagraphs(), bv->text->cursor.par()); } - diff --git a/src/undo_funcs.h b/src/undo_funcs.h index f34005dca6..96efcb9564 100644 --- a/src/undo_funcs.h +++ b/src/undo_funcs.h @@ -18,6 +18,7 @@ #include "undo.h" #include "ParagraphList_fwd.h" +#include "support/types.h" class BufferView; class Paragraph; @@ -48,10 +49,11 @@ void unFreezeUndo(); * will record the original information of the paragraphs in the undo stack. */ void recordUndo(BufferView *, Undo::undo_kind kind, - ParagraphList::iterator first, ParagraphList::iterator last); + ParagraphList & plist, lyx::paroffset_type first, lyx::paroffset_type last); + /// Convienience: Prepare undo when change in a single paragraph. void recordUndo(BufferView *, Undo::undo_kind kind, - ParagraphList::iterator first); + ParagraphList & plist, lyx::paroffset_type par); /// Convienience: Prepare undo for the paragraph that contains the cursor void recordUndo(BufferView *, Undo::undo_kind kind);