updateScrollbar();
}
screen().redraw(*bv_);
+ bv_->owner()->view_state_changed();
}
+
+2004-03-08 André Pönitz <poenitz@gmx.net>
+
+ * undo.[Ch]: use 'StableDocumentIterator' as base for
+ the Undo struct.
+
2004-03-07 Jürgen Spitzmüller <j.spitzmueller@gmx.de>
* LaTeXFeatures.C:
DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
{
- lyxerr << "\nLCursor::dispatch: cmd: " << cmd0 << endl << *this << endl;
+ //lyxerr << "\nLCursor::dispatch: cmd: " << cmd0 << endl << *this << endl;
BOOST_ASSERT(pos() <= lastpos());
BOOST_ASSERT(idx() <= lastidx());
BOOST_ASSERT(par() <= lastpar());
}
-/*
-DispatchResult dispatch(LCursor & cur, FuncRequest const & cmd)
-{
- // mouse clicks are somewhat special
- // check
- switch (cmd.action) {
- case LFUN_MOUSE_PRESS:
- case LFUN_MOUSE_MOTION:
- case LFUN_MOUSE_RELEASE:
- case LFUN_MOUSE_DOUBLE: {
- CursorSlice & pos = back();
- int x = 0;
- int y = 0;
- getPos(x, y);
- if (x < cmd.x && pos() != 0) {
- DispatchResult const res = prevAtom().nucleus()->dispatch(cmd);
- if (res.dispatched())
- return res;
- }
- if (x > cmd.x && pos() != lastpos()) {
- DispatchResult const res = inset()->dispatch(cmd);
- if (res.dispatched())
- return res;
- }
- }
- default:
- break;
- }
-}
-*/
-
-
void LCursor::handleFont(string const & font)
{
lyxerr << "LCursor::handleFont: " << font << endl;
class MathGridInset;
-/**
- * The cursor class describes the position of a cursor within a document.
- */
+/// The cursor class describes the position of a cursor within a document.
// The public inheritance should go in favour of a suitable data member
// (or maybe private inheritance) at some point of time.
-std::ostream & operator<<(std::ostream & os, DocumentIterator const & cur);
-
-
DocumentIterator::DocumentIterator()
: bv_(0)
{}
}
-std::ostream & operator<<(std::ostream & os, DocumentIterator const & cur)
+std::ostream & operator<<(std::ostream & os, DocumentIterator const & dit)
{
- for (size_t i = 0, n = cur.size(); i != n; ++i)
- os << " " << cur.operator[](i) << "\n";
+ os << "bv: " << &dit.bv() << "\n";
+ for (size_t i = 0, n = dit.size(); i != n; ++i)
+ os << " " << dit.operator[](i) << "\n";
return os;
}
+
+
+
+///////////////////////////////////////////////////////
+
+StableDocumentIterator::StableDocumentIterator(const DocumentIterator & dit)
+{
+ data_ = dit;
+ for (size_t i = 0, n = data_.size(); i != n; ++i)
+ data_[i].inset_ = 0;
+}
+
+
+DocumentIterator
+StableDocumentIterator::asDocumentIterator(BufferView & bv) const
+{
+ // this function re-creates the cache of inset pointers
+ //lyxerr << "converting:\n" << *this << std::endl;
+ DocumentIterator dit(bv);
+ dit.clear();
+ InsetBase * inset = 0;
+ for (size_t i = 0, n = data_.size(); i != n; ++i) {
+ dit.push_back(data_[i]);
+ dit.back().inset_ = inset;
+ if (i + 1 != n)
+ inset = dit.nextInset();
+ }
+ //lyxerr << "convert:\n" << *this << " to:\n" << dit << std::endl;
+ return dit;
+}
+
+
+std::ostream & operator<<(std::ostream & os, StableDocumentIterator const & dit)
+{
+ for (size_t i = 0, n = dit.data_.size(); i != n; ++i)
+ os << " " << dit.data_[i] << "\n";
+ return os;
+}
+
#include "cursor_slice.h"
#include <vector>
+#include <iosfwd>
class BufferView;
class MathAtom;
class Row;
+
// only needed for gcc 2.95, remove when support terminated
template <typename A, typename B>
bool ptr_cmp(A const * a, B const * b)
void forwardIdx();
/// move on one inset
void forwardInset();
+ /// output
+ friend std::ostream &
+ operator<<(std::ostream & os, DocumentIterator const & cur);
private:
///
///
DocumentIterator insetEnd();
+
+// The difference to a ('non stable') DocumentIterator is the removed
+// (overwritte by 0...) part of the CursorSlice data items. So this thing
+// is suitable for external storage, but not for iteration as such.
+
+class StableDocumentIterator {
+public:
+ ///
+ StableDocumentIterator() {}
+ /// non-explicit intended
+ StableDocumentIterator(const DocumentIterator & it);
+ ///
+ DocumentIterator asDocumentIterator(BufferView & bv) const;
+ ///
+ size_t size() const { return data_.size(); }
+ ///
+ friend std::ostream &
+ operator<<(std::ostream & os, StableDocumentIterator const & cur);
+ ///
+ friend std::istream &
+ operator>>(std::istream & is, StableDocumentIterator & cur);
+private:
+ std::vector<CursorSlice> data_;
+};
+
+bool operator==(StableDocumentIterator const &, StableDocumentIterator const &);
+
#endif
string const InsetCollapsable::getNewLabel(string const & l) const
{
- string la;
+ string label;
pos_type const max_length = 15;
pos_type const p_siz = inset.paragraphs().begin()->size();
pos_type const n = min(max_length, p_siz);
for( ; i < n && j < p_siz; ++j) {
if (inset.paragraphs().begin()->isInset(j))
continue;
- la += inset.paragraphs().begin()->getChar(j);
+ label += inset.paragraphs().begin()->getChar(j);
++i;
}
if (inset.paragraphs().size() > 1 || (i > 0 && j < p_siz)) {
- la += "...";
+ label += "...";
}
- return la.empty() ? l : la;
+ return label.empty() ? l : label;
}
kb_action action = cmd.action;
lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl;
- lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
+ //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
// we have not done anything wrong yet.
errorstat = false;
{
// this whole function is a hack and won't work for incremental font
// changes...
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
if (cur.inset()->asMathInset()->name() == font)
cur.handleFont(font);
void MathNestInset::handleFont2(LCursor & cur, string const & arg)
{
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
LyXFont font;
bool b;
bv_funcs::string2font(arg, font, b);
is >> n;
if (was_macro)
cur.macroModeClose();
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.selPaste(n);
break;
}
case LFUN_DELETE_WORD_BACKWARD:
case LFUN_BACKSPACE:
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.backspace();
break;
case LFUN_DELETE_WORD_FORWARD:
case LFUN_DELETE:
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.erase();
cur.dispatched(FINISHED_LEFT);
break;
cur.dispatched(FINISHED_RIGHT);
break;
}
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
if (cmd.argument.size() != 1) {
cur.insert(cmd.argument);
break;
}
case LFUN_CUT:
- //recordUndo(cur, Undo::DELETE);
+ recordUndo(cur, Undo::DELETE);
cur.selCut();
break;
if (cmd.argument.empty()) {
// do superscript if LyX handles
// deadkeys
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
script(cur, true);
}
break;
case LFUN_MATH_SIZE:
#if 0
if (!arg.empty()) {
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.setSize(arg);
}
#endif
break;
case LFUN_INSERT_MATRIX: {
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
unsigned int m = 1;
unsigned int n = 1;
string v_align;
ls = '(';
if (rs.empty())
rs = ')';
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.handleNest(MathAtom(new MathDelimInset(ls, rs)));
break;
}
case LFUN_SPACE_INSERT:
case LFUN_MATH_SPACE:
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.insert(MathAtom(new MathSpaceInset(",")));
break;
case LFUN_INSET_ERT:
// interpret this as if a backslash was typed
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
interpret(cur, '\\');
break;
// handling such that "self-insert" works on "arbitrary stuff" too, and
// math-insert only handles special math things like "matrix".
case LFUN_INSERT_MATH:
- //recordUndo(cur, Undo::ATOMIC);
+ recordUndo(cur, Undo::ATOMIC);
cur.niceInsert(cmd.argument);
break;
void LyXText::insertChar(LCursor & cur, char c)
{
BOOST_ASSERT(this == cur.text());
+ BOOST_ASSERT(c != Paragraph::META_INSET);
+
recordUndo(cur, Undo::INSERT);
Paragraph & par = cur.paragraph();
}
}
- // Here case LyXText::InsertInset already inserted the character
- if (c != Paragraph::META_INSET)
- par.insertChar(cur.pos(), c);
-
+ par.insertChar(cur.pos(), c);
setCharFont(pit, cur.pos(), rawtmpfont);
current_font = rawtmpfont;
LyXText::LyXText(BufferView * bv, bool in_inset)
- : height_(0), width_(0), maxwidth_(bv ? bv->workWidth() : 100),
+ : width_(0), maxwidth_(bv ? bv->workWidth() : 100), height_(0),
background_color_(LColor::background),
bv_owner(bv), in_inset_(in_inset), xo_(0), yo_(0)
{}
void LyXText::insertInset(LCursor & cur, InsetBase * inset)
{
BOOST_ASSERT(this == cur.text());
- recordUndo(cur);
- freezeUndo();
+ BOOST_ASSERT(inset);
cur.paragraph().insertInset(cur.pos(), inset);
- // Just to rebreak and refresh correctly.
- // The character will not be inserted a second time
- insertChar(cur, Paragraph::META_INSET);
- // If we enter a highly editable inset the cursor should be before
- // the inset. After an undo LyX tries to call inset->edit(...)
- // and fails if the cursor is behind the inset and getInset
- // does not return the inset!
- if (isHighlyEditableInset(inset))
- cursorLeft(cur);
- unFreezeUndo();
+ redoParagraph(cur);
}
void LyXText::replaceSelectionWithString(LCursor & cur, string const & str)
{
recordUndo(cur);
- freezeUndo();
// Get font setting before we cut
pos_type pos = cur.selEnd().pos();
// Cut the selection
cutSelection(cur, true, false);
- unFreezeUndo();
}
}
if (pos > end) {
- lyxerr << "dont like 2 please report" << endl;
+ lyxerr << "dont like 2, pos: " << pos
+ << " size: " << para.size()
+ << " row.pos():" << row.pos()
+ << " par: " << par << endl;
// This shouldn't happen.
BOOST_ASSERT(false);
}
void toggleAndShow(LCursor & cur, LyXText * text,
LyXFont const & font, bool toggleall = true)
{
- if (!cur.bv().available())
- return;
-
text->toggleFree(cur, font, toggleall);
if (font.language() != ignore_language ||
text->setCursor(cur, cur.par(), cur.pos(),
false, !cur.boundary());
}
- cur.update();
}
}
- void finishChange(LCursor & cur, bool selecting = false)
+ void finishChange(LCursor & cur, bool selecting)
{
finishUndo();
moveCursor(cur, selecting);
- cur.bv().owner()->view_state_changed();
}
void mathDispatch(LCursor & cur, LyXText * text,
FuncRequest const & cmd, bool display)
{
+ recordUndo(cur);
string sel = cur.selectionAsString(false);
lyxerr << "selection is: '" << sel << "'" << endl;
if (!inset)
return;
+ recordUndo(cur);
bool gotsel = false;
if (cur.selection()) {
cur.bv().owner()->dispatch(FuncRequest(LFUN_CUT));
case LFUN_DELETE_WORD_FORWARD:
cur.clearSelection();
deleteWordForward(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_DELETE_WORD_BACKWARD:
cur.clearSelection();
deleteWordBackward(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_DELETE_LINE_FORWARD:
cur.clearSelection();
deleteLineForward(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_WORDRIGHT:
cursorLeftOneWord(cur);
else
cursorRightOneWord(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_WORDLEFT:
cursorRightOneWord(cur);
else
cursorLeftOneWord(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_BEGINNINGBUF:
if (!cur.mark())
cur.clearSelection();
cursorTop(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_ENDBUF:
if (!cur.mark())
cur.clearSelection();
cursorBottom(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_RIGHT:
if (!cur.mark())
cur.clearSelection();
cursorUpParagraph(cur);
- finishChange(cur);
+ finishChange(cur, false);
break;
case LFUN_DOWN_PARAGRAPH:
cutSelection(cur, true, false);
}
moveCursor(cur, false);
- bv->owner()->view_state_changed();
break;
case LFUN_DELETE_SKIP:
} else {
cutSelection(cur, true, false);
}
- bv->owner()->view_state_changed();
bv->switchKeyMap();
cur.update();
break;
cur.update();
cur.resetAnchor();
bv->switchKeyMap();
- bv->owner()->view_state_changed();
break;
case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
cur.update();
cur.resetAnchor();
bv->switchKeyMap();
- bv->owner()->view_state_changed();
break;
case LFUN_BREAKPARAGRAPH_SKIP: {
cur.update();
// anchor() = cur;
bv->switchKeyMap();
- bv->owner()->view_state_changed();
break;
}
}
case LFUN_INSET_INSERT: {
+ recordUndo(cur);
InsetBase * inset = createInset(bv, cmd);
if (inset)
insertInset(cur, inset);
bv->haveSelection(cur.selection());
bv->switchKeyMap();
- bv->owner()->view_state_changed();
bv->owner()->updateMenubar();
bv->owner()->updateToolbar();
break;
// real_current_font.number can change so we need to
// update the minibuffer
if (old_font != real_current_font)
- bv->owner()->view_state_changed();
bv->updateScrollbar();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setEmph(LyXFont::TOGGLE);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setSeries(LyXFont::BOLD_SERIES);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setNoun(LyXFont::TOGGLE);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setFamily(LyXFont::TYPEWRITER_FAMILY); // no good
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setFamily(LyXFont::SANS_FAMILY);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setFamily(LyXFont::ROMAN_FAMILY);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
case LFUN_DEFAULT: {
LyXFont font(LyXFont::ALL_INHERIT, ignore_language);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setUnderbar(LyXFont::TOGGLE);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
LyXFont font(LyXFont::ALL_IGNORE);
font.setLyXSize(cmd.argument);
toggleAndShow(cur, this, font);
- bv->owner()->view_state_changed();
break;
}
font.setLanguage(lang);
toggleAndShow(cur, this, font);
bv->switchKeyMap();
- bv->owner()->view_state_changed();
break;
}
case LFUN_FREEFONT_APPLY:
toggleAndShow(cur, this, freefont, toggleall);
- bv->owner()->view_state_changed();
cur.message(_("Character set"));
break;
freefont = font;
toggleall = toggle;
toggleAndShow(cur, this, freefont, toggleall);
- bv->owner()->view_state_changed();
cur.message(_("Character set"));
}
break;
if (tclass.floats().typeExist(cmd.argument)) {
// not quite sure if we want this...
recordUndo(cur);
- freezeUndo();
cur.clearSelection();
breakParagraph(cur);
setLayout(cur, tclass.defaultLayoutName());
setParagraph(cur, Spacing(), LYX_ALIGN_LAYOUT, string(), 0);
- cur.insert(new InsetFloatList(cmd.argument));
- unFreezeUndo();
+ insertInset(cur, new InsetFloatList(cmd.argument));
} else {
lyxerr << "Non-existent float type: "
<< cmd.argument << endl;
#include "cursor.h"
#include "debug.h"
#include "BufferView.h"
-#include "iterators.h"
#include "lyxtext.h"
#include "paragraph.h"
+#include "mathed/math_support.h"
+
+#include <algorithm>
+
using lyx::paroffset_type;
std::ostream & operator<<(std::ostream & os, Undo const & undo)
{
- return os << " text: " << undo.text
- << " index: " << undo.index
- << " first: " << undo.first_par
- << " from end: " << undo.end_par
- << " cursor: " << undo.cursor_par
- << "/" << undo.cursor_pos;
-}
-
-
-// translates LyXText pointer into offset count from document begin
-ParIterator text2pit(Buffer & buf, LyXText * text, int & tcount)
-{
- tcount = 0;
- ParIterator pit = buf.par_iterator_begin();
- ParIterator end = buf.par_iterator_end();
-
- for ( ; pit != end; ++pit, ++tcount)
- if (pit.text(buf) == text)
- return pit;
- lyxerr << "undo: should not happen" << std::endl;
- return end;
-}
-
-
-// translates offset from buffer begin to ParIterator
-ParIterator num2pit(Buffer & buf, int num)
-{
- ParIterator pit = buf.par_iterator_begin();
- ParIterator end = buf.par_iterator_end();
-
- for ( ; num && pit != end; ++pit, --num)
- ;
-
- if (pit != end)
- return pit;
-
- // don't crash early...
- lyxerr << "undo: num2pit: num: " << num << std::endl;
- BOOST_ASSERT(false);
- return buf.par_iterator_begin();
+ return os << " from: " << undo.from
+ << " end: " << undo.end
+ << " cursor:\n" << undo.cursor;
}
LCursor & cur, paroffset_type first_par, paroffset_type last_par,
limited_stack<Undo> & stack)
{
-#if 0
- DocumentIterator it = bufferBegin(cur.bv());
- DocumentIterator et = bufferEnd();
- size_t count = 0;
- for ( ; it != et; it.forwardPos(), ++count)
- if (it.top() == cur.top())
- lyxerr << "### found at " << count << std::endl;
-#endif
-
- if (first_par > last_par) {
- paroffset_type t = first_par;
- first_par = last_par;
- last_par = t;
- }
+ BOOST_ASSERT(first_par <= cur.lastpar());
+ BOOST_ASSERT(last_par <= cur.lastpar());
- Buffer & buf = *cur.bv().buffer();
- int const end_par = cur.lastpar() + 1 - last_par;
+ if (first_par > last_par)
+ std::swap(first_par, last_par);
- // Undo::ATOMIC are always recorded (no overlapping there).
- // overlapping only with insert and delete inside one paragraph:
- // nobody wants all removed character appear one by one when undoing.
- if (!undo_finished && kind != Undo::ATOMIC) {
- // Check whether storing is needed.
- if (!buf.undostack().empty()
- && buf.undostack().top().kind == kind
- && buf.undostack().top().first_par == first_par
- && buf.undostack().top().end_par == end_par) {
- // No additonal undo recording needed -
- // effectively, we combine undo recordings to one.
- return;
- }
- }
+ // create the position information of the Undo entry
+ Undo undo;
+ undo.kind = kind;
+ undo.cursor = StableDocumentIterator(cur);
+ undo.from = first_par;
+ undo.end = cur.lastpar() - last_par;
- // push and fill the Undo entry
- if (cur.inTexted()) {
- stack.push(Undo());
- LyXText * text = cur.text();
- int textnum;
- ParIterator pit = text2pit(buf, text, textnum);
- Undo & undo = stack.top();
- undo.kind = kind;
- undo.text = textnum;
- undo.index = pit.index();
- undo.first_par = first_par;
- undo.end_par = end_par;
- undo.cursor_par = cur.par();
- undo.cursor_pos = cur.pos();
- undo.math = false;
- //lyxerr << "undo record: " << stack.top() << std::endl;
+ // Undo::ATOMIC are always recorded (no overlapping there).
+ // As nobody wants all removed character appear one by one when undoing,
+ // we want combine 'similar' non-ATOMIC undo recordings to one.
+ if (!undo_finished
+ && kind != Undo::ATOMIC
+ && !stack.empty()
+ && stack.top().cursor.size() == undo.cursor.size()
+ && stack.top().kind == undo.kind
+ && stack.top().from == undo.from
+ && stack.top().end == undo.end)
+ return;
+ // fill in the real data to be saved
+ if (cur.inMathed()) {
+ // simply use the whole cell
+ undo.array = asString(cur.cell());
+ } else {
+ // some more effort needed here as 'the whole cell' of the
+ // main LyXText _is_ the whole document.
// record the relevant paragraphs
+ LyXText * text = cur.text();
+ BOOST_ASSERT(text);
ParagraphList & plist = text->paragraphs();
ParagraphList::iterator first = plist.begin();
advance(first, first_par);
ParagraphList::iterator last = plist.begin();
- advance(last, last_par);
-
- for (ParagraphList::iterator it = first; it != last; ++it)
- undo.pars.push_back(*it);
- undo.pars.push_back(*last);
- } else {
- BOOST_ASSERT(false); // not in mathed (yet)
- stack.push(Undo());
- Undo & undo = stack.top();
- undo.math = false;
+ advance(last, last_par + 1);
+ undo.pars = ParagraphList(first, last);
}
- // and make sure that next time, we should be combining if possible
+ // push the undo entry to undo stack
+ //lyxerr << "undo record: " << stack.top() << std::endl;
+ stack.push(undo);
+
+ // next time we'll try again to combine entries if possible
undo_finished = false;
}
-// returns false if no undo possible
-bool performUndoOrRedo(BufferView & bv, Undo const & undo)
+void performUndoOrRedo(BufferView & bv, Undo const & undo)
{
- Buffer & buf = *bv.buffer();
+ LCursor & cur = bv.cursor();
lyxerr << "undo, performing: " << undo << std::endl;
- ParIterator pit = num2pit(buf, undo.text);
- LyXText * text = pit.text(buf);
- ParagraphList & plist = text->paragraphs();
+ cur.setCursor(undo.cursor.asDocumentIterator(bv), false);
- // remove new stuff between first and last
- {
+ if (cur.inMathed()) {
+ // We stored the full cell here as there is not much to be
+ // gained by storing just 'a few' paragraphs (most if not
+ // all math inset cells have just one paragraph!)
+ asArray(undo.array, cur.cell());
+ } else {
+ // Some finer machinery is needed here.
+ LyXText * text = cur.text();
+ BOOST_ASSERT(text);
+ ParagraphList & plist = text->paragraphs();
+
+ // remove new stuff between first and last
ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par);
+ advance(first, undo.from);
ParagraphList::iterator last = plist.begin();
- advance(last, plist.size() - undo.end_par);
- plist.erase(first, ++last);
- }
+ advance(last, plist.size() - undo.end);
+ plist.erase(first, last);
- // re-insert old stuff instead
- if (plist.empty()) {
- plist.assign(undo.pars.begin(), undo.pars.end());
- } else {
- ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par);
+ // re-insert old stuff instead
+ first = plist.begin();
+ advance(first, undo.from);
plist.insert(first, undo.pars.begin(), undo.pars.end());
}
- // set cursor
- lyxerr << "undo, text: " << undo.text
- << " inset: " << pit.inset()
- << " index: " << undo.index
- << " par: " << undo.cursor_par
- << " pos: " << undo.cursor_pos
- << std::endl;
-
- text->updateCounters();
-
- // rebreak the entire lyxtext
-#warning needed?
- text->redoParagraphs(buf.paragraphs().begin(), buf.paragraphs().end());
- bv.cursor().resetAnchor();
-
- ParIterator pit2 = num2pit(buf, undo.text);
- advance(pit2, undo.cursor_par);
- bv.setCursor(pit2, undo.cursor_pos);
-
+ cur.resetAnchor();
finishUndo();
- return true;
}
bool textUndoOrRedo(BufferView & bv,
limited_stack<Undo> & stack, limited_stack<Undo> & otherstack)
{
- Buffer & buf = *bv.buffer();
if (stack.empty()) {
// nothing to do
finishUndo();
stack.pop();
finishUndo();
+ // this implements redo
if (!undo_frozen) {
otherstack.push(undo);
- otherstack.top().pars.clear();
- ParIterator pit = num2pit(buf, undo.text);
- ParagraphList & plist = pit.plist();
- if (undo.first_par + undo.end_par <= int(plist.size())) {
- ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par);
- ParagraphList::iterator last = plist.begin();
- advance(last, plist.size() - undo.end_par + 1);
- otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last);
+ DocumentIterator dit = undo.cursor.asDocumentIterator(bv);
+ if (dit.inMathed()) {
+ // not much to be done
+ } else {
+ otherstack.top().pars.clear();
+ LyXText * text = dit.text();
+ BOOST_ASSERT(text);
+ ParagraphList & plist = text->paragraphs();
+ if (undo.from + undo.end <= int(plist.size())) {
+ ParagraphList::iterator first = plist.begin();
+ advance(first, undo.from);
+ ParagraphList::iterator last = plist.begin();
+ advance(last, plist.size() - undo.end);
+ otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last);
+ }
}
- otherstack.top().cursor_pos = bv.cursor().pos();
- otherstack.top().cursor_par = bv.cursor().par();
- lyxerr << " undo other: " << otherstack.top() << std::endl;
+ otherstack.top().cursor = bv.cursor();
+ //lyxerr << " undo other: " << otherstack.top() << std::endl;
}
- freezeUndo();
- bool const ret = performUndoOrRedo(bv, undo);
- unFreezeUndo();
- return ret;
-}
-
-} // namespace anon
-
-
-void freezeUndo()
-{
- // this is dangerous and for internal use only
undo_frozen = true;
-}
-
-
-void unFreezeUndo()
-{
- // this is dangerous and for internal use only
+ performUndoOrRedo(bv, undo);
undo_frozen = false;
+ return true;
}
+} // namespace anon
+
void finishUndo()
{
Buffer * buf = cur.bv().buffer();
recordUndo(kind, cur, first, last, buf->undostack());
buf->redostack().clear();
+ //lyxerr << "undostack:\n";
+ //for (size_t i = 0, n = buf->undostack().size(); i != n && i < 6; ++i)
+ // lyxerr << " " << i << ": " << buf->undostack()[i] << std::endl;
}
#ifndef UNDO_H
#define UNDO_H
+#include "dociterator.h"
#include "ParagraphList_fwd.h"
+
#include "support/types.h"
#include <string>
/// which kind of operation are we recording for?
undo_kind kind;
- /// hosting LyXText counted from buffer begin
- int text;
- /// cell in a tabular or similar
- int index;
- /// offset to the first paragraph in the paragraph list
- int first_par;
- /// offset to the last paragraph from the end of paragraph list
- int end_par;
- /// offset to the first paragraph in the paragraph list
- int cursor_par;
- /// the position of the cursor in the hosting paragraph
- int cursor_pos;
+ /// the position of the cursor
+ StableDocumentIterator cursor;
+ /// counted from begin of buffer
+ lyx::paroffset_type from;
+ /// complement to end of this cell
+ lyx::paroffset_type end;
/// the contents of the saved paragraphs (for texted)
ParagraphList pars;
/// the contents of the saved matharray (for mathed)
std::string array;
- /// in mathed?
- bool math;
};
/// makes sure the next operation will be stored
void finishUndo();
-/// whilst undo is frozen, no actions gets added to the undo stack
-void freezeUndo();
-
-/// track undos again
-void unFreezeUndo();
-
/**
* Record undo information - call with the current cursor and the 'other