mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
fix crash with DEPM when the cursor goes in a deeper inset
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@10573 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
b1cda27e0a
commit
8679982264
@ -1,3 +1,14 @@
|
||||
2005-10-24 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
|
||||
|
||||
* dociterator.C (updateInsets): new method. Updates the inset_
|
||||
cache of all the slices of the iterator.
|
||||
|
||||
* 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'; use updateInsets on cur to make
|
||||
sure that the inset caches are correct; general cleanup.
|
||||
|
||||
2005-10-21 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
|
||||
|
||||
* text3.C (dispatch): LFUN_NEXT_INSET_TOGGLE: first try to
|
||||
|
@ -490,6 +490,25 @@ bool DocIterator::hasPart(DocIterator const & it) const
|
||||
}
|
||||
|
||||
|
||||
void DocIterator::updateInsets(InsetBase * inset)
|
||||
{
|
||||
// this function re-creates the cache of inset pointers.
|
||||
// code taken in part from StableDocIterator::asDocIterator.
|
||||
//lyxerr << "converting:\n" << *this << endl;
|
||||
DocIterator dit = DocIterator(*inset);
|
||||
size_t const n = slices_.size();
|
||||
for (size_t i = 0 ; i < n; ++i) {
|
||||
BOOST_ASSERT(inset);
|
||||
dit.push_back(slices_[i]);
|
||||
dit.top().inset_ = inset;
|
||||
if (i + 1 != n)
|
||||
inset = dit.nextInset();
|
||||
}
|
||||
//lyxerr << "converted:\n" << *this << endl;
|
||||
operator=(dit);
|
||||
}
|
||||
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, DocIterator const & dit)
|
||||
{
|
||||
for (size_t i = 0, n = dit.depth(); i != n; ++i)
|
||||
|
@ -214,6 +214,9 @@ public:
|
||||
void push_back(CursorSlice const & sl) { slices_.push_back(sl); }
|
||||
///
|
||||
void pop_back() { slices_.pop_back(); }
|
||||
/// recompute the inset parts of the cursor from the document data
|
||||
void updateInsets(InsetBase * inset);
|
||||
|
||||
private:
|
||||
/**
|
||||
* When the cursor position is i, is the cursor after the i-th char
|
||||
|
@ -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);
|
||||
|
93
src/text2.C
93
src/text2.C
@ -1119,7 +1119,6 @@ bool LyXText::cursorDown(LCursor & cur)
|
||||
cur = dummy;
|
||||
|
||||
return changed;
|
||||
|
||||
}
|
||||
|
||||
bool updateNeeded = false;
|
||||
@ -1181,32 +1180,29 @@ void LyXText::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where)
|
||||
}
|
||||
|
||||
|
||||
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())
|
||||
return false;
|
||||
|
||||
/* Ok I'll put some comments here about what is missing.
|
||||
I have fixed BackSpace (and thus Delete) to not delete
|
||||
double-spaces automagically. I have also changed Cut,
|
||||
Copy and Paste to hopefully do some sensible things.
|
||||
There are still some small problems that can lead to
|
||||
double spaces stored in the document file or space at
|
||||
the beginning of paragraphs(). This happens if you have
|
||||
the cursor between to spaces and then save. Or if you
|
||||
cut and paste and the selection have a space at the
|
||||
beginning and then save right after the paste. I am
|
||||
sure none of these are very hard to fix, but I will
|
||||
put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
|
||||
that I can get some feedback. (Lgb)
|
||||
beginning and then save right after the paste. (Lgb)
|
||||
*/
|
||||
|
||||
// If old.pos() == 0 and old.pos()(1) == LineSeparator
|
||||
@ -1217,9 +1213,12 @@ bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor const & old)
|
||||
// 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 +1227,8 @@ bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor const & old)
|
||||
&& 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 +1236,51 @@ bool LyXText::deleteEmptyParagraphMechanism(LCursor & cur, LCursor const & old)
|
||||
// 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());
|
||||
recordUndo(old, Undo::ATOMIC, old.pit());
|
||||
ParagraphList & plist = old.text()->paragraphs();
|
||||
plist.erase(plist.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();
|
||||
// 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();
|
||||
// since a paragraph has been deleted, all the
|
||||
// insets after `old' have been copied and
|
||||
// their address has changed. Therefore we
|
||||
// need to `regenerate' cur. (JMarc)
|
||||
cur.updateInsets(&(cur.bottom().inset()));
|
||||
cur.resetAnchor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deleted) {
|
||||
updateCounters(cur.buffer());
|
||||
updateCounters(old.buffer());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pars_[old.pit()].stripLeadingSpaces())
|
||||
if (oldpar.stripLeadingSpaces())
|
||||
cur.resetAnchor();
|
||||
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user