#include "buffer.h"
#include "insets/inset.h"
#include "debug.h"
+#include "support/LAssert.h"
+
+#include "iterators.h"
+
+//#define DELETE_UNUSED_PARAGRAPHS 1
+#ifdef DELETE_UNUSED_PARAGRAPHS
+#include <vector>
+#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->text->getParFromID(undo->number_of_before_par);
- if (!first)
+ Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par);
+ 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->text->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->text->getParFromID(undo->number_of_before_par);
- if (!first)
+ Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par);
+ if (first && first->next())
+ first = first->next();
+ else if (!first)
first = firstUndoParagraph(bv, undo->number_of_inset_id);
if (first) {
bv->buffer()->undostack.push(
createUndo(bv, undo->kind, first,
- bv->text->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 result = false;
if (undo) {
Paragraph * before =
- bv->text->getParFromID(undo->number_of_before_par);
+ bv->buffer()->getParFromID(undo->number_of_before_par);
Paragraph * behind =
- bv->text->getParFromID(undo->number_of_behind_par);
+ bv->buffer()->getParFromID(undo->number_of_behind_par);
Paragraph * tmppar;
Paragraph * tmppar2;
- Paragraph * endpar;
Paragraph * tmppar5;
// if there's no before take the beginning
// replace the paragraphs with the undo informations
Paragraph * tmppar3 = undo->par;
- undo->par = 0; // otherwise the undo destructor would delete the paragraph
- Paragraph * tmppar4 = tmppar3;
+ undo->par = 0; /* otherwise the undo destructor would
+ delete the paragraph */
+ // 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();
- } // get last undo par
+ tmppar4->setInsetOwner(in);
+ }
+ }
// now remove the old text if there is any
+#ifdef DELETE_UNUSED_PARAGRAPHS
+ std::vector<Paragraph *> vvpar;
+#endif
if (before != behind || (!behind && !before)) {
if (before)
tmppar5 = before->next();
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: Only layout information
- // is stored in the undo. So restore the text informations.
+ // a memory optimization for edit:
+ // Only layout information
+ // is stored in the undo. So restore
+ // the text informations.
if (undo->kind == Undo::EDIT) {
tmppar2->setContentsFromPar(tmppar);
+#ifndef DELETE_UNUSED_PARAGRAPHS
tmppar->clearContents();
+#endif
tmppar2 = tmppar2->next();
}
}
if (before)
before->next(tmppar3);
else
- bv->text->ownerParagraph(tmppar3->id(), tmppar3);
+ bv->text->ownerParagraph(tmppar3->id(),
+ tmppar3);
+
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);
// 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;
-
- tmppar = bv->text->getParFromID(undo->number_of_cursor_par);
- UpdatableInset* it = static_cast<UpdatableInset*>(tmppar3->InInset());
+ if (behind)
+ endpar = behind->next();
+
+ tmppar = bv->buffer()->getParFromID(undo->number_of_cursor_par);
+ UpdatableInset* it = 0;
+ if (tmppar3)
+ it = static_cast<UpdatableInset*>(tmppar3->inInset());
if (it) {
- it->getLyXText(bv)->redoParagraphs(bv, it->getLyXText(bv)->cursor,
+ it->getLyXText(bv)->redoParagraphs(bv,
+ it->getLyXText(bv)->cursor,
endpar);
+ LyXFont font;
+ it->update(bv, font, false);
+ // 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());
if (tmppar){
- it->getLyXText(bv)->setCursorIntern(bv, tmppar, undo->cursor_pos);
- it->getLyXText(bv)->updateCounters(bv, it->getLyXText(bv)->cursor.row());
+ it = static_cast<UpdatableInset*>(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());
}
-#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
- bv->text->redoParagraphs(bv, bv->text->cursor,
- bv->text->cursor.par());
-#endif
+ 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<Paragraph *>::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);
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();
+ }
}
before_number = first->previous()->id();
if (behind)
behind_number = behind->id();
- if (first->InInset())
- inset_id = first->InInset()->id();
+ if (first->inInset())
+ inset_id = first->inInset()->id();
// Undo::EDIT and Undo::FINISH are
// always finished. (no overlapping there)
// 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;
}
Paragraph * start = const_cast<Paragraph *>(first);
Paragraph * end = 0;
-#if 0
- if (first)
- start = const_cast<Paragraph*>(before->next());
- else
- start = firstUndoParagraph(bv);
-#endif
if (behind)
end = const_cast<Paragraph*>(behind->previous());
else {
}
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
while (tmppar != end && tmppar->next()) {
tmppar = tmppar->next();
- tmppar2->next(new Paragraph(*tmppar));
- 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);
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())