>>>>> "Jean-Marc" == Jean-Marc Lasgouttes <[EMAIL PROTECTED]> writes:
Jean-Marc> Basically, dEPM compares the tips of cursors without caring Jean-Marc> whether they are at same depth (insert apples and oranges Jean-Marc> comment here). Here undo is called between two cursors at Jean-Marc> different depth :( Jean-Marc> This is a real mess. I can confirm that last sentence. The following patch does a cleanup of dEPM in the following respects: 1/ call recordUndo with the right cursor, and only for the pit contains `old' (this is the only paragraph we change) 2/ when comparing cursors, do not compare pit:s without first checking that they are relative to the same inset 3/ when a paragraph has been removed,try to update the right slice of `cur', which might not be the top. 4/ simplify the code to the point where I understand it. The result of this patch is that I do not get a crash in dEPM any more with the following (description courtesy of Bennett): > Type some arbitrary text. Below this, create an inset in a paragraph > all by itself; set this paragraph to have no indentation. Place the > cursor at the end of the line immediately above the inset. Press > return to create a new paragraph, and then down-arrow: crash. However, I still get a crash in fitCursor() :( The relevant backtrace is: 0x0819ee76 in LCursor::getFont (this=0x883ee74) at cursor_slice.h:103 103 LyXText const * text() const { return inset_->getText(idx_); } (gdb) bt #0 0x0819ee76 in LCursor::getFont (this=0x883ee74) at cursor_slice.h:103 #1 0x0806d5c1 in BufferView::Pimpl::fitCursor (this=0x883ed60) at ../../lyx-devel/src/BufferView_pimpl.C:634 #2 0x0806d852 in BufferView::Pimpl::update (this=0x883ed60, flags=143432372) at BufferView.h:52 #3 0x08066a7b in BufferView::update (this=0x88c9ab4, flags=3) at ../../lyx-devel/src/BufferView.C:146 #4 0x0821aa33 in LyXFunc::dispatch (this=0x883a028, [EMAIL PROTECTED]) at BufferView.h:47 #5 0x08215271 in LyXFunc::processKeySym (this=0x883a028, keysym= {px = 0x8843778, pn = {pi_ = 0x88daa20}}, state=key_modifier::none) at ../../lyx-devel/src/lyxfunc.C:326 #6 0x0806d288 in BufferView::Pimpl::workAreaKeyPress (this=0x883ed60, key=Cannot access memory at address 0x1 ) at LyXView.h:83 I really cannot make sense of it. Martin, Help!!! Here is the patch FWIW. I still think it would be worth committing it. JMarc
Index: src/ChangeLog =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v retrieving revision 1.2306 diff -u -p -r1.2306 ChangeLog --- src/ChangeLog 18 Oct 2005 13:34:50 -0000 1.2306 +++ src/ChangeLog 19 Oct 2005 15:43:59 -0000 @@ -1,5 +1,12 @@ 2005-10-18 Jean-Marc Lasgouttes <[EMAIL PROTECTED]> + * text2.C (deleteEmptyParagraphMechanism): compare also containing + insets when comparing pit/pos; pass the right cursor to + recordUndo; when a paragraph has been deleted, compare `old.top()' to + the right cursor slice of `cur'; general cleanup. + +2005-10-18 Jean-Marc Lasgouttes <[EMAIL PROTECTED]> + * messages.C: do not forget to include <cerrno>. 2005-10-12 Jürgen Spitzmüller <[EMAIL PROTECTED]> Index: src/lyxtext.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxtext.h,v retrieving revision 1.328 diff -u -p -r1.328 lyxtext.h --- src/lyxtext.h 13 Oct 2005 14:48:24 -0000 1.328 +++ src/lyxtext.h 19 Oct 2005 15:43:59 -0000 @@ -373,7 +373,7 @@ private: void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where); /// delete double space or empty paragraphs around old cursor - bool deleteEmptyParagraphMechanism(LCursor & cur, LCursor const & old); + bool deleteEmptyParagraphMechanism(LCursor & cur, LCursor & old); /// void deleteWordForward(LCursor & cur); Index: src/text2.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text2.C,v retrieving revision 1.633 diff -u -p -r1.633 text2.C --- src/text2.C 13 Oct 2005 14:48:26 -0000 1.633 +++ src/text2.C 19 Oct 2005 15:43:59 -0000 @@ -1119,7 +1119,6 @@ bool LyXText::cursorDown(LCursor & cur) cur = dummy; return changed; - } bool updateNeeded = false; @@ -1181,14 +1180,17 @@ void LyXText::fixCursorAfterDelete(Curso } -bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor const & old) +bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor & old) { // Would be wrong to delete anything if we have a selection. if (cur.selection()) return false; //lyxerr[Debug::DEBUG] << "DEPM: cur:\n" << cur << "old:\n" << old << endl; - Paragraph const & oldpar = pars_[old.pit()]; + // old should point to us + BOOST_ASSERT(old.text() == this); + + Paragraph & oldpar = old.paragraph(); // We allow all kinds of "mumbo-jumbo" when freespacing. if (oldpar.isFreeSpacing()) @@ -1217,9 +1219,12 @@ bool LyXText::deleteEmptyParagraphMechan // delete the LineSeparator. // MISSING - // If the chars around the old cursor were spaces, delete one of them. - if (old.pit() != cur.pit() || old.pos() != cur.pos()) { + bool const same_inset = &old.inset() == &cur.inset(); + bool const same_par = same_inset && old.pit() == cur.pit(); + bool const same_par_pos = same_par && old.pos() == cur.pos(); + // If the chars around the old cursor were spaces, delete one of them. + if (!same_par_pos) { // Only if the cursor has really moved. if (old.pos() > 0 && old.pos() < oldpar.size() @@ -1228,9 +1233,8 @@ bool LyXText::deleteEmptyParagraphMechan && oldpar.lookupChange(old.pos() - 1) != Change::DELETED) { // We need to set the text to Change::INSERTED to // get it erased properly - pars_[old.pit()].setChange(old.pos() -1, - Change::INSERTED); - pars_[old.pit()].erase(old.pos() - 1); + oldpar.setChange(old.pos() -1, Change::INSERTED); + oldpar.erase(old.pos() - 1); #ifdef WITH_WARNINGS #warning This will not work anymore when we have multiple views of the same buffer // In this case, we will have to correct also the cursors held by @@ -1238,68 +1242,46 @@ bool LyXText::deleteEmptyParagraphMechan // automated way in CursorSlice code. (JMarc 26/09/2001) #endif // correct all cursor parts - fixCursorAfterDelete(cur.top(), old.top()); -#ifdef WITH_WARNINGS -#warning DEPM, look here -#endif - //fixCursorAfterDelete(cur.anchor(), old.top()); + if (same_par) { + fixCursorAfterDelete(cur.top(), old.top()); + cur.resetAnchor(); + } return true; } } // only do our magic if we changed paragraph - if (old.pit() == cur.pit()) + if (same_par) return false; // don't delete anything if this is the ONLY paragraph! - if (pars_.size() == 1) + if (old.lastpit() == 0) return false; // Do not delete empty paragraphs with keepempty set. if (oldpar.allowEmpty()) return false; - // record if we have deleted a paragraph - // we can't possibly have deleted a paragraph before this point - bool deleted = false; - if (oldpar.empty() || (oldpar.size() == 1 && oldpar.isLineSeparator(0))) { - // ok, we will delete something - deleted = true; - - bool selection_position_was_oldcursor_position = - cur.anchor().pit() == old.pit() && cur.anchor().pos() == old.pos(); - - // This is a bit of a overkill. We change the old and the cur par - // at max, certainly not everything in between... - recUndo(old.pit(), cur.pit()); - // Delete old par. - pars_.erase(pars_.begin() + old.pit()); - - // Update cursor par offset if necessary. - // Some 'iterator registration' would be nice that takes care of - // such events. Maybe even signal/slot? - if (cur.pit() > old.pit()) - --cur.pit(); -#ifdef WITH_WARNINGS -#warning DEPM, look here -#endif -// if (cur.anchor().pit() > old.pit()) -// --cur.anchor().pit(); - - if (selection_position_was_oldcursor_position) { - // correct selection - cur.resetAnchor(); + recordUndo(old, Undo::ATOMIC, old.pit()); + ParagraphList & plist = old.text()->paragraphs(); + plist.erase(plist.begin() + old.pit()); + + // see #warning above + if (cur.depth() >= old.depth()) { + CursorSlice & curslice = cur[old.depth() - 1]; + if (&curslice.inset() == &old.inset() + && curslice.pit() > old.pit()) { + --curslice.pit(); + cur.resetAnchor(); + } } - } - - if (deleted) { - updateCounters(cur.buffer()); + updateCounters(old.buffer()); return true; } - if (pars_[old.pit()].stripLeadingSpaces()) + if (oldpar.stripLeadingSpaces()) cur.resetAnchor(); return false;