X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fundo_funcs.C;h=e0b0e42117d517414b6e2151597628b46efd689d;hb=34d28f9daae536db06d6cf1a9dcf62dc0f5aa432;hp=37041317f4474efa292857e7ff326349d7773f41;hpb=af7109795725294e87e7c2fd29d13eddb837c769;p=lyx.git diff --git a/src/undo_funcs.C b/src/undo_funcs.C index 37041317f4..e0b0e42117 100644 --- a/src/undo_funcs.C +++ b/src/undo_funcs.C @@ -21,41 +21,62 @@ #include "debug.h" #include "support/LAssert.h" +#include "iterators.h" + +//#define DELETE_UNUSED_PARAGRAPHS 1 +#ifdef DELETE_UNUSED_PARAGRAPHS +#include +#endif + /// the flag used by FinishUndo(); bool undo_finished; /// a flag bool undo_frozen; + bool textUndo(BufferView * bv) { // returns false if no undo possible - Undo * undo = bv->buffer()->undostack.pop(); + Undo * undo = bv->buffer()->undostack.top(); + bv->buffer()->undostack.pop(); if (undo) { finishUndo(); if (!undo_frozen) { Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par); - if (!first) + if (first && first->next()) + first = first->next(); + else if (!first) first = firstUndoParagraph(bv, undo->number_of_inset_id); if (first) { bv->buffer()->redostack.push( createUndo(bv, undo->kind, first, - bv->buffer()->getParFromID(undo->number_of_behind_par))); + bv->buffer()->getParFromID(undo->number_of_behind_par))); } } } - return textHandleUndo(bv, undo); + // now we can unlock the inset for saftey because the inset pointer could + // be changed during the undo-function. Anyway if needed we have to lock + // the right inset/position if this is requested. + freezeUndo(); + bv->unlockInset(bv->theLockingInset()); + bool ret = textHandleUndo(bv, undo); + unFreezeUndo(); + return ret; } bool textRedo(BufferView * bv) { // returns false if no redo possible - Undo * undo = bv->buffer()->redostack.pop(); + Undo * undo = bv->buffer()->redostack.top(); + bv->buffer()->redostack.pop(); if (undo) { finishUndo(); if (!undo_frozen) { Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par); - if (!first) + if (first && first->next()) + first = first->next(); + else if (!first) first = firstUndoParagraph(bv, undo->number_of_inset_id); if (first) { bv->buffer()->undostack.push( @@ -64,7 +85,14 @@ bool textRedo(BufferView * bv) } } } - return textHandleUndo(bv, undo); + // now we can unlock the inset for saftey because the inset pointer could + // be changed during the undo-function. Anyway if needed we have to lock + // the right inset/position if this is requested. + freezeUndo(); + bv->unlockInset(bv->theLockingInset()); + bool ret = textHandleUndo(bv, undo); + unFreezeUndo(); + return ret; } @@ -79,7 +107,6 @@ bool textHandleUndo(BufferView * bv, Undo * undo) bv->buffer()->getParFromID(undo->number_of_behind_par); Paragraph * tmppar; Paragraph * tmppar2; - Paragraph * endpar; Paragraph * tmppar5; // if there's no before take the beginning @@ -101,17 +128,29 @@ bool textHandleUndo(BufferView * bv, Undo * undo) // replace the paragraphs with the undo informations Paragraph * tmppar3 = undo->par; - undo->par = 0; // otherwise the undo destructor would - // delete the paragraph + undo->par = 0; /* otherwise the undo destructor would + delete the paragraph */ - // get last undo par + // get last undo par and set the right(new) inset-owner of the + // paragraph if there is any. This is not needed if we don't have + // a paragraph before because then in is automatically done in the + // function which assigns the first paragraph to an InsetText. (Jug) Paragraph * tmppar4 = tmppar3; if (tmppar4) { - while (tmppar4->next()) + Inset * in = 0; + if (before) + in = before->inInset(); + tmppar4->setInsetOwner(in); + while (tmppar4->next()) { tmppar4 = tmppar4->next(); - } + tmppar4->setInsetOwner(in); + } + } // now remove the old text if there is any +#ifdef DELETE_UNUSED_PARAGRAPHS + std::vector vvpar; +#endif if (before != behind || (!behind && !before)) { if (before) tmppar5 = before->next(); @@ -119,6 +158,9 @@ bool textHandleUndo(BufferView * bv, Undo * undo) tmppar5 = firstUndoParagraph(bv, undo->number_of_inset_id); tmppar2 = tmppar3; while (tmppar5 && tmppar5 != behind) { +#ifdef DELETE_UNUSED_PARAGRAPHS + vvpar.push_back(tmppar5); +#endif tmppar = tmppar5; tmppar5 = tmppar5->next(); // a memory optimization for edit: @@ -127,9 +169,11 @@ bool textHandleUndo(BufferView * bv, Undo * undo) // the text informations. if (undo->kind == Undo::EDIT) { tmppar2->setContentsFromPar(tmppar); +#ifndef DELETE_UNUSED_PARAGRAPHS + tmppar->clearContents(); +#endif tmppar2 = tmppar2->next(); } - delete tmppar; } } @@ -138,26 +182,16 @@ bool textHandleUndo(BufferView * bv, Undo * undo) if (before) before->next(tmppar3); else -#warning Juergen, why is this needed?? (JMarc) -// since tmppar3 is not yet inserted in the document, I do not see why -// the getParFromID which is done by the function below makes sense. -// OTOH, since you wrote the method just for this instance, I guess you -// have something in mind -#if 1 bv->text->ownerParagraph(tmppar3->id(), tmppar3); -#else -// in this case, since getParFromID is not called, the program does -// not crash on trying to access buffer()->paragraph, which does not -// exist anymore if we undid the first par f the document. (JMarc) - bv->text->ownerParagraph(tmppar3); -#endif tmppar3->previous(before); } else { // Do we really enter here ??? (Jug) - if (!before) + if (!before && behind) { bv->text->ownerParagraph(behind); + tmppar3 = behind; + } } if (tmppar4) { tmppar4->next(behind); @@ -168,42 +202,84 @@ bool textHandleUndo(BufferView * bv, Undo * undo) // Set the cursor for redoing if (before) { - bv->text->setCursorIntern(bv, before, 0); + Inset * it = before->inInset(); + if (it) + it->getLyXText(bv)->setCursorIntern(bv, before, 0); + else + bv->text->setCursorIntern(bv, before, 0); } + Paragraph * endpar = 0; // calculate the endpar for redoing the paragraphs. - if (behind) { - endpar = behind->next(); - } else - endpar = behind; - + if (behind) + endpar = behind->next(); + tmppar = bv->buffer()->getParFromID(undo->number_of_cursor_par); - UpdatableInset* it = static_cast(tmppar3->inInset()); + UpdatableInset* it = 0; + if (tmppar3) + it = static_cast(tmppar3->inInset()); if (it) { - it->getLyXText(bv)->redoParagraphs(bv, it->getLyXText(bv)->cursor, + it->getLyXText(bv)->redoParagraphs(bv, + it->getLyXText(bv)->cursor, endpar); - if (tmppar){ - it->getLyXText(bv)->setCursorIntern(bv, tmppar, undo->cursor_pos); - it->getLyXText(bv)->updateCounters(bv, it->getLyXText(bv)->cursor.row()); - } LyXFont font; it->update(bv, font, false); -#ifdef THIS_DOES_NOT_WORK - // we need this anyway as also if the undo was - // inside an inset we have to redo the - // paragraph breaking + // we now would have to rebreak the whole paragraph the + // undo-par was in. How we do it here is not really true. + // We would have to save this information in the undo-struct + // and then we could do the right rebreak. Here we only + // handle the case where this was in the actual paragraph, + // which not always is true. bv->text->redoParagraphs(bv, bv->text->cursor, - bv->text->cursor.par()); -#endif + bv->text->cursor.par()); + if (tmppar){ + it = static_cast(tmppar->inInset()); + LyXText * t; + if (it) { + it->edit(bv); + t = it->getLyXText(bv); + } else { + t = bv->text; + } + t->setCursorIntern(bv, tmppar, undo->cursor_pos); + t->updateCounters(bv, t->cursor.row()); + } + bv->text->setCursorIntern(bv, bv->text->cursor.par(), + bv->text->cursor.pos()); } else { bv->text->redoParagraphs(bv, bv->text->cursor, endpar); if (tmppar) { - bv->text->setCursorIntern(bv, tmppar, undo->cursor_pos); - bv->text->updateCounters(bv, bv->text->cursor.row()); + LyXText * t; + Inset * it = tmppar->inInset(); + if (it) { + it->edit(bv); + t = it->getLyXText(bv); + } else { + t = bv->text; + } + t->setCursorIntern(bv, tmppar, undo->cursor_pos); + t->updateCounters(bv, t->cursor.row()); } } result = true; delete undo; +#ifdef DELETE_UNUSED_PARAGRAPHS + // And here it's save enough to delete all removed paragraphs + std::vector::iterator pit = vvpar.begin(); + if (pit != vvpar.end()) { + lyxerr << "DEL: "; + for(;pit != vvpar.end(); ++pit) { + lyxerr << *pit << " "; + delete (*pit); + } + lyxerr << endl << "PARS:"; + ParIterator end = bv->buffer()->par_iterator_end(); + ParIterator it = bv->buffer()->par_iterator_begin(); + for (; it != end; ++it) + lyxerr << *it << " "; + lyxerr << endl; + } +#endif } finishUndo(); bv->text->status(bv, LyXText::NEED_MORE_REFRESH); @@ -235,9 +311,10 @@ void unFreezeUndo() void setUndo(BufferView * bv, Undo::undo_kind kind, Paragraph const * first, Paragraph const * behind) { - if (!undo_frozen) + if (!undo_frozen) { bv->buffer()->undostack.push(createUndo(bv, kind, first, behind)); - bv->buffer()->redostack.clear(); + bv->buffer()->redostack.clear(); + } } @@ -247,7 +324,6 @@ void setRedo(BufferView * bv, Undo::undo_kind kind, bv->buffer()->redostack.push(createUndo(bv, kind, first, behind)); } -using lyx::pos_type; Undo * createUndo(BufferView * bv, Undo::undo_kind kind, Paragraph const * first, Paragraph const * behind) @@ -276,8 +352,8 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind, // check wether storing is needed if (!bv->buffer()->undostack.empty() && bv->buffer()->undostack.top()->kind == kind && - bv->buffer()->undostack.top()->number_of_before_par == before_number && - bv->buffer()->undostack.top()->number_of_behind_par == behind_number ){ + bv->buffer()->undostack.top()->number_of_before_par == before_number && + bv->buffer()->undostack.top()->number_of_behind_par == behind_number) { // no undo needed return 0; } @@ -297,10 +373,10 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind, } if (start && end && (start != end->next()) && ((before_number != behind_number) || - ((before_number < 0) && (behind_number < 0)))) { + ((before_number < 0) && (behind_number < 0)))) + { Paragraph * tmppar = start; Paragraph * tmppar2 = new Paragraph(*tmppar, true); - tmppar2->id(tmppar->id()); // a memory optimization: Just store the layout information // when only edit @@ -312,14 +388,19 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind, while (tmppar != end && tmppar->next()) { tmppar = tmppar->next(); - tmppar2->next(new Paragraph(*tmppar, false)); - tmppar2->next()->id(tmppar->id()); +#if 0 + tmppar2->next(new Paragraph(*tmppar, true)); +#else + Paragraph * ptmp = new Paragraph(*tmppar, true); + tmppar2->next(ptmp); +#endif // a memory optimization: Just store the layout // information when only edit if (kind == Undo::EDIT) { tmppar2->clearContents(); } tmppar2->next()->previous(tmppar2); + tmppar2 = tmppar2->next(); } tmppar2->next(0); @@ -340,22 +421,23 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind, void setCursorParUndo(BufferView * bv) { - setUndo(bv, Undo::FINISH, - bv->text->cursor.par(), - bv->text->cursor.par()->next()); + setUndo(bv, Undo::FINISH, bv->text->cursor.par(), + bv->text->cursor.par()->next()); } + Paragraph * firstUndoParagraph(BufferView * bv, int inset_id) { Inset * inset = bv->buffer()->getInsetFromID(inset_id); if (inset) { - Paragraph * result = inset->firstParagraph(); + Paragraph * result = inset->getFirstParagraph(0); if (result) return result; } return bv->text->ownerParagraph(); } + LyXCursor const & undoCursor(BufferView * bv) { if (bv->theLockingInset())