mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-26 11:16:55 +00:00
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:
parent
8b8741cd5d
commit
17e8d4dfd8
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
29
src/text2.C
29
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,
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user