On Wed, Mar 12, 2003 at 11:35:16AM +0100, Alfredo Braunstein wrote: > > I'm making a minimal kill-depm right now.
Here it is (I'm still building it, but more testers would be great !) john Index: BufferView.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView.C,v retrieving revision 1.125 diff -u -p -r1.125 BufferView.C --- BufferView.C 12 Mar 2003 05:46:32 -0000 1.125 +++ BufferView.C 12 Mar 2003 10:58:46 -0000 @@ -334,135 +334,50 @@ bool BufferView::insertLyXFile(string co bool BufferView::removeAutoInsets() { - // keep track of which pos and par the cursor was on - Paragraph * cursor_par = text->cursor.par(); - Paragraph * cursor_par_prev = cursor_par ? cursor_par->previous() : 0; - Paragraph * cursor_par_next = cursor_par ? cursor_par->next() : 0; - pos_type cursor_pos = text->cursor.pos(); - bool found = false; - // Trap the deletion of the paragraph the cursor is in. - // Iterate until we find a paragraph that won't be immediately deleted. - // In reality this should mean we only execute the body of the while - // loop once at most. However for safety we iterate rather than just - // make this an if () conditional. - while ((cursor_par_prev || cursor_par_next) - && text->setCursor(this, - cursor_par_prev ? cursor_par_prev : cursor_par_next, - 0)) { - // We just removed cursor_par so have to fix the "cursor" - if (cursor_par_prev) { - // '.' = cursor_par - // a -> a. - // . - cursor_par = cursor_par_prev; - cursor_pos = cursor_par->size(); - } else { - // . -> .a - // a - cursor_par = cursor_par_next; - cursor_pos = 0; - } - cursor_par_prev = cursor_par->previous(); - cursor_par_next = cursor_par->next(); - } - // Iterate through the paragraphs removing autoDelete insets as we go. - // If the paragraph ends up empty after all the autoDelete insets are - // removed that paragraph will be removed by the next setCursor() call. 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; - - if (text->setCursor(this, par, 0) - && cursor_par == par_prev) { - // The previous setCursor line was deleted and that - // was the cursor_par line. This can only happen if an - // error box was the sole item on cursor_par. - // It is possible for cursor_par_prev to be stray if - // the line it pointed to only had a error box on it - // so we have to set it to a known correct value. - // This is often the same value it already had. - cursor_par_prev = par->previous(); - if (cursor_par_prev) { - // '|' = par, '.' = cursor_par, 'E' = error box - // First step below may occur before while{} - // a |a a a a. - // E -> .E -> |.E -> . -> |b - // . b b |b - // b - cursor_par = cursor_par_prev; - cursor_pos = cursor_par_prev->size(); - cursor_par_prev = cursor_par->previous(); - // cursor_par_next remains the same - } else if (cursor_par_next) { - // First step below may occur before while{} - // . - // E -> |.E -> |. -> . -> .|a - // a a a |a - cursor_par = cursor_par_next; - cursor_pos = 0; - // cursor_par_prev remains unset - cursor_par_next = cursor_par->next(); - } else { - // I can't find a way to trigger this - // so it should be unreachable code - // unless the buffer is corrupted. - lyxerr << "BufferView::removeAutoInsets() is bad\n"; - } - } InsetList::iterator pit = par->insetlist.begin(); InsetList::iterator pend = par->insetlist.end(); + bool removed = false; + while (pit != pend) { - if (pit.getInset()->autoDelete()) { - removed = true; - pos_type const pos = pit.getPos(); - - par->erase(pos); - // We just invalidated par's inset iterators so - // we get the next valid iterator position - pit = par->insetlist.insetIterator(pos); - // and ensure we have a valid end iterator. - pend = par->insetlist.end(); - - if (cursor_par == par) { - // update the saved cursor position - if (cursor_pos > pos) - --cursor_pos; - } - } else { + if (!pit.getInset()->autoDelete()) { ++pit; + continue; } + + pos_type const pos = pit.getPos(); + + par->erase(pos); + removed = true; + found = true; + + // We just invalidated par's inset iterators so + // we get the next valid iterator position + // FIXME: erase should return the next iterator like STL + pit = par->insetlist.insetIterator(pos); + + // and ensure we have a valid end iterator. + pend = par->insetlist.end(); + + ++pit; } + if (removed) { - found = true; + // don't leave cursor in an impossible position + if (par == text->cursor.par()) + text->cursor.pos(0); + text->redoParagraph(this); } } - - // It is possible that the last line is empty if it was cursor_par - // and/or only had an error inset on it. So we set the cursor to the - // start of the doc to force its removal and ensure a valid saved cursor - if (text->setCursor(this, text->ownerParagraph(), 0) - && 0 == cursor_par_next) { - cursor_par = cursor_par_prev; - cursor_pos = cursor_par->size(); - } else if (cursor_pos > cursor_par->size()) { - // Some C-Enter lines were removed by the setCursor call which - // then invalidated cursor_pos. It could still be "wrong" because - // the cursor may appear to have jumped but since we collapsed - // some C-Enter lines this should be a reasonable compromise. - cursor_pos = cursor_par->size(); - } - - // restore the original cursor in its corrected location. - text->setCursorIntern(this, cursor_par, cursor_pos); return found; } Index: lyxtext.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxtext.h,v retrieving revision 1.139 diff -u -p -r1.139 lyxtext.h --- lyxtext.h 10 Mar 2003 00:05:05 -0000 1.139 +++ lyxtext.h 12 Mar 2003 10:58:47 -0000 @@ -306,7 +306,7 @@ public: /// void selectSelectedWord(BufferView *); /// returns true if par was empty and was removed - bool setCursor(BufferView *, Paragraph * par, + void setCursor(BufferView *, Paragraph * par, lyx::pos_type pos, bool setfont = true, bool boundary = false) const; @@ -536,14 +536,13 @@ private: void setHeightOfRow(BufferView *, Row * row_ptr) const; // fix the cursor `cur' after a characters has been deleted at `where' - // position. Called by deleteEmptyParagraphMechanism + // position. Called by deleteExtraSpaces void fixCursorAfterDelete(BufferView * bv, LyXCursor & cur, LyXCursor const & where) const; - /// delete double space (false) or empty paragraphs (true) around old_cursor - bool deleteEmptyParagraphMechanism(BufferView *, - LyXCursor const & old_cursor) const; + /// delete double spaces + void deleteExtraSpaces(BufferView *, LyXCursor const & old_cursor) const; public: /** Updates all counters starting BEHIND the row. Changed paragraphs Index: paragraph.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/paragraph.C,v retrieving revision 1.249 diff -u -p -r1.249 paragraph.C --- paragraph.C 12 Mar 2003 06:53:49 -0000 1.249 +++ paragraph.C 12 Mar 2003 10:58:50 -0000 @@ -24,6 +24,7 @@ #include "ParameterStruct.h" #include "gettext.h" #include "changes.h" +#include "paragraph_funcs.h" #include "insets/insetbibitem.h" #include "insets/insetoptarg.h" @@ -146,6 +147,9 @@ void Paragraph::write(Buffer const * buf BufferParams const & bparams, depth_type & dth) const { + if (ignorePar(*this)) + return; + // The beginning or end of a deeper (i.e. nested) area? if (dth != params().depth()) { if (params().depth() > dth) { Index: paragraph_funcs.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/paragraph_funcs.C,v retrieving revision 1.18 diff -u -p -r1.18 paragraph_funcs.C --- paragraph_funcs.C 10 Mar 2003 17:49:24 -0000 1.18 +++ paragraph_funcs.C 12 Mar 2003 10:58:53 -0000 @@ -714,3 +714,12 @@ void latexParagraphs(Buffer const * buf, texrow.newline(); } } + + +bool ignorePar(Paragraph const & par) +{ + if (!par.empty()) + return false; + + return !par.layout()->free_spacing && !par.isFreeSpacing(); +} Index: paragraph_funcs.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/paragraph_funcs.h,v retrieving revision 1.13 diff -u -p -r1.13 paragraph_funcs.h --- paragraph_funcs.h 10 Mar 2003 17:49:24 -0000 1.13 +++ paragraph_funcs.h 12 Mar 2003 10:58:53 -0000 @@ -86,4 +86,7 @@ void latexParagraphs(Buffer const * buf, TexRow & texrow, bool moving_arg = false); +/// Return true if this paragraph should not be saved/exported +bool ignorePar(Paragraph const & par); + #endif // PARAGRAPH_FUNCS_H Index: text.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text.C,v retrieving revision 1.307 diff -u -p -r1.307 text.C --- text.C 11 Mar 2003 15:01:27 -0000 1.307 +++ text.C 12 Mar 2003 10:58:59 -0000 @@ -178,30 +178,6 @@ unsigned char LyXText::transformChar(uns } } -// This is the comments that some of the warnings below refers to. -// There are some issues in this file and I don't think they are -// really related to the FIX_DOUBLE_SPACE patch. I'd rather think that -// this is a problem that has been here almost from day one and that a -// larger userbase with differenct access patters triggers the bad -// behaviour. (segfaults.) What I think happen is: In several places -// we store the paragraph in the current cursor and then moves the -// cursor. This movement of the cursor will delete paragraph at the -// old position if it is now empty. This will make the temporary -// pointer to the old cursor paragraph invalid and dangerous to use. -// And is some cases this will trigger a segfault. I have marked some -// of the cases where this happens with a warning, but I am sure there -// are others in this file and in text2.C. There is also a note in -// Delete() that you should read. In Delete I store the paragraph->id -// instead of a pointer to the paragraph. I am pretty sure this faulty -// use of temporary pointers to paragraphs that might have gotten -// invalidated (through a cursor movement) before they are used, are -// the cause of the strange crashes we get reported often. -// -// It is very tiresom to change this code, especially when it is as -// hard to read as it is. Help to fix all the cases where this is done -// would be greately appreciated. -// -// Lgb int LyXText::singleWidth(BufferView * bview, Paragraph * par, pos_type pos) const @@ -2390,26 +2366,13 @@ void LyXText::Delete(BufferView * bview) // just move to the right cursorRight(bview); - // CHECK Look at the comment here. - // This check is not very good... - // The cursorRightIntern calls DeleteEmptyParagrapgMechanism - // and that can very well delete the par or par->previous in - // old_cursor. Will a solution where we compare paragraph id's - //work better? - if ((cursor.par()->previous() ? cursor.par()->previous()->id() : -1) - == old_cur_par_prev_id - && cursor.par()->id() != old_cur_par_id) { - // delete-empty-paragraph-mechanism has done it - return; - } - // if you had success make a backspace if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) { LyXCursor tmpcursor = cursor; // to make sure undo gets the right cursor position cursor = old_cursor; setUndo(bview, Undo::DELETE, - cursor.par(), cursor.par()->next()); + cursor.par(), cursor.par()->next()); cursor = tmpcursor; backspace(bview); } @@ -2432,41 +2395,6 @@ void LyXText::backspace(BufferView * bvi if (cursor.par()->isChangeEdited(0, cursor.par()->size())) return; - // we may paste some paragraphs - - // is it an empty paragraph? - - if ((lastpos == 0 - || (lastpos == 1 && cursor.par()->isSeparator(0)))) { - // This is an empty paragraph and we delete it just by moving the cursor one step - // left and let the DeleteEmptyParagraphMechanism handle the actual deletion - // of the paragraph. - - if (cursor.par()->previous()) { - Paragraph * tmppar = cursor.par()->previous(); - if (cursor.par()->layout() == tmppar->layout() - && cursor.par()->getAlign() == tmppar->getAlign()) { - // Inherit bottom DTD from the paragraph below. - // (the one we are deleting) - tmppar->params().lineBottom(cursor.par()->params().lineBottom()); - tmppar->params().spaceBottom(cursor.par()->params().spaceBottom()); - tmppar->params().pagebreakBottom(cursor.par()->params().pagebreakBottom()); - } - - cursorLeft(bview); - - // the layout things can change the height of a row ! - int const tmpheight = cursor.row()->height(); - setHeightOfRow(bview, cursor.row()); - if (cursor.row()->height() != tmpheight) { - refresh_y = cursor.y() - cursor.row()->baseline(); - refresh_row = cursor.row(); - status(bview, LyXText::NEED_MORE_REFRESH); - } - return; - } - } - if (cursor.par()->previous()) { setUndo(bview, Undo::DELETE, cursor.par()->previous(), cursor.par()->next()); @@ -2475,12 +2403,8 @@ void LyXText::backspace(BufferView * bvi Paragraph * tmppar = cursor.par(); Row * tmprow = cursor.row(); - // We used to do cursorLeftIntern() here, but it is - // not a good idea since it triggers the auto-delete - // mechanism. So we do a cursorLeftIntern()-lite, - // without the dreaded mechanism. (JMarc) + // step to the end of the previous paragraph if (cursor.par()->previous()) { - // steps into the above paragraph. setCursorIntern(bview, cursor.par()->previous(), cursor.par()->previous()->size(), false); @@ -2519,14 +2443,6 @@ void LyXText::backspace(BufferView * bvi refresh_row = cursor.row(); refresh_y = cursor.y() - cursor.row()->baseline(); - // remove the lost paragraph - // This one is not safe, since the paragraph that the tmprow and the - // following rows belong to has been deleted by the PasteParagraph - // above. The question is... could this be moved in front of the - // PasteParagraph? - //RemoveParagraph(tmprow); - //RemoveRow(tmprow); - // This rebuilds the rows. appendParagraph(bview, cursor.row()); updateCounters(bview); @@ -2539,10 +2455,7 @@ void LyXText::backspace(BufferView * bvi // any paragraphs setUndo(bview, Undo::DELETE, cursor.par(), cursor.par()->next()); - // We used to do cursorLeftIntern() here, but it is - // not a good idea since it triggers the auto-delete - // mechanism. So we do a cursorLeftIntern()-lite, - // without the dreaded mechanism. (JMarc) + setCursorIntern(bview, cursor.par(), cursor.pos()- 1, false, cursor.boundary()); Index: text2.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text2.C,v retrieving revision 1.286 diff -u -p -r1.286 text2.C --- text2.C 11 Mar 2003 16:38:37 -0000 1.286 +++ text2.C 12 Mar 2003 10:59:03 -0000 @@ -850,10 +850,6 @@ void LyXText::fullRebreak(BufferView * b // important for the screen -// the cursor set functions have a special mechanism. When they -// realize, that you left an empty paragraph, they will delete it. -// They also delete the corresponding row - // need the selection cursor: void LyXText::setSelection(BufferView * bview) { @@ -1743,7 +1739,7 @@ bool LyXText::setCursor(BufferView * bvi { LyXCursor old_cursor = cursor; setCursorIntern(bview, par, pos, setfont, boundary); - return deleteEmptyParagraphMechanism(bview, old_cursor); + deleteExtraSpaces(bview, old_cursor); } @@ -2061,7 +2057,7 @@ void LyXText::setCursorFromCoordinates(B setCursorFromCoordinates(bview, cursor, x, y); setCurrentFont(bview); - deleteEmptyParagraphMechanism(bview, old_cursor); + deleteExtraSpaces(bview, old_cursor); } @@ -2217,7 +2213,7 @@ void LyXText::cursorDownParagraph(Buffer } // fix the cursor `cur' after a characters has been deleted at `where' -// position. Called by deleteEmptyParagraphMechanism +// position. Called by deleteExtraSpaces void LyXText::fixCursorAfterDelete(BufferView * bview, LyXCursor & cur, LyXCursor const & where) const @@ -2242,8 +2238,8 @@ void LyXText::fixCursorAfterDelete(Buffe } -bool LyXText::deleteEmptyParagraphMechanism(BufferView * bview, - LyXCursor const & old_cursor) const +void LyXText::deleteExtraSpaces(BufferView * bview, + LyXCursor const & old_cursor) const { // Would be wrong to delete anything if we have a selection. if (selection.set()) @@ -2311,117 +2307,6 @@ bool LyXText::deleteEmptyParagraphMechan return false; } } - - // don't delete anything if this is the ONLY paragraph! - if (!old_cursor.par()->next() && !old_cursor.par()->previous()) - return false; - - // Do not delete empty paragraphs with keepempty set. - if (old_cursor.par()->layout()->keepempty) - return false; - - // only do our magic if we changed paragraph - if (old_cursor.par() == cursor.par()) - 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()->empty() - || (old_cursor.par()->size() == 1 - && old_cursor.par()->isLineSeparator(0)))) { - // ok, we will delete anything - LyXCursor tmpcursor; - - // make sure that you do not delete any environments - status(bview, LyXText::NEED_MORE_REFRESH); - deleted = true; - - if (old_cursor.row()->previous()) { - refresh_row = old_cursor.row()->previous(); - refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height(); - tmpcursor = cursor; - cursor = old_cursor; // that undo can restore the right cursor position - Paragraph * endpar = old_cursor.par()->next(); - if (endpar && endpar->getDepth()) { - while (endpar && endpar->getDepth()) { - endpar = endpar->next(); - } - } - setUndo(bview, Undo::DELETE, old_cursor.par(), endpar); - cursor = tmpcursor; - - // delete old row - removeRow(old_cursor.row()); - if (ownerParagraph() == old_cursor.par()) { - ownerParagraph(ownerParagraph()->next()); - } - // delete old par - delete old_cursor.par(); - - /* Breakagain the next par. Needed because of - * the parindent that can occur or dissappear. - * The next row can change its height, if - * there is another layout before */ - if (refresh_row->next()) { - breakAgain(bview, refresh_row->next()); - updateCounters(bview); - } - setHeightOfRow(bview, refresh_row); - } else { - refresh_row = old_cursor.row()->next(); - refresh_y = old_cursor.y() - old_cursor.row()->baseline(); - - tmpcursor = cursor; - cursor = old_cursor; // that undo can restore the right cursor position - Paragraph * endpar = old_cursor.par()->next(); - if (endpar && endpar->getDepth()) { - while (endpar && endpar->getDepth()) { - endpar = endpar->next(); - } - } - setUndo(bview, Undo::DELETE, old_cursor.par(), endpar); - cursor = tmpcursor; - - // delete old row - removeRow(old_cursor.row()); - // delete old par - if (ownerParagraph() == old_cursor.par()) { - ownerParagraph(ownerParagraph()->next()); - } - - delete old_cursor.par(); - - /* Breakagain the next par. Needed because of - the parindent that can occur or dissappear. - The next row can change its height, if - there is another layout before */ - if (refresh_row) { - breakAgain(bview, refresh_row); - updateCounters(bview); - } - } - - // correct cursor y - setCursorIntern(bview, cursor.par(), cursor.pos()); - - if (selection.cursor.par() == old_cursor.par() - && selection.cursor.pos() == old_cursor.pos()) { - // correct selection - selection.cursor = cursor; - } - } - if (!deleted) { - if (old_cursor.par()->stripLeadingSpaces()) { - redoParagraphs(bview, old_cursor, - old_cursor.par()->next()); - // correct cursor y - setCursorIntern(bview, cursor.par(), cursor.pos()); - selection.cursor = cursor; - } - } - return deleted; } Index: insets/insettext.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insettext.C,v retrieving revision 1.353 diff -u -p -r1.353 insettext.C --- insets/insettext.C 12 Mar 2003 05:46:35 -0000 1.353 +++ insets/insettext.C 12 Mar 2003 10:59:11 -0000 @@ -820,6 +820,7 @@ void InsetText::insetUnlock(BufferView * } else bv->owner()->setLayout(bv->text->cursor.par()->layout()->name()); // hack for deleteEmptyParMech +#warning FIXME, DEPM is dead - now what ? if (!paragraphs.begin()->empty()) { lt->setCursor(bv, &*(paragraphs.begin()), 0); } else if (paragraphs.begin()->next()) {