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
This commit is contained in:
Allan Rae 2002-01-12 21:03:30 +00:00
parent 8b8741cd5d
commit 17e8d4dfd8
6 changed files with 110 additions and 20 deletions

View File

@ -110,17 +110,44 @@ bool BufferView::removeAutoInsets()
{ {
LyXCursor tmpcursor = text->cursor; LyXCursor tmpcursor = text->cursor;
Paragraph * cur_par = tmpcursor.par(); 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(); pos_type cur_pos = tmpcursor.pos();
bool found = false; 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 <Enter>,
// <down-arrow>, <Enter> 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 it = buffer()->par_iterator_begin();
ParIterator end = buffer()->par_iterator_end(); ParIterator end = buffer()->par_iterator_end();
for (; it != end; ++it) { for (; it != end; ++it) {
Paragraph * par = *it; Paragraph * par = *it;
Paragraph * par_prev = par ? par->previous() : 0;
bool removed = false; 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 pit = par->inset_iterator_begin();
Paragraph::inset_iterator pend = par->inset_iterator_end(); Paragraph::inset_iterator pend = par->inset_iterator_end();
@ -142,6 +169,40 @@ bool BufferView::removeAutoInsets()
found = true; found = true;
text->redoParagraph(this); 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); text->setCursorIntern(this, cur_par, cur_pos);

View File

@ -1,3 +1,18 @@
2002-01-13 Allan Rae <rae@lyx.org>
* 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 <Enter>,
<down-arrow>, <Enter> 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 <lasgouttes@freesurf.fr> 2002-01-12 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
* LyXAction.[Ch]: move isPseudoAction to the C file, since nobody * LyXAction.[Ch]: move isPseudoAction to the C file, since nobody

View File

@ -1,3 +1,8 @@
2002-01-13 Allan Rae <rae@lyx.org>
* insettabular.C (InsetTabular): Both constructors now initialise
all class variables.
2002-01-11 Juergen Vigna <jug@sad.it> 2002-01-11 Juergen Vigna <jug@sad.it>
* insettext.C (insetButtonPress): set the_locking_inset to 0. * insettext.C (insetButtonPress): set the_locking_inset to 0.

View File

@ -138,6 +138,7 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
// for now make it always display as display() inset // for now make it always display as display() inset
// just for test!!! // just for test!!!
the_locking_inset = 0; the_locking_inset = 0;
old_locking_inset = 0;
locked = false; locked = false;
oldcell = -1; oldcell = -1;
actrow = actcell = 0; actrow = actcell = 0;
@ -145,6 +146,8 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
need_update = INIT; need_update = INIT;
in_update = false; in_update = false;
in_reset_pos = 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)); tabular.reset(new LyXTabular(this, *(tab.tabular), same_id));
the_locking_inset = 0; the_locking_inset = 0;
old_locking_inset = 0;
locked = false; locked = false;
oldcell = -1; oldcell = -1;
actrow = actcell = 0; actrow = actcell = 0;
@ -161,6 +165,8 @@ InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf,
need_update = INIT; need_update = INIT;
in_update = false; in_update = false;
in_reset_pos = false; in_reset_pos = false;
inset_x = 0;
inset_y = 0;
} }

View File

@ -306,8 +306,8 @@ public:
string const selectNextWordToSpellcheck(BufferView *, float & value) const; string const selectNextWordToSpellcheck(BufferView *, float & value) const;
/// ///
void selectSelectedWord(BufferView *); void selectSelectedWord(BufferView *);
/// /// returns true if par was empty and was removed
void setCursor(BufferView *, Paragraph * par, bool setCursor(BufferView *, Paragraph * par,
lyx::pos_type pos, lyx::pos_type pos,
bool setfont = true, bool setfont = true,
bool boundary = false) const; bool boundary = false) const;
@ -612,8 +612,8 @@ private:
LyXCursor & cur, LyXCursor & cur,
LyXCursor const & where) const; LyXCursor const & where) const;
/// delete double space or empty paragraphs around old_cursor /// delete double space (false) or empty paragraphs (true) around old_cursor
void deleteEmptyParagraphMechanism(BufferView *, bool deleteEmptyParagraphMechanism(BufferView *,
LyXCursor const & old_cursor) const; LyXCursor const & old_cursor) const;
public: public:

View File

@ -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, pos_type pos,
bool setfont, bool boundary) const bool setfont, bool boundary) const
{ {
LyXCursor old_cursor = cursor; LyXCursor old_cursor = cursor;
setCursorIntern(bview, par, pos, setfont, boundary); setCursorIntern(bview, par, pos, setfont, boundary);
deleteEmptyParagraphMechanism(bview, old_cursor); return deleteEmptyParagraphMechanism(bview, old_cursor);
} }
@ -2373,22 +2373,20 @@ void LyXText::fixCursorAfterDelete(BufferView * bview,
} }
void LyXText::deleteEmptyParagraphMechanism(BufferView * bview, bool LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
LyXCursor const & old_cursor) const LyXCursor const & old_cursor) const
{ {
// Would be wrong to delete anything if we have a selection. // 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. // We allow all kinds of "mumbo-jumbo" when freespacing.
if (textclasslist.Style(bview->buffer()->params.textclass, if (textclasslist.Style(bview->buffer()->params.textclass,
old_cursor.par()->getLayout()).free_spacing old_cursor.par()->getLayout()).free_spacing
|| old_cursor.par()->isFreeSpacing()) || old_cursor.par()->isFreeSpacing())
{ {
return; return false;
} }
bool deleted = false;
/* Ok I'll put some comments here about what is missing. /* Ok I'll put some comments here about what is missing.
I have fixed BackSpace (and thus Delete) to not delete I have fixed BackSpace (and thus Delete) to not delete
double-spaces automagically. I have also changed Cut, double-spaces automagically. I have also changed Cut,
@ -2442,22 +2440,26 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
fixCursorAfterDelete(bview, toggle_cursor, old_cursor); fixCursorAfterDelete(bview, toggle_cursor, old_cursor);
fixCursorAfterDelete(bview, toggle_end_cursor, fixCursorAfterDelete(bview, toggle_end_cursor,
old_cursor); old_cursor);
return; return false;
} }
} }
// don't delete anything if this is the ONLY paragraph! // don't delete anything if this is the ONLY paragraph!
if (!old_cursor.par()->next() && !old_cursor.par()->previous()) if (!old_cursor.par()->next() && !old_cursor.par()->previous())
return; return false;
// Do not delete empty paragraphs with keepempty set. // Do not delete empty paragraphs with keepempty set.
if ((textclasslist.Style(bview->buffer()->params.textclass, if ((textclasslist.Style(bview->buffer()->params.textclass,
old_cursor.par()->getLayout())).keepempty) old_cursor.par()->getLayout())).keepempty)
return; return false;
// only do our magic if we changed paragraph // only do our magic if we changed paragraph
if (old_cursor.par() == cursor.par()) 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 if ((old_cursor.par()->size() == 0
|| (old_cursor.par()->size() == 1 || (old_cursor.par()->size() == 1
@ -2488,7 +2490,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
if (ownerParagraph() == old_cursor.par()) { if (ownerParagraph() == old_cursor.par()) {
ownerParagraph(ownerParagraph()->next()); ownerParagraph(ownerParagraph()->next());
} }
// delete old par // delete old par
delete old_cursor.par(); delete old_cursor.par();
/* Breakagain the next par. Needed because of /* Breakagain the next par. Needed because of
@ -2538,7 +2540,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
setCursorIntern(bview, cursor.par(), cursor.pos()); setCursorIntern(bview, cursor.par(), cursor.pos());
if (selection.cursor.par() == old_cursor.par() if (selection.cursor.par() == old_cursor.par()
&& selection.cursor.pos() == selection.cursor.pos()) { && selection.cursor.pos() == old_cursor.pos()) {
// correct selection // correct selection
selection.cursor = cursor; selection.cursor = cursor;
} }
@ -2552,6 +2554,7 @@ void LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
selection.cursor = cursor; selection.cursor = cursor;
} }
} }
return deleted;
} }