From 17e8d4dfd879b3baccfa77934786be6520ee8f73 Mon Sep 17 00:00:00 2001 From: Allan Rae Date: Sat, 12 Jan 2002 21:03:30 +0000 Subject: [PATCH] Mostly fixed the 'empty paragraph deletion kills the cursor' problem; and initialise a few more vars in tabulars git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3347 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView2.C | 67 +++++++++++++++++++++++++++++++++++++-- src/ChangeLog | 15 +++++++++ src/insets/ChangeLog | 5 +++ src/insets/insettabular.C | 6 ++++ src/lyxtext.h | 8 ++--- src/text2.C | 29 +++++++++-------- 6 files changed, 110 insertions(+), 20 deletions(-) diff --git a/src/BufferView2.C b/src/BufferView2.C index 0eb2b4611c..bbfa04cadf 100644 --- a/src/BufferView2.C +++ b/src/BufferView2.C @@ -110,18 +110,45 @@ bool BufferView::removeAutoInsets() { LyXCursor tmpcursor = text->cursor; Paragraph * cur_par = tmpcursor.par(); + Paragraph * cur_par_prev = cur_par ? cur_par->previous() : 0; + Paragraph * cur_par_next = cur_par ? cur_par->next() : 0; pos_type cur_pos = tmpcursor.pos(); - + bool found = false; + // Trap the deletion of the paragraph the cursor is in. + // It should be almost impossible for the new cursor par to be + // deleted later on in this function. + // This is the way to segfault this now. Although you may have to do this + // multiple times: Have an InsetERT with an unknown command in it. + // View->DVI, move cursor between Error box and InsetERT and hit , + // , again, View->DVI, BANG! + // + while ((cur_par_prev || cur_par_next) + && text->setCursor(this, + cur_par_prev ? cur_par_prev : cur_par_next, + 0)) { + // we just removed cur_par so have to fix the "cursor" + if (cur_par_prev) { + cur_par = cur_par_prev; + cur_pos = cur_par->size(); + } else { + cur_par = cur_par_next; + cur_pos = 0; + } + cur_par_prev = cur_par->previous(); + cur_par_next = cur_par->next(); + } + ParIterator it = buffer()->par_iterator_begin(); ParIterator end = buffer()->par_iterator_end(); for (; it != end; ++it) { Paragraph * par = *it; + Paragraph * par_prev = par ? par->previous() : 0; bool removed = false; - text->setCursor(this, par, 0); - + bool dead = text->setCursor(this, par, 0); + Paragraph::inset_iterator pit = par->inset_iterator_begin(); Paragraph::inset_iterator pend = par->inset_iterator_end(); while (pit != pend) { @@ -142,6 +169,40 @@ bool BufferView::removeAutoInsets() found = true; text->redoParagraph(this); } + if (dead) { + // Error box paragraphs appear to have a bad next_ pointer + // especially when that's all that's in the paragraph.. + // Then if you are in an empty paragraph after an error box + // which is in its own paragraph this will fail because + // cur_prev_par was the one just deleted (I think). + // That's the main reason why this clause makes almost no difference. + // Feel free to delete this whole clause as my brain is asleep now. + while ((cur_par_prev || cur_par_next) + && text->setCursor(this, + cur_par_prev ? cur_par_prev : cur_par_next, + 0)) { + // we just removed cur_par so have to fix the "cursor" + if (cur_par_prev == par) { + // attempting to solve the "prev par was deleted + // because it had only an error inset in it" problem + if (par_prev) { + cur_par = par_prev; + cur_pos = cur_par->size(); + } else { + cur_par = cur_par_next; + cur_pos = 0; + } + } else if (cur_par_prev) { + cur_par = cur_par_prev; + cur_pos = cur_par->size(); + } else { + cur_par = cur_par_next; + cur_pos = 0; + } + cur_par_prev = cur_par->previous(); + cur_par_next = cur_par->next(); + } + } } text->setCursorIntern(this, cur_par, cur_pos); diff --git a/src/ChangeLog b/src/ChangeLog index 9de7590097..0ecf8a48e1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2002-01-13 Allan Rae + + * BufferView2.C (removeAutoInsets): ensure we have a valid cursor if + the old cursor is now invalid due to deleteEmptyParagraphMechanism. + There is still a way to segfault this although you may have to do this + multiple times: Have an InsetERT with an unknown command in it. + View->DVI, move cursor between Error box and InsetERT and hit , + , again, View->DVI, BANG! + + * text2.C (setCursor): + (deleteEmptyParagraphMechanism): + * lyxtext.h (setCursor): + (deleteEmptyParagraphMechanism): return true if the paragraph was deleted. + Making use of the return value may help fix other bugs. + 2002-01-12 Jean-Marc Lasgouttes * LyXAction.[Ch]: move isPseudoAction to the C file, since nobody diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index c3c6f9bd9c..7fa91dc48c 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,8 @@ +2002-01-13 Allan Rae + + * insettabular.C (InsetTabular): Both constructors now initialise + all class variables. + 2002-01-11 Juergen Vigna * insettext.C (insetButtonPress): set the_locking_inset to 0. diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index e748979ca7..32b45f29f1 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -138,6 +138,7 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns) // for now make it always display as display() inset // just for test!!! the_locking_inset = 0; + old_locking_inset = 0; locked = false; oldcell = -1; actrow = actcell = 0; @@ -145,6 +146,8 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns) need_update = INIT; in_update = false; in_reset_pos = false; + inset_x = 0; + inset_y = 0; } @@ -154,6 +157,7 @@ InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf, { tabular.reset(new LyXTabular(this, *(tab.tabular), same_id)); the_locking_inset = 0; + old_locking_inset = 0; locked = false; oldcell = -1; actrow = actcell = 0; @@ -161,6 +165,8 @@ InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf, need_update = INIT; in_update = false; in_reset_pos = false; + inset_x = 0; + inset_y = 0; } diff --git a/src/lyxtext.h b/src/lyxtext.h index 8c6114ea62..f80c84b7d0 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -306,8 +306,8 @@ public: string const selectNextWordToSpellcheck(BufferView *, float & value) const; /// void selectSelectedWord(BufferView *); - /// - void setCursor(BufferView *, Paragraph * par, + /// returns true if par was empty and was removed + bool setCursor(BufferView *, Paragraph * par, lyx::pos_type pos, bool setfont = true, bool boundary = false) const; @@ -612,8 +612,8 @@ private: LyXCursor & cur, LyXCursor const & where) const; - /// delete double space or empty paragraphs around old_cursor - void deleteEmptyParagraphMechanism(BufferView *, + /// delete double space (false) or empty paragraphs (true) around old_cursor + bool deleteEmptyParagraphMechanism(BufferView *, LyXCursor const & old_cursor) const; public: diff --git a/src/text2.C b/src/text2.C index 2437cf1570..ce0fe04a3a 100644 --- a/src/text2.C +++ b/src/text2.C @@ -2090,13 +2090,13 @@ bool LyXText::updateInset(BufferView * bview, Inset * inset) } -void LyXText::setCursor(BufferView * bview, Paragraph * par, +bool LyXText::setCursor(BufferView * bview, Paragraph * par, pos_type pos, bool setfont, bool boundary) const { LyXCursor old_cursor = cursor; setCursorIntern(bview, par, pos, setfont, boundary); - deleteEmptyParagraphMechanism(bview, old_cursor); + return deleteEmptyParagraphMechanism(bview, old_cursor); } @@ -2373,21 +2373,19 @@ void LyXText::fixCursorAfterDelete(BufferView * bview, } -void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, +bool LyXText::deleteEmptyParagraphMechanism(BufferView * bview, LyXCursor const & old_cursor) const { // Would be wrong to delete anything if we have a selection. - if (selection.set()) return; + if (selection.set()) return false; // We allow all kinds of "mumbo-jumbo" when freespacing. if (textclasslist.Style(bview->buffer()->params.textclass, old_cursor.par()->getLayout()).free_spacing || old_cursor.par()->isFreeSpacing()) { - return; + return false; } - - bool deleted = false; /* Ok I'll put some comments here about what is missing. I have fixed BackSpace (and thus Delete) to not delete @@ -2442,23 +2440,27 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, fixCursorAfterDelete(bview, toggle_cursor, old_cursor); fixCursorAfterDelete(bview, toggle_end_cursor, old_cursor); - return; + return false; } } // don't delete anything if this is the ONLY paragraph! if (!old_cursor.par()->next() && !old_cursor.par()->previous()) - return; + return false; // Do not delete empty paragraphs with keepempty set. if ((textclasslist.Style(bview->buffer()->params.textclass, old_cursor.par()->getLayout())).keepempty) - return; + return false; // only do our magic if we changed paragraph if (old_cursor.par() == cursor.par()) - return; + return false; + // record if we have deleted a paragraph + // we can't possibly have deleted a paragraph before this point + bool deleted = false; + if ((old_cursor.par()->size() == 0 || (old_cursor.par()->size() == 1 && old_cursor.par()->isLineSeparator(0)))) { @@ -2488,7 +2490,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, if (ownerParagraph() == old_cursor.par()) { ownerParagraph(ownerParagraph()->next()); } - // delete old par + // delete old par delete old_cursor.par(); /* Breakagain the next par. Needed because of @@ -2538,7 +2540,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, setCursorIntern(bview, cursor.par(), cursor.pos()); if (selection.cursor.par() == old_cursor.par() - && selection.cursor.pos() == selection.cursor.pos()) { + && selection.cursor.pos() == old_cursor.pos()) { // correct selection selection.cursor = cursor; } @@ -2552,6 +2554,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, selection.cursor = cursor; } } + return deleted; }