Juergen Spitzmueller wrote: > Jean-Marc Lasgouttes wrote: > > I'm very glad that you found the > > cause, but the fix doesn't look > > right. > > Too bad. Then I am at my witness end.
I have tried to enhance my witness a bit this year. Here's how I understand this case: After DEPM, doRecordUndo is finally called, where undo.end is calculated as undo.end = cell.lastpit() - last_pit; cell.lastpit() is the lastpit of the buffer _including_ the paragraph that will be deleted. last_pit is the paragraph where the cursor sits. If this is the first paragraph (pit = 0), then undo.end = cell.lastpit(), which is 1 bigger than lastpit() of the buffer _after_ DEPM. Now if undo is activated after DEPM, textUndoOrRedo calls doRecordUndo again, with a last_pit that is calculated from cell_dit.lastpit() - undo.end. In our case, this is -1, since, as elaborated, undo.end is 1 bigger than current lastpit. Until now, we thought that such a value is invalid, but as I understand it now, this is correct, since last_pit is again only used to calculate undo.end: undo.end = cell.lastpit() - last_pit; which is undo.end = cell.lastpit() - (-1), e.g. undo.end = cell.lastpit() + 1 IMHO this is correct, since the deleted paragraph is being added again at this stage, so undo.end has to increase by one. However, I'm not definitely sure. Let's have a look at the crash. This is due to the first action of doRecordUndo: if (first_pit > last_pit) std::swap(first_pit, last_pit); this is of course triggeres if last_pit = -1, but it shouldn't in this case. I don't know if it crashes because swap cannot handle negative values or because of some later action, anyway, it just shouldn't try to swap the two values here. So my proposal to fix the bug now is - if (first_pit > last_pit) + if (last_pit >= 0 && first_pit > last_pit) std::swap(first_pit, last_pit); (see attached patch). As expected, this fixes the crash and also works as expected for undo after DEPM. Does this sound reasonable? Jürgen
Index: undo.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/undo.C,v retrieving revision 1.69 diff -u -r1.69 undo.C --- undo.C 24 Nov 2005 16:22:39 -0000 1.69 +++ undo.C 2 Jan 2006 11:43:19 -0000 @@ -64,7 +64,9 @@ bool isFullBuffer, limited_stack<Undo> & stack) { - if (first_pit > last_pit) + // last_pit can legally be -1 when a DEPM action in the first paragraph + // has to be restored! Then undo.end below is cell.lastpit + 1 + if (last_pit >= 0 && first_pit > last_pit) std::swap(first_pit, last_pit); // create the position information of the Undo entry Undo undo; @@ -150,10 +152,9 @@ Buffer * buf = bv.buffer(); DocIterator cell_dit = undo.cell.asDocIterator(&buf->inset()); - doRecordUndo(Undo::ATOMIC, cell_dit, - undo.from, cell_dit.lastpit() - undo.end, bv.cursor(), - undo.bparams, undo.isFullBuffer, - otherstack); + doRecordUndo(Undo::ATOMIC, cell_dit, undo.from, + cell_dit.lastpit() - undo.end, bv.cursor(), + undo.bparams, undo.isFullBuffer, otherstack); // This does the actual undo/redo. //lyxerr << "undo, performing: " << undo << std::endl;