+ Buffer * b = bv->buffer();
+
+ if (b->redostack.empty()) {
+ finishNoUndo(bv);
+ return false;
+ }
+
+ shared_ptr<Undo> undo = b->redostack.top();
+ b->redostack.pop();
+ finishUndo();
+
+ if (!undo_frozen) {
+ 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) {
+ shared_ptr<Undo> u;
+ if (createUndo(bv, undo->kind, first,
+ bv->buffer()->getParFromID(undo->number_of_behind_par), u))
+ bv->buffer()->undostack.push(u);
+ }
+ }
+
+ // 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.get());
+ unFreezeUndo();
+ return ret;
+}
+
+
+void setUndo(BufferView * bv, Undo::undo_kind kind,
+ Paragraph const * first, Paragraph const * behind)
+{
+ if (!undo_frozen) {
+ shared_ptr<Undo> u;
+ if (createUndo(bv, kind, first, behind, u))
+ bv->buffer()->undostack.push(u);
+ bv->buffer()->redostack.clear();
+ }
+}
+
+
+void setRedo(BufferView * bv, Undo::undo_kind kind,
+ Paragraph const * first, Paragraph const * behind)
+{
+ shared_ptr<Undo> u;
+ if (createUndo(bv, kind, first, behind, u))
+ bv->buffer()->redostack.push(u);
+}
+
+
+void setCursorParUndo(BufferView * bv)
+{
+ setUndo(bv, Undo::FINISH, &*bv->text->cursor.par(),
+ bv->text->cursor.par()->next());